Title in docs in IDE (#1904)

This commit is contained in:
Maciej Mikołajek 2021-08-17 01:40:58 +02:00 committed by GitHub
parent 98eab2873e
commit 6652a00241
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 144 additions and 132 deletions

View File

@ -17,6 +17,8 @@
propagate error information
([#1941](https://github.com/enso-org/enso/pull/1941)).
- Fixed inaproppriate parsing of code blocks in documentation.
- Documentation in IDE now shows names of suggestions
([#1904](https://github.com/enso-org/enso/pull/1904)).
## Tooling

View File

@ -162,7 +162,7 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
selfType = selfType.toString,
returnType = buildReturnType(returnTypeDef),
documentation = doc,
documentationHtml = doc.map(DocParserWrapper.runOnPureDoc),
documentationHtml = doc.map(DocParserWrapper.runOnPureDoc(_, name.name)),
reexport = None
)
}
@ -216,10 +216,11 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
doc: Option[String]
): Suggestion =
Suggestion.Module(
module = module.toString,
documentation = doc,
documentationHtml = doc.map(DocParserWrapper.runOnPureDoc),
reexport = None
module = module.toString,
documentation = doc,
documentationHtml =
doc.map(DocParserWrapper.runOnPureDoc(_, module.toString)),
reexport = None
)
/** Build suggestions for an atom definition. */
@ -247,7 +248,7 @@ final class SuggestionBuilder[A: IndexedSource](val source: A) {
arguments = arguments.map(buildArgument),
returnType = module.createChild(name).toString,
documentation = doc,
documentationHtml = doc.map(DocParserWrapper.runOnPureDoc),
documentationHtml = doc.map(DocParserWrapper.runOnPureDoc(_, name)),
reexport = None
)

View File

@ -33,18 +33,15 @@ class SuggestionBuilderTest extends CompilerTest {
private val moduleDoc = "Module doc"
private val DoccedModuleNode = Tree.Node(
Suggestion.Module(
module = Module.toString,
documentation = Some(" " + moduleDoc),
documentationHtml = Some(DocParserWrapper.runOnPureDoc(moduleDoc)),
reexport = None
module = Module.toString,
documentation = Some(" " + moduleDoc),
documentationHtml =
Some(DocParserWrapper.runOnPureDoc(moduleDoc, Module.toString)),
reexport = None
),
Vector()
)
private def htmlDoc(inner: String): String = {
"<html><body><div class=\"doc\" style=\"font-size: 13px;\"><div><div class=\"\">" + inner + "</div></div></div></body></html>"
}
"SuggestionBuilder" should {
"build method without explicit arguments" in {
@ -96,10 +93,11 @@ class SuggestionBuilderTest extends CompilerTest {
arguments = Seq(
Suggestion.Argument("this", "Unnamed.Test", false, false, None)
),
selfType = "Unnamed.Test",
returnType = SuggestionBuilder.Any,
documentation = Some(" The foo"),
documentationHtml = Some(htmlDoc("<p>The foo</p>"))
selfType = "Unnamed.Test",
returnType = SuggestionBuilder.Any,
documentation = Some(" The foo"),
documentationHtml =
Some(DocParserWrapper.runOnPureDoc(" The foo", "foo"))
),
Vector()
)
@ -129,10 +127,11 @@ class SuggestionBuilderTest extends CompilerTest {
arguments = Seq(
Suggestion.Argument("this", "Unnamed.Test", false, false, None)
),
selfType = "Unnamed.Test",
returnType = "Number",
documentation = Some(" The foo"),
documentationHtml = Some(htmlDoc("<p>The foo</p>"))
selfType = "Unnamed.Test",
returnType = "Number",
documentation = Some(" The foo"),
documentationHtml =
Some(DocParserWrapper.runOnPureDoc(" The foo", "foo"))
),
Vector()
)
@ -460,10 +459,11 @@ class SuggestionBuilderTest extends CompilerTest {
Suggestion.Argument("a", "Number", false, false, None),
Suggestion.Argument("b", "Number", false, false, None)
),
selfType = "Unnamed.Test.MyAtom",
returnType = "Number",
documentation = Some(" My bar"),
documentationHtml = Some(htmlDoc("<p>My bar</p>"))
selfType = "Unnamed.Test.MyAtom",
returnType = "Number",
documentation = Some(" My bar"),
documentationHtml =
Some(DocParserWrapper.runOnPureDoc(" My bar", "bar"))
),
Vector()
)
@ -1172,9 +1172,10 @@ class SuggestionBuilderTest extends CompilerTest {
Suggestion
.Argument("b", SuggestionBuilder.Any, false, false, None)
),
returnType = "Unnamed.Test.MyType",
documentation = Some(" My sweet type"),
documentationHtml = Some(htmlDoc("<p>My sweet type</p>"))
returnType = "Unnamed.Test.MyType",
documentation = Some(" My sweet type"),
documentationHtml =
Some(DocParserWrapper.runOnPureDoc(" My sweet type", "MyType"))
),
Vector()
),
@ -1292,13 +1293,15 @@ class SuggestionBuilderTest extends CompilerTest {
DoccedModuleNode,
Tree.Node(
Suggestion.Atom(
externalId = None,
module = "Unnamed.Test",
name = "Nothing",
arguments = Seq(),
returnType = "Unnamed.Test.Nothing",
documentation = Some(" Nothing here"),
documentationHtml = Some(htmlDoc("<p>Nothing here</p>"))
externalId = None,
module = "Unnamed.Test",
name = "Nothing",
arguments = Seq(),
returnType = "Unnamed.Test.Nothing",
documentation = Some(" Nothing here"),
documentationHtml = Some(
DocParserWrapper.runOnPureDoc(" Nothing here", "Nothing")
)
),
Vector()
),
@ -1311,9 +1314,11 @@ class SuggestionBuilderTest extends CompilerTest {
Suggestion
.Argument("a", SuggestionBuilder.Any, false, false, None)
),
returnType = "Unnamed.Test.Just",
documentation = Some(" Something there"),
documentationHtml = Some(htmlDoc("<p>Something there</p>"))
returnType = "Unnamed.Test.Just",
documentation = Some(" Something there"),
documentationHtml = Some(
DocParserWrapper.runOnPureDoc(" Something there", "Just")
)
),
Vector()
),
@ -1357,25 +1362,27 @@ class SuggestionBuilderTest extends CompilerTest {
ModuleNode,
Tree.Node(
Suggestion.Atom(
externalId = None,
module = "Unnamed.Test",
name = "Cons",
arguments = Seq(),
returnType = "Unnamed.Test.Cons",
documentation = Some(" And more"),
documentationHtml = Some(htmlDoc("<p>And more</p>"))
externalId = None,
module = "Unnamed.Test",
name = "Cons",
arguments = Seq(),
returnType = "Unnamed.Test.Cons",
documentation = Some(" And more"),
documentationHtml =
Some(DocParserWrapper.runOnPureDoc(" And more", "Cons"))
),
Vector()
),
Tree.Node(
Suggestion.Atom(
externalId = None,
module = "Unnamed.Test",
name = "Nil",
arguments = Seq(),
returnType = "Unnamed.Test.Nil",
documentation = Some(" End"),
documentationHtml = Some(htmlDoc("<p>End</p>"))
externalId = None,
module = "Unnamed.Test",
name = "Nil",
arguments = Seq(),
returnType = "Unnamed.Test.Nil",
documentation = Some(" End"),
documentationHtml =
Some(DocParserWrapper.runOnPureDoc(" End", "Nil"))
),
Vector()
),
@ -1388,10 +1395,11 @@ class SuggestionBuilderTest extends CompilerTest {
Suggestion
.Argument("this", "Unnamed.Test.Cons", false, false, None)
),
selfType = "Unnamed.Test.Cons",
returnType = "List",
documentation = Some(" a method"),
documentationHtml = Some(htmlDoc("<p>a method</p>"))
selfType = "Unnamed.Test.Cons",
returnType = "List",
documentation = Some(" a method"),
documentationHtml =
Some(DocParserWrapper.runOnPureDoc(" a method", "empty"))
),
Vector()
),
@ -1404,10 +1412,11 @@ class SuggestionBuilderTest extends CompilerTest {
Suggestion
.Argument("this", "Unnamed.Test.Nil", false, false, None)
),
selfType = "Unnamed.Test.Nil",
returnType = "List",
documentation = Some(" a method"),
documentationHtml = Some(htmlDoc("<p>a method</p>"))
selfType = "Unnamed.Test.Nil",
returnType = "List",
documentation = Some(" a method"),
documentationHtml =
Some(DocParserWrapper.runOnPureDoc(" a method", "empty"))
),
Vector()
)
@ -1897,7 +1906,7 @@ class SuggestionBuilderTest extends CompilerTest {
"Unnamed.Test",
Some(" Module doc"),
Some(
"<html><body><div class=\"doc\" style=\"font-size: 13px;\"><div><div class=\"\"><p>Module doc</p></div></div></div></body></html>"
DocParserWrapper.runOnPureDoc(" Module doc", "Unnamed.Test")
),
None
),
@ -1911,10 +1920,11 @@ class SuggestionBuilderTest extends CompilerTest {
arguments = Seq(
Suggestion.Argument("this", "Unnamed.Test", false, false, None)
),
selfType = "Unnamed.Test",
returnType = SuggestionBuilder.Any,
documentation = Some(" The foo"),
documentationHtml = Some(htmlDoc("<p>The foo</p>"))
selfType = "Unnamed.Test",
returnType = SuggestionBuilder.Any,
documentation = Some(" The foo"),
documentationHtml =
Some(DocParserWrapper.runOnPureDoc(" The foo", "foo"))
),
Vector()
)

