Documentation for functions and locals (#4029)

Add documentation for functions and locals to suggestions database.
This commit is contained in:
Dmitry Bushev 2023-01-10 19:59:53 +03:00 committed by GitHub
parent bc66753627
commit 2cd880f43d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 396 additions and 96 deletions

View File

@ -602,6 +602,15 @@ interface Function {
/** The scope where the function is defined. */
scope: SuggestionEntryScope;
/** The documentation string. */
documentation?: string;
/** The rendered HTML of the documentation string. */
documentationHtml?: string;
/** The documentation string divided into sections. */
documentationSections?: DocSection[];
}
interface Local {
@ -619,6 +628,15 @@ interface Local {
/** The scope where the value is defined. */
scope: SuggestionEntryScope;
/** The documentation string. */
documentation?: string;
/** The rendered HTML of the documentation string. */
documentationHtml?: string;
/** The documentation string divided into sections. */
documentationSections?: DocSection[];
}
```
@ -940,6 +958,11 @@ interface Modify {
*/
documentation?: FieldUpdate<String>;
/**
* New documentation sections.
*/
documentationSections?: FieldUpdate<DocSection[]>;
/**
* The scope to update.
*/

View File

@ -408,6 +408,7 @@ object SearchProtocol {
* @param returnType the return type to update
* @param documentation the documentation string to update
* @param documentationHtml the HTML documentation to update
* @param documentationSections the documentation sections to update
* @param scope the scope to update
* @param reexport the module reexporting the suggestion
*/
@ -420,6 +421,7 @@ object SearchProtocol {
returnType: Option[FieldUpdate[String]] = None,
documentation: Option[FieldUpdate[String]] = None,
documentationHtml: Option[FieldUpdate[String]] = None,
documentationSections: Option[FieldUpdate[Seq[DocSection]]] = None,
scope: Option[FieldUpdate[Suggestion.Scope]] = None,
reexport: Option[FieldUpdate[String]] = None
) extends SuggestionsDatabaseUpdate

View File

@ -591,8 +591,11 @@ final class SuggestionsHandler(
externalId = m.externalId.map(fieldUpdateOption),
arguments = m.arguments.map(_.map(toApiArgumentAction)),
returnType = m.returnType.map(fieldUpdate),
scope = m.scope.map(fieldUpdate),
documentation = m.documentation.map(fieldUpdateOption),
scope = m.scope.map(fieldUpdate)
documentationSections = m.documentation.map(
fieldUpdateMapOption(docSectionsBuilder.build)
)
)
}
}
@ -625,7 +628,7 @@ final class SuggestionsHandler(
/** Construct the field update object from an optional value.
*
* @param value the optional value
* @return the field update object representint the value update
* @return the field update object representing the value update
*/
private def fieldUpdateOption[A](value: Option[A]): FieldUpdate[A] =
value match {
@ -633,6 +636,20 @@ final class SuggestionsHandler(
case None => FieldUpdate(FieldAction.Remove, None)
}
/** Construct the field update object from an optional value.
*
* @param f the mapping function
* @param value the optional value
* @return the field update object representing the value update
*/
private def fieldUpdateMapOption[A, B](
f: A => B
)(value: Option[A]): FieldUpdate[B] =
value match {
case Some(value) => FieldUpdate(FieldAction.Set, Some(f(value)))
case None => FieldUpdate(FieldAction.Remove, None)
}
/** Construct the field update object from and update value.
*
* @param value the update value
@ -731,8 +748,13 @@ final class SuggestionsHandler(
val docSections = conversion.documentation.map(docSectionsBuilder.build)
conversion.copy(documentationSections = docSections)
case _: Suggestion.Function => suggestion
case _: Suggestion.Local => suggestion
case function: Suggestion.Function =>
val docSections = function.documentation.map(docSectionsBuilder.build)
function.copy(documentationSections = docSections)
case local: Suggestion.Local =>
val docSections = local.documentation.map(docSectionsBuilder.build)
local.copy(documentationSections = docSections)
}
}

View File

@ -87,7 +87,10 @@ object Suggestions {
),
returnType = "IO",
scope =
Suggestion.Scope(Suggestion.Position(1, 9), Suggestion.Position(1, 22))
Suggestion.Scope(Suggestion.Position(1, 9), Suggestion.Position(1, 22)),
documentation = Some("My Function"),
documentationHtml = None,
documentationSections = Some(docSectionsBuilder.build("My Function"))
)
val local: Suggestion.Local = Suggestion.Local(
@ -96,7 +99,8 @@ object Suggestions {
name = "x",
returnType = "Number",
scope =
Suggestion.Scope(Suggestion.Position(21, 0), Suggestion.Position(89, 0))
Suggestion.Scope(Suggestion.Position(21, 0), Suggestion.Position(89, 0)),
documentation = None
)
val methodOnAny: Suggestion.Method = Suggestion.Method(

View File

@ -307,7 +307,14 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"line" : 1,
"character" : 22
}
},
"documentation" : "My Function",
"documentationSections" : [
{
"type" : "paragraph",
"body" : "My Function"
}
]
}
}
],
@ -503,7 +510,14 @@ class SuggestionsHandlerEventsTest extends BaseServerTest with FlakySpec {
"line" : 1,
"character" : 22
}
},
"documentation" : "My Function",
"documentationSections" : [
{
"type" : "paragraph",
"body" : "My Function"
}
]
}
},
{

View File

@ -45,6 +45,7 @@ sealed trait Suggestion extends ToLogString {
def module: String
def name: String
def returnType: String
def documentation: Option[String]
}
object Suggestion {
@ -121,20 +122,6 @@ object Suggestion {
}
}
/** Documentation extractor */
object Documentation {
def apply(suggestion: Suggestion): Option[String] =
suggestion match {
case module: Module => module.documentation
case tpe: Type => tpe.documentation
case constructor: Constructor => constructor.documentation
case method: Method => method.documentation
case conv: Conversion => conv.documentation
case _: Function => None
case _: Local => None
}
}
/** An argument of an atom or a function.
*
* @param name the argument name
@ -185,6 +172,7 @@ object Suggestion {
* @param module the fully qualified module name
* @param documentation the documentation string
* @param documentationHtml the documentation rendered as HTML
* @param documentationSections the documentation parsed into sections
* @param reexport the module re-exporting this module
*/
case class Module(
@ -222,6 +210,7 @@ object Suggestion {
* @param parentType qualified name of the parent type
* @param documentation the documentation string
* @param documentationHtml the documentation rendered as HTML
* @param documentationSections the documentation parsed into sections
* @param reexport the module re-exporting this atom
*/
case class Type(
@ -261,6 +250,7 @@ object Suggestion {
* @param returnType the type of an atom
* @param documentation the documentation string
* @param documentationHtml the documentation rendered as HTML
* @param documentationSections the documentation parsed into sections
* @param reexport the module re-exporting this atom
*/
case class Constructor(
@ -300,6 +290,7 @@ object Suggestion {
* @param isStatic the flag indicating whether a method is static or instance
* @param documentation the documentation string
* @param documentationHtml the documentation rendered as HTML
* @param documentationSections the documentation parsed into sections
* @param reexport the module re-exporting this method
*/
case class Method(
@ -340,6 +331,7 @@ object Suggestion {
* @param returnType the return type of a conversion
* @param documentation the documentation string
* @param documentationHtml the documentation rendered as HTML
* @param documentationSections the documentation parsed into sections
* @param reexport the module re-exporting this conversion
*/
case class Conversion(
@ -378,6 +370,9 @@ object Suggestion {
* @param arguments the function arguments
* @param returnType the return type of a function
* @param scope the scope where the function is defined
* @param documentation the documentation string
* @param documentationHtml the documentation rendered as HTML
* @param documentationSections the documentation parsed into sections
*/
case class Function(
externalId: Option[ExternalId],
@ -385,7 +380,10 @@ object Suggestion {
name: String,
arguments: Seq[Argument],
returnType: String,
scope: Scope
scope: Scope,
documentation: Option[String],
documentationHtml: Option[String] = None,
documentationSections: Option[List[DocSection]] = None
) extends Suggestion
with ToLogString {
@ -397,7 +395,8 @@ object Suggestion {
s"name=$name," +
s"arguments=${arguments.map(_.toLogString(shouldMask))}," +
s"returnType=$returnType," +
s"scope=$scope" +
s"scope=$scope," +
s"documentation=$documentation" +
")"
}
@ -408,13 +407,19 @@ object Suggestion {
* @param name the name of a value
* @param returnType the type of a local value
* @param scope the scope where the value is defined
* @param documentation the documentation string
* @param documentationHtml the documentation rendered as HTML
* @param documentationSections the documentation parsed into sections
*/
case class Local(
externalId: Option[ExternalId],
module: String,
name: String,
returnType: String,
scope: Scope
scope: Scope,
documentation: Option[String],
documentationHtml: Option[String] = None,
documentationSections: Option[List[DocSection]] = None
) extends Suggestion {
/** @inheritdoc */
@ -424,7 +429,8 @@ object Suggestion {
s"module=$module," +
s"name=$name," +
s"returnType=$returnType," +
s"scope=$scope" +
s"scope=$scope," +
s"documentation=$documentation" +
s")"
}
}

View File

@ -360,13 +360,15 @@ class RuntimeStdlibTest
)
) =>
updates.toVector.foreach { update =>
val docstring = Suggestion.Documentation(update.suggestion)
docstring.foreach(
context.docsGenerator.generate(_, update.suggestion.name)
update.suggestion.documentation.foreach { documentation =>
context.docsGenerator.generate(
documentation,
update.suggestion.name
)
}
}
}
}
context.consumeOut shouldEqual List("Hello World!")
}

View File

@ -247,7 +247,8 @@ class RuntimeSuggestionUpdatesTest
Suggestion.Scope(
Suggestion.Position(2, 6),
Suggestion.Position(4, 16)
)
),
None
),
Api.SuggestionAction.Add()
),
@ -328,7 +329,8 @@ class RuntimeSuggestionUpdatesTest
Suggestion.Scope(
Suggestion.Position(2, 6),
Suggestion.Position(4, 16)
)
),
None
),
Api.SuggestionAction.Modify(scope =
Some(
@ -351,7 +353,8 @@ class RuntimeSuggestionUpdatesTest
Suggestion.Scope(
Suggestion.Position(2, 6),
Suggestion.Position(5, 18)
)
),
None
),
Api.SuggestionAction.Add()
),
@ -429,7 +432,8 @@ class RuntimeSuggestionUpdatesTest
Suggestion.Scope(
Suggestion.Position(2, 6),
Suggestion.Position(5, 18)
)
),
None
),
Api.SuggestionAction.Modify(scope =
Some(
@ -452,7 +456,8 @@ class RuntimeSuggestionUpdatesTest
Suggestion.Scope(
Suggestion.Position(2, 6),
Suggestion.Position(5, 18)
)
),
None
),
Api.SuggestionAction.Modify(
returnType = Some(ConstantsGen.NUMBER),
@ -540,7 +545,8 @@ class RuntimeSuggestionUpdatesTest
Suggestion.Scope(
Suggestion.Position(2, 6),
Suggestion.Position(6, 18)
)
),
None
),
Api.SuggestionAction.Modify(scope =
Some(
@ -563,7 +569,8 @@ class RuntimeSuggestionUpdatesTest
Suggestion.Scope(
Suggestion.Position(2, 6),
Suggestion.Position(6, 18)
)
),
None
),
Api.SuggestionAction.Modify(scope =
Some(
@ -808,7 +815,8 @@ class RuntimeSuggestionUpdatesTest
Suggestion.Scope(
Suggestion.Position(4, 6),
Suggestion.Position(8, 11)
)
),
None
),
Api.SuggestionAction.Add()
),

View File

@ -165,6 +165,7 @@ final class SuggestionBuilder[A: IndexedSource](
name,
args,
scope.location.get,
doc,
typeSignature
)
val subforest = go(
@ -181,6 +182,7 @@ final class SuggestionBuilder[A: IndexedSource](
module,
name.name,
scope.location.get,
doc,
typeSignature
)
val subforest = go(
@ -264,6 +266,7 @@ final class SuggestionBuilder[A: IndexedSource](
name: IR.Name,
args: Seq[IR.DefinitionArgument],
location: Location,
doc: Option[String],
typeSignature: Option[TypeSignatures.Metadata]
): Suggestion.Function = {
val typeSig = buildTypeSignatureFromMetadata(typeSignature)
@ -275,7 +278,8 @@ final class SuggestionBuilder[A: IndexedSource](
name = name.name,
arguments = methodArgs,
returnType = buildReturnType(returnTypeDef),
scope = buildScope(location)
scope = buildScope(location),
documentation = doc
)
}
@ -285,16 +289,18 @@ final class SuggestionBuilder[A: IndexedSource](
module: QualifiedName,
name: String,
location: Location,
doc: Option[String],
typeSignature: Option[TypeSignatures.Metadata]
): Suggestion.Local = {
val typeSig = buildTypeSignatureFromMetadata(typeSignature)
val (_, returnTypeDef) = buildFunctionArguments(Seq(), typeSig)
Suggestion.Local(
externalId,
module.toString,
name,
buildReturnType(returnTypeDef),
buildScope(location)
externalId = externalId,
module = module.toString,
name = name,
returnType = buildReturnType(returnTypeDef),
scope = buildScope(location),
documentation = doc
)
}

View File

@ -222,6 +222,9 @@ object SuggestionDiff {
if (e1.scope != e2.scope) {
op = op.copy(scope = Some(e2.scope))
}
if (e1.documentation != e2.documentation) {
op = op.copy(documentation = Some(e2.documentation))
}
Api.SuggestionUpdate(e1, op)
}
@ -239,6 +242,9 @@ object SuggestionDiff {
if (e1.scope != e2.scope) {
op = op.copy(scope = Some(e2.scope))
}
if (e1.documentation != e2.documentation) {
op = op.copy(documentation = Some(e2.documentation))
}
Api.SuggestionUpdate(e1, op)
}
}

View File

@ -317,7 +317,11 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
"x",
"Number",
Suggestion
.Scope(Suggestion.Position(0, 9), Suggestion.Position(4, 9))
.Scope(
Suggestion.Position(0, 9),
Suggestion.Position(4, 9)
),
None
),
Vector()
),
@ -328,7 +332,11 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
"y",
SuggestionBuilder.Any,
Suggestion
.Scope(Suggestion.Position(0, 9), Suggestion.Position(4, 9))
.Scope(
Suggestion.Position(0, 9),
Suggestion.Position(4, 9)
),
None
),
Vector()
)
@ -939,7 +947,8 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(0, 6),
Suggestion.Position(2, 10)
)
),
None
),
Vector()
)
@ -988,7 +997,8 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(0, 6),
Suggestion.Position(4, 10)
)
),
documentation = None
),
Vector(
Tree.Node(
@ -1000,7 +1010,8 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(1, 11),
Suggestion.Position(3, 9)
)
),
documentation = None
),
Vector()
)
@ -1049,7 +1060,8 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(0, 6),
Suggestion.Position(3, 10)
)
),
documentation = None
),
Vector()
)
@ -1118,7 +1130,63 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(2, 6),
Suggestion.Position(5, 10)
),
documentation = None
),
Vector()
)
)
)
)
)
}
"build function with documentation" in {
val code =
"""main =
| ## Foo documentation.
| foo a = a + 1
| foo 42
|""".stripMargin
val module = code.preprocessModule
build(code, module) shouldEqual Tree.Root(
Vector(
ModuleNode,
Tree.Node(
Suggestion.Method(
externalId = None,
module = "Unnamed.Test",
name = "main",
arguments = Seq(),
selfType = "Unnamed.Test",
returnType = SuggestionBuilder.Any,
isStatic = true,
documentation = None
),
Vector(
Tree.Node(
Suggestion.Function(
externalId = None,
module = "Unnamed.Test",
name = "foo",
arguments = Seq(
Suggestion
.Argument(
"a",
SuggestionBuilder.Any,
false,
false,
None
)
),
returnType = SuggestionBuilder.Any,
scope = Suggestion.Scope(
Suggestion.Position(0, 6),
Suggestion.Position(3, 10)
),
documentation = Some(" Foo documentation.")
),
Vector()
)
@ -1161,7 +1229,8 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(0, 6),
Suggestion.Position(2, 7)
)
),
documentation = None
),
Vector()
)
@ -1206,7 +1275,8 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(0, 6),
Suggestion.Position(4, 7)
)
),
documentation = None
),
Vector(
Tree.Node(
@ -1218,7 +1288,8 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(1, 9),
Suggestion.Position(3, 9)
)
),
documentation = None
),
Vector()
)
@ -1264,7 +1335,8 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(0, 6),
Suggestion.Position(3, 7)
)
),
documentation = None
),
Vector()
)
@ -1322,7 +1394,53 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(2, 6),
Suggestion.Position(5, 7)
),
documentation = None
),
Vector()
)
)
)
)
)
}
"build local with documentation" in {
val code =
"""main =
| ## This is foo.
| foo = 42
| foo
|""".stripMargin
val module = code.preprocessModule
build(code, module) shouldEqual Tree.Root(
Vector(
ModuleNode,
Tree.Node(
Suggestion.Method(
externalId = None,
module = "Unnamed.Test",
name = "main",
arguments = Seq(),
selfType = "Unnamed.Test",
returnType = SuggestionBuilder.Any,
isStatic = true,
documentation = None
),
Vector(
Tree.Node(
Suggestion.Local(
externalId = None,
module = "Unnamed.Test",
name = "foo",
returnType = SuggestionBuilder.Any,
scope = Suggestion.Scope(
Suggestion.Position(0, 6),
Suggestion.Position(3, 7)
),
documentation = Some(" This is foo.")
),
Vector()
)
@ -2187,7 +2305,8 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(0, 6),
Suggestion.Position(2, 28)
)
),
documentation = None
),
Vector()
)
@ -2236,7 +2355,8 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers {
scope = Suggestion.Scope(
Suggestion.Position(0, 6),
Suggestion.Position(2, 18)
)
),
documentation = None
),
Vector()
)

View File

@ -82,7 +82,8 @@ object SuggestionRandom {
name = nextString(),
arguments = Seq(),
returnType = nextString(),
scope = nextScope()
scope = nextScope(),
documentation = optional(nextString())
)
def nextSuggestionLocal(): Suggestion.Local =
@ -91,7 +92,8 @@ object SuggestionRandom {
module = "Test.Main",
name = nextString(),
returnType = nextString(),
scope = nextScope()
scope = nextScope(),
documentation = optional(nextString())
)
def nextScope(): Suggestion.Scope =

View File

@ -1129,7 +1129,17 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
reexport = reexport
)
row -> (firstArg +: args)
case Suggestion.Function(expr, module, name, args, returnType, scope) =>
case Suggestion.Function(
expr,
module,
name,
args,
returnType,
scope,
doc,
_,
_
) =>
val row = SuggestionRow(
id = None,
externalIdLeast = expr.map(_.getLeastSignificantBits),
@ -1141,7 +1151,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
returnType = returnType,
parentType = None,
isStatic = false,
documentation = None,
documentation = doc,
scopeStartLine = scope.start.line,
scopeStartOffset = scope.start.character,
scopeEndLine = scope.end.line,
@ -1149,7 +1159,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
reexport = None
)
row -> args
case Suggestion.Local(expr, module, name, returnType, scope) =>
case Suggestion.Local(expr, module, name, returnType, scope, doc, _, _) =>
val row = SuggestionRow(
id = None,
externalIdLeast = expr.map(_.getLeastSignificantBits),
@ -1161,7 +1171,7 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
returnType = returnType,
parentType = None,
isStatic = false,
documentation = None,
documentation = doc,
scopeStartLine = scope.start.line,
scopeStartOffset = scope.start.character,
scopeEndLine = scope.end.line,
@ -1288,7 +1298,10 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
suggestion.scopeEndLine,
suggestion.scopeEndOffset
)
)
),
documentation = suggestion.documentation,
documentationHtml = None,
documentationSections = None
)
case SuggestionKind.LOCAL =>
Suggestion.Local(
@ -1306,7 +1319,10 @@ final class SqlSuggestionsRepo(val db: SqlDatabase)(implicit
suggestion.scopeEndLine,
suggestion.scopeEndOffset
)
)
),
documentation = suggestion.documentation,
documentationHtml = None,
documentationSections = None
)
case k =>
throw new NoSuchElementException(s"Unknown suggestion kind: $k")

View File

@ -675,6 +675,73 @@ class SuggestionsRepoTest extends AnyWordSpec with Matchers with RetrySpec {
)
}
"update suggestion function documentation" taggedAs Retry in withRepo {
repo =>
val newDoc = "My awesome function!"
val action = for {
(v1, Seq(_, _, _, _, _, id1, _)) <- repo.insertAll(
Seq(
suggestion.module,
suggestion.tpe,
suggestion.constructor,
suggestion.method,
suggestion.conversion,
suggestion.function,
suggestion.local
)
)
(v2, id2) <- repo.update(
suggestion.function,
None,
None,
None,
Some(Some(newDoc)),
None,
None
)
s <- repo.select(id1.get)
} yield (v1, id1, v2, id2, s)
val (v1, id1, v2, id2, s) = Await.result(action, Timeout)
v1 should not equal v2
id1 shouldEqual id2
s shouldEqual Some(
suggestion.function.copy(documentation = Some(newDoc))
)
}
"update suggestion local documentation" taggedAs Retry in withRepo { repo =>
val newDoc = "Some stuff there"
val action = for {
(v1, Seq(_, _, _, _, _, _, id1)) <- repo.insertAll(
Seq(
suggestion.module,
suggestion.tpe,
suggestion.constructor,
suggestion.method,
suggestion.conversion,
suggestion.function,
suggestion.local
)
)
(v2, id2) <- repo.update(
suggestion.local,
None,
None,
None,
Some(Some(newDoc)),
None,
None
)
s <- repo.select(id1.get)
} yield (v1, id1, v2, id2, s)
val (v1, id1, v2, id2, s) = Await.result(action, Timeout)
v1 should not equal v2
id1 shouldEqual id2
s shouldEqual Some(
suggestion.local.copy(documentation = Some(newDoc))
)
}
"update suggestion removing documentation" taggedAs Retry in withRepo {
repo =>
val action = for {
@ -1898,8 +1965,9 @@ class SuggestionsRepoTest extends AnyWordSpec with Matchers with RetrySpec {
Suggestion.Argument("x", "Number", false, true, Some("0"))
),
returnType = "local.Test.Main.MyType",
scope =
Suggestion.Scope(Suggestion.Position(1, 5), Suggestion.Position(6, 0))
scope = Suggestion
.Scope(Suggestion.Position(1, 5), Suggestion.Position(6, 0)),
documentation = Some("My function bar.")
)
val local: Suggestion.Local =
@ -1911,7 +1979,8 @@ class SuggestionsRepoTest extends AnyWordSpec with Matchers with RetrySpec {
scope = Suggestion.Scope(
Suggestion.Position(3, 4),
Suggestion.Position(6, 0)
)
),
documentation = Some("Some bazz")
)
}
}