diff --git a/HISTORY_v2.md b/HISTORY_v2.md index 93bddc3fe..e772f00a8 100644 --- a/HISTORY_v2.md +++ b/HISTORY_v2.md @@ -1,3 +1,7 @@ +# v2.11.4 + +Fixed a bug where comments from outside docstrings would be incorrectly duplicated inside the docstring if the vertical length of the docstring changed during formatting. (#1223, #1229) + # v2.11.3 Fixed a bug where Julia code in docstrings would be formatted incorrectly if the code itself contained characters that had to be escaped. (#1224, #1228) diff --git a/Project.toml b/Project.toml index f37ef4f97..5a8c9d601 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "JuliaFormatter" uuid = "98e50ef6-434e-11e9-1051-2b60c6c9e899" -version = "2.11.3" +version = "2.11.4" authors = ["Dominique Luna and contributors"] [workspace] diff --git a/src/styles/default/pretty.jl b/src/styles/default/pretty.jl index 812df8012..7cb2208a3 100644 --- a/src/styles/default/pretty.jl +++ b/src/styles/default/pretty.jl @@ -896,17 +896,23 @@ function p_stringh( end for (i, l) in enumerate(lines) - ln = startline + i - 1 + # When format_docstrings is enabled, the formatted docstring may have more lines + # than the original (e.g. blank lines added around code fences). Clamping prevents + # add_node! from checking source lines outside the docstring for comments. See + # https://github.com/JuliaEditorSupport/JuliaFormatter.jl/issues/1223 + ln = min(startline + i - 1, endline) l = i == 1 ? l : l[sidx:end] n = FST(LITERAL, ln, ln, sidx - 1, textwidth(l), l, (), AllowNest, 0, -1, nothing) - add_node!(t, n, s) + # override_join_lines_based_on_source ensures that the lines are always printed on + # separate lines rather than being joined, even if join_lines_based_on_source has + # been enabled by the user + add_node!(t, n, s; override_join_lines_based_on_source = true) end # we need to maintain the start and endlines of the original source t.startline = startline t.endline = endline - - t + return t end # GlobalRefDoc (docstring) diff --git a/test/options/format_docstrings.jl b/test/options/format_docstrings.jl index 01af8d928..44d9622be 100644 --- a/test/options/format_docstrings.jl +++ b/test/options/format_docstrings.jl @@ -1,227 +1,233 @@ module OptionsFormatDocstringsTests -using JuliaFormatter.Internal: test_format +using JuliaFormatter.Internal: test_format, ALL_STYLES using Test @testset "format_docstrings" begin @testset "basic" begin - normalized = """ - \""" - doc - \""" - function f() - 20 - end""" - - str = """ - \"""doc - \""" - function f() - 20 - end""" - test_format(str, str) - test_format(str, normalized; format_docstrings = true) + for style in ALL_STYLES + normalized = """ + \""" + doc + \""" + function f() + return 20 + end""" - str = """ - \""" - doc\""" - function f() - 20 - end""" - test_format(str, str) - test_format(str, normalized; format_docstrings = true) + str = """ + \"""doc + \""" + function f() + return 20 + end""" + test_format(str, str, style) + test_format(str, normalized, style; format_docstrings = true) - str = """ - \"""doc\""" - function f() - 20 - end""" - test_format(str, str) - test_format(str, normalized; format_docstrings = true) + str = """ + \""" + doc\""" + function f() + return 20 + end""" + test_format(str, str, style) + test_format(str, normalized, style; format_docstrings = true) - str = """ - "doc - " - function f() - 20 - end""" - test_format(str, str) - test_format(str, normalized; format_docstrings = true) + str = """ + \"""doc\""" + function f() + return 20 + end""" + test_format(str, str, style) + test_format(str, normalized, style; format_docstrings = true) - str = """ - " - doc" - function f() - 20 - end""" - test_format(str, str) - test_format(str, normalized; format_docstrings = true) + str = """ + "doc + " + function f() + return 20 + end""" + test_format(str, str, style) + test_format(str, normalized, style; format_docstrings = true) - str = """ - "doc" - function f() - 20 - end""" - test_format(str, str) - test_format(str, normalized; format_docstrings = true) + str = """ + " + doc" + function f() + return 20 + end""" + test_format(str, str, style) + test_format(str, normalized, style; format_docstrings = true) - # test aligning to function identation - str_ = """ + str = """ "doc" - function f() - 20 - end""" - str = """ - "doc" - function f() - 20 - end""" - test_format(str_, str) - test_format(str_, normalized; format_docstrings = true) - - str = """\""" - doc for Foo - \""" - Foo""" - test_format(str, str) + function f() + return 20 + end""" + test_format(str, str, style) + test_format(str, normalized, style; format_docstrings = true) + + # test aligning to function identation + str_ = """ + "doc" + function f() + return 20 + end""" + str = """ + "doc" + function f() + return 20 + end""" + test_format(str_, str, style) + test_format(str_, normalized, style; format_docstrings = true) + + str = """\""" + doc for Foo + \""" + Foo""" + test_format(str, str, style) - str = """ - \""" - doc - \""" - function f() # comment - 20 - end""" - test_format(str, str) - test_format(str, str; format_docstrings = true) + str = """ + \""" + doc + \""" + function f() # comment + return 20 + end""" + test_format(str, str, style) + test_format(str, str, style; format_docstrings = true) + + # Issue 157 + str = raw""" + @doc \""" + foo() + \""" + foo() = bar()""" + test_format(str, str, style) + test_format(str, str, style; format_docstrings = true) - # Issue 157 - str = raw""" - @doc \""" - foo() - \""" - foo() = bar()""" - test_format(str, str) - test_format(str, str; format_docstrings = true) + str = raw""" + @doc docϵ\""" + foo() + \""" + foo() = bar()""" + test_format(str, str, style) + test_format(str, str, style; format_docstrings = true) - str = raw""" - @doc docϵ\""" - foo() - \""" - foo() = bar()""" - test_format(str, str) - test_format(str, str; format_docstrings = true) + str = raw"""@doc "doc for foo" foo""" + test_format(str, str, style) + test_format(str, str, style; format_docstrings = true) - str = raw"""@doc "doc for foo" foo""" - test_format(str, str) - test_format(str, str; format_docstrings = true) + str = raw"""@doc \"""doc for foo\""" foo""" + test_format(str, str, style) + test_format(str, str, style; format_docstrings = true) - str = raw"""@doc \"""doc for foo\""" foo""" - test_format(str, str) - test_format(str, str; format_docstrings = true) - - str = raw"""@doc doc\"""doc for foo\""" foo()""" - test_format(str, str) - test_format(str, str; format_docstrings = true) + str = raw"""@doc doc\"""doc for foo\""" foo()""" + test_format(str, str, style) + test_format(str, str, style; format_docstrings = true) - str = raw"""@doc foo""" - test_format(str, str) - test_format(str, str; format_docstrings = true) + str = raw"""@doc foo""" + test_format(str, str, style) + test_format(str, str, style; format_docstrings = true) - # issue 160 - str = raw""" - module MyModule + # issue 160 + str = raw""" + module MyModule - import Markdown: @doc_str + import Markdown: @doc_str - @doc doc\""" - foo() - \""" - foo() = bar() + @doc doc\""" + foo() + \""" + foo() = bar() - end # module""" - test_format(str, str) - test_format(str, str; format_docstrings = true) + end # module""" + test_format(str, str, style) + test_format(str, str, style; format_docstrings = true) + end end @testset "with code" begin - unformatted = """ - \""" - This is a docstring + for style in ALL_STYLES + unformatted = """ + \""" + This is a docstring - ```@example - a = 1 - b = 2 - a + b - ``` + ```@example + a = 1 + b = 2 + a + b + ``` - ```jldoctest - a = 1 - b = 2 - a + b + ```jldoctest + a = 1 + b = 2 + a + b - # output + # output - 3 - ``` + 3 + ``` - ```jldoctest - julia> a = 1 - 1 + ```jldoctest + julia> a = 1 + 1 - julia> b = 2; + julia> b = 2; - julia> a + b - 3 + julia> a + b + 3 - julia> function test(x) - x + 1 - x + 2 - end; - ``` - \""" - function test(x) x end""" + julia> function test(x) + x + 1 + return x + 2 + end; + ``` + \""" + function test(x) + return x + end""" - formatted = """ - \""" - This is a docstring + formatted = """ + \""" + This is a docstring - ```@example - a = 1 - b = 2 - a + b - ``` + ```@example + a = 1 + b = 2 + a + b + ``` - ```jldoctest - a = 1 - b = 2 - a + b + ```jldoctest + a = 1 + b = 2 + a + b - # output + # output - 3 - ``` + 3 + ``` - ```jldoctest - julia> a = 1 - 1 + ```jldoctest + julia> a = 1 + 1 - julia> b = 2; + julia> b = 2; - julia> a + b - 3 + julia> a + b + 3 - julia> function test(x) - x + 1 - x + 2 - end; + julia> function test(x) + x + 1 + return x + 2 + end; - ``` - \""" - function test(x) - x - end""" - test_format(unformatted, formatted; format_docstrings = true) + ``` + \""" + function test(x) + return x + end""" + test_format(unformatted, formatted, style; format_docstrings = true) + end end @testset "issue 602" begin @@ -389,6 +395,72 @@ using Test end end + @testset "1223 comments not duplicated into docstrings" begin + # Single code block + str = """ + \""" + a + ```julia + b + ``` + \""" + function f end + # comment + f() = 1 + """ + expected = """ + \""" + a + + ```julia + b + ``` + \""" + function f end + # comment + f() = 1 + """ + test_format(str, expected; format_docstrings = true) + + # Two code blocks + str = """ + \""" + a + ```julia + b + ``` + foo + ```julia + c + ``` + \""" + function f end + # comment + f() = 1 + """ + expected = """ + \""" + a + + ```julia + b + ``` + + foo + + ```julia + c + ``` + \""" + function f end + # comment + f() = 1 + """ + for style in ALL_STYLES + test_format(str, expected, style; format_docstrings = true) + end + end + @testset "1224 escape sequences" begin for escaped_julia_code in ( raw"@macro a.\$s", @@ -403,7 +475,9 @@ using Test \""" f """ - test_format(s, s; format_docstrings=true) + for style in ALL_STYLES + test_format(s, s, style; format_docstrings=true) + end end @testset "normalisation of triple quotes" begin @@ -426,8 +500,10 @@ using Test \""" f """ - test_format(s_, s; format_docstrings=true) - test_format(s, s; format_docstrings=true) + for style in ALL_STYLES + test_format(s_, s, style; format_docstrings=true) + test_format(s, s, style; format_docstrings=true) + end # However if the docstring is single quoted we need to normalise to `\"\"\"` # instead @@ -437,7 +513,9 @@ using Test ```\" f """ - test_format(s, s; format_docstrings=true, enforce_triplequoted_docstrings=false) + for style in ALL_STYLES + test_format(s, s, style; format_docstrings=true, enforce_triplequoted_docstrings=false) + end end end end