View File

@ -6,6 +6,7 @@ import org.enso.compiler.core.IR
import org.enso.compiler.pass.resolve.GenerateDocumentation
import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager}
import org.enso.compiler.test.CompilerTest
import org.enso.docs.generator.DocParserWrapper
import org.scalatest.Inside
import pprint.pprintln
@ -79,24 +80,6 @@ class GenerateDocumentationTest extends CompilerTest with Inside {
meta.get.documentation
}
/** Creates full html doc generator output from the `inner` string, the one
* that will only change during the test.
*/
def unfoldedDocumentationForAssertion(inner: String): String =
s"""<html>
| <body>
| <div class="doc" style="font-size: 13px;">
| <div>
| <div class="">
| $inner
| </div>
| </div>
| </div>
| </body>
|</html>""".stripMargin
.replaceAll(System.lineSeparator(), "")
.replaceAll(">[ ]+<", "><")
// === The Tests ============================================================
"Documentation comments in the top scope" should {
@ -117,11 +100,11 @@ class GenerateDocumentationTest extends CompilerTest with Inside {
ir.bindings(0) shouldBe an[IR.Module.Scope.Definition.Atom]
ir.bindings(1) shouldBe an[IR.Module.Scope.Definition.Method]
getDoc(ir.bindings(0)) shouldEqual unfoldedDocumentationForAssertion(
"<p>This is doc for My<div class=\"Unclosed\"><i>Atom</i></div></p>"
getDoc(ir.bindings(0)) shouldEqual DocParserWrapper.runOnPureDoc(
" This is doc for My_Atom"
)
getDoc(ir.bindings(1)) shouldEqual unfoldedDocumentationForAssertion(
"<p>This is doc for my<div class=\"Unclosed\"><i>method</i></div></p>"
getDoc(ir.bindings(1)) shouldEqual DocParserWrapper.runOnPureDoc(
" This is doc for my_method"
)
}
}
@ -148,11 +131,11 @@ class GenerateDocumentationTest extends CompilerTest with Inside {
pprintln(body)
body.expressions.length shouldEqual 1
getDoc(body.expressions(0)) shouldEqual unfoldedDocumentationForAssertion(
"<p>Do thing</p>"
getDoc(body.expressions(0)) shouldEqual DocParserWrapper.runOnPureDoc(
" Do thing"
)
getDoc(body.returnValue) shouldEqual unfoldedDocumentationForAssertion(
"<p>Do another thing</p>"
getDoc(body.returnValue) shouldEqual DocParserWrapper.runOnPureDoc(
" Do another thing"
)
}
@ -178,11 +161,11 @@ class GenerateDocumentationTest extends CompilerTest with Inside {
body.expressions.length shouldEqual 2
body.expressions(0) shouldBe an[IR.Application.Operator.Binary]
getDoc(body.expressions(0)) shouldEqual unfoldedDocumentationForAssertion(
"<p>Id</p>"
getDoc(body.expressions(0)) shouldEqual DocParserWrapper.runOnPureDoc(
" Id"
)
getDoc(body.returnValue) shouldEqual unfoldedDocumentationForAssertion(
"<p>Return thing</p>"
getDoc(body.returnValue) shouldEqual DocParserWrapper.runOnPureDoc(
" Return thing"
)
}
}
@ -208,31 +191,30 @@ class GenerateDocumentationTest extends CompilerTest with Inside {
| ## the return
| 0
|""".stripMargin.preprocessModule.resolve
// pprintln(ir)
val tp = ir.bindings(0).asInstanceOf[IR.Module.Scope.Definition.Type]
getDoc(tp) shouldEqual unfoldedDocumentationForAssertion(
"<p>the type Foo</p>"
getDoc(tp) shouldEqual DocParserWrapper.runOnPureDoc(
" the type Foo"
)
val t1 = tp.body(0)
getDoc(t1) shouldEqual unfoldedDocumentationForAssertion(
"<p>the constructor Bar</p>"
getDoc(t1) shouldEqual DocParserWrapper.runOnPureDoc(
" the constructor Bar"
)
val t2 = tp.body(1)
getDoc(t2) shouldEqual unfoldedDocumentationForAssertion(
"<p>the included Unit</p>"
getDoc(t2) shouldEqual DocParserWrapper.runOnPureDoc(
" the included Unit"
)
val method = tp.body(2).asInstanceOf[IR.Function.Binding]
getDoc(method) shouldEqual unfoldedDocumentationForAssertion(
"<p>a method</p>"
getDoc(method) shouldEqual DocParserWrapper.runOnPureDoc(
" a method"
)
val block = method.body.asInstanceOf[IR.Expression.Block]
getDoc(
block.expressions(0)
) shouldEqual unfoldedDocumentationForAssertion(
"<p>a statement</p>"
) shouldEqual DocParserWrapper.runOnPureDoc(
" a statement"
)
getDoc(block.returnValue) shouldEqual unfoldedDocumentationForAssertion(
"<p>the return</p>"
getDoc(block.returnValue) shouldEqual DocParserWrapper.runOnPureDoc(
" the return"
)
}
}

View File

@ -21,9 +21,9 @@ object DocParserWrapper {
/** Generates HTML from Documentation string.
*/
def runOnPureDoc(comment: String): String = {
def runOnPureDoc(comment: String, title: String = ""): String = {
val doc = DocParser.runMatched(comment)
val html = DocParserHTMLGenerator.generateHTMLPureDoc(doc)
val html = DocParserHTMLGenerator.generateHTMLPureDoc(doc, title)
html
}

View File

@ -19,7 +19,7 @@ object DocsGenerator {
/** Generates list of HTML docs from given doc comments.
*/
def generate(comments: List[String]): List[String] = {
comments.map(runOnPureDoc)
comments.map(c => runOnPureDoc(c))
}
/** Connects HTML documentation with it's AST element.

View File

@ -39,6 +39,19 @@ final case class Doc(
val html: Doc.HTML = Seq(
HTML.div(tags.html)(synopsis.html)(body.html)
)
def htmlWithTitle(title: String): Doc.HTML = {
if (title != "") {
Seq(
HTML.div(HTML.`class` := "doc-title-container")(
HTML.div(HTML.`class` := "doc-title-name")(title),
tags.html
)(synopsis.html)(body.html)
)
} else {
Seq(HTML.div(tags.html)(synopsis.html)(body.html))
}
}
}
object Doc {
@ -182,7 +195,7 @@ object Doc {
val htmlIdCode = HTML.`id` := uniqueIDCode
val htmlIdBtn = HTML.`id` := uniqueIDBtn
val firstIndent = elems.head.indent
val elemsHTML = elems.toList.map(elem => elem.htmlOffset(firstIndent))
val elemsHTML = elems.toList.map(_.htmlOffset(firstIndent))
val copyClass = HTML.`class` := "doc-copy-btn flex"
val codeClass = HTML.`class` := "doc-code-container"
val copyBtn = HTML.button(htmlIdBtn)(copyClass)("Copy")
@ -441,7 +454,7 @@ object Doc {
val repr: Repr.Builder = R + indent + elemsRepr
override def htmlCls(): generic.AttrPair[Builder, String] = {
HTML.`class` := ""
HTML.`class` := "raw"
}
override val html: HTML = Seq(HTML.p(elems.map(_.html)))
@ -471,7 +484,7 @@ object Doc {
val repr: Repr.Builder = R + elems.head + elems.tail.map(R + newLn + _)
val html: HTML = {
Seq(
HTML.div(HTML.`class` := "")(
HTML.div(HTML.`class` := "synopsis")(
elems.toList.map(_.html)
)
)
@ -504,7 +517,7 @@ object Doc {
R + newLn + _
)
val html: HTML = Seq(
HTML.div(elems.toList.map(_.html))
HTML.div(HTML.`class` := "body")(elems.toList.map(_.html))
)
}
@ -551,16 +564,17 @@ object Doc {
case _ => R + indent + name + details
}
val html: HTML = {
val htmlClass = HTML.`class` := "tag"
typ match {
case Tag.Unrecognized =>
Seq(
HTML.p(HTML.`class` := "tag")(
HTML.p(htmlClass)(
HTML.span(HTML.`class` := cName)(details.html)
)
)
case Tag.Type.TextOnly =>
Seq(
HTML.p(HTML.`class` := "tag")(
HTML.p(htmlClass)(
HTML.span(HTML.`class` := cName)("TEXT ONLY")(
details.html
)
@ -568,7 +582,7 @@ object Doc {
)
case _ =>
Seq(
HTML.p(HTML.`class` := "tag")(
HTML.p(htmlClass)(
HTML.span(HTML.`class` := cName)(name)(details.html)
)
)

View File

@ -855,14 +855,21 @@ case class DocParserDef() extends Parser[Doc] {
var current = section.pop().get
if (current.indent > baseIndent && current.isInstanceOf[Section.Raw]) {
var stackOfCodeSections: List[Section] = List[Section]()
while (section.stack.nonEmpty && current.indent > baseIndent) {
while (
section.stack.nonEmpty && current.indent > baseIndent && current
.isInstanceOf[Section.Raw] && section.stack.head
.isInstanceOf[Section.Raw]
) {
stackOfCodeSections = stackOfCodeSections :+ current
current = section.pop().get
if (section.stack.head.isInstanceOf[Section.Raw]) {
current = section.pop().get
}
}
stackOfCodeSections = stackOfCodeSections :+ current
val codeLines = stackOfCodeSections.map(s =>
Doc.Elem.CodeBlock.Line(s.indent, s.repr.build().trim)
)
val codeLines = stackOfCodeSections.flatMap(s => {
val inLines = s.repr.build().split("\n").map(_.trim)
inLines.map(Doc.Elem.CodeBlock.Line(s.indent, _))
})
if (codeLines.nonEmpty) {
val l1CodeLines = List1(codeLines.head, codeLines.tail)
val codeBlock = Doc.Elem.CodeBlock(l1CodeLines)

View File

@ -69,13 +69,11 @@ object DocParserHTMLGenerator {
* @param doc - Doc from Doc Parser
* @return - HTML Code from Doc
*/
def generateHTMLPureDoc(doc: Doc): String =
def generateHTMLPureDoc(doc: Doc, title: String = ""): String =
HTML
.html(
HTML.body(
HTML.div(HTML.`class` := "doc")(HTML.style := "font-size: 13px;")(
doc.html
)
HTML.div(HTML.`class` := "enso docs")(doc.htmlWithTitle(title))
)
)
.toString()

View File

@ -949,10 +949,8 @@ class DocParserTests extends AnyFlatSpec with Matchers {
" file in the project directory.",
Newline,
CodeBlock(
CodeBlock.Line(
6,
"import Standard.Base.System.File\n import Standard.Examples"
),
CodeBlock.Line(6, "import Standard.Base.System.File"),
CodeBlock.Line(6, "import Standard.Examples"),
CodeBlock.Line(6, "example_new = File.new Examples.csv_path")
)
)