1
1
package effekt
2
2
3
3
import effekt .context .{Annotations , Context }
4
- import effekt .source .{FunDef , Include , Maybe , ModuleDecl , Span , Tree }
4
+ import effekt .source .{FunDef , Include , Maybe , ModuleDecl , Span , Tree , Doc }
5
5
import effekt .symbols .{CaptureSet , Hole }
6
6
import kiama .util .{Position , Source }
7
7
import effekt .symbols .scopes .Scope
@@ -18,27 +18,35 @@ trait Intelligence {
18
18
symbol : Symbol ,
19
19
header : String ,
20
20
signature : Option [String ],
21
- description : Option [String ]
21
+ description : Option [String ],
22
+ documentation : Doc
22
23
) {
23
24
def fullDescription : String = {
24
25
val sig = signature.map(sig => s " ```effekt \n $sig\n ``` " ).getOrElse { " " }
25
26
val desc = description.getOrElse(" " )
27
+ val doc = showDocumentation(documentation)
26
28
27
29
s """ |#### $header
28
30
| $sig
29
- | $desc
31
+ | $desc$doc
30
32
| """ .stripMargin
31
33
}
32
34
33
35
def shortDescription : String = {
34
36
val sig = signature.map(sig => s " ```effekt \n $sig\n ``` " ).getOrElse { " " }
37
+ val doc = showDocumentation(documentation)
35
38
36
39
s """ |#### $header
37
- | $sig
40
+ | $sig$doc
38
41
| """ .stripMargin
39
42
}
40
43
}
41
44
45
+ def showDocumentation (documentation : Doc ): String =
46
+ documentation.map('\n ' +: _)
47
+ .getOrElse(" " )
48
+ .replace(" \\ n" , " \n " )
49
+
42
50
private def sortByPosition (trees : Vector [Tree ])(using C : Context ): Vector [Tree ] =
43
51
val pos = C .positions
44
52
trees.sortWith {
@@ -110,6 +118,16 @@ trait Intelligence {
110
118
case u => C .definitionTreeOption(u)
111
119
}
112
120
121
+ def getDocumentationOf (s : Symbol )(using C : Context ): Doc =
122
+ getDefinitionOf(s).asInstanceOf [Option [Any ]] match {
123
+ case Some (p : Product ) =>
124
+ p.productElementNames.zip(p.productIterator)
125
+ .collectFirst {
126
+ case (" doc" , Some (s : String )) => s
127
+ }
128
+ case _ => None
129
+ }
130
+
113
131
// For now, only show the first call target
114
132
def resolveCallTarget (sym : Symbol ): Symbol = sym match {
115
133
case t : CallTarget => t.symbols.flatten.headOption.getOrElse(sym)
@@ -204,12 +222,15 @@ trait Intelligence {
204
222
def getInfoOf (sym : Symbol )(using C : Context ): Option [SymbolInfo ] = PartialFunction .condOpt(resolveCallTarget(sym)) {
205
223
206
224
case b : ExternFunction =>
207
- SymbolInfo (b, " External function definition" , Some (DeclPrinter (b)), None )
225
+ val doc = getDocumentationOf(b)
226
+ SymbolInfo (b, " External function definition" , Some (DeclPrinter (b)), None , doc)
208
227
209
228
case f : UserFunction if C .functionTypeOption(f).isDefined =>
210
- SymbolInfo (f, " Function" , Some (DeclPrinter (f)), None )
229
+ val doc = getDocumentationOf(f)
230
+ SymbolInfo (f, " Function" , Some (DeclPrinter (f)), None , doc)
211
231
212
232
case f : Operation =>
233
+ val doc = getDocumentationOf(f)
213
234
val ex =
214
235
pp """ |Effect operations, like ` ${f.name}` allow to express non-local control flow.
215
236
|
@@ -229,32 +250,39 @@ trait Intelligence {
229
250
|handled by the handler. This is important when considering higher-order functions.
230
251
| """ .stripMargin
231
252
232
- SymbolInfo (f, " Effect operation" , Some (DeclPrinter (f)), Some (ex))
253
+ SymbolInfo (f, " Effect operation" , Some (DeclPrinter (f)), Some (ex), doc )
233
254
234
255
case f : EffectAlias =>
235
- SymbolInfo (f, " Effect alias" , Some (DeclPrinter (f)), None )
256
+ val doc = getDocumentationOf(f)
257
+ SymbolInfo (f, " Effect alias" , Some (DeclPrinter (f)), None , doc)
236
258
237
259
case t : TypeAlias =>
238
- SymbolInfo (t, " Type alias" , Some (DeclPrinter (t)), None )
260
+ val doc = getDocumentationOf(t)
261
+ SymbolInfo (t, " Type alias" , Some (DeclPrinter (t)), None , doc)
239
262
240
263
case t : ExternType =>
241
- SymbolInfo (t, " External type definition" , Some (DeclPrinter (t)), None )
264
+ val doc = getDocumentationOf(t)
265
+ SymbolInfo (t, " External type definition" , Some (DeclPrinter (t)), None , doc)
242
266
243
267
case t : ExternInterface =>
244
- SymbolInfo (t, " External interface definition" , Some (DeclPrinter (t)), None )
268
+ val doc = getDocumentationOf(t)
269
+ SymbolInfo (t, " External interface definition" , Some (DeclPrinter (t)), None , doc)
245
270
246
271
case t : ExternResource =>
247
- SymbolInfo (t, " External resource definition" , Some (DeclPrinter (t)), None )
272
+ val doc = getDocumentationOf(t)
273
+ SymbolInfo (t, " External resource definition" , Some (DeclPrinter (t)), None , doc)
248
274
249
275
case c : Constructor =>
276
+ val doc = getDocumentationOf(c)
250
277
val ex = pp """ |Instances of data types like ` ${c.tpe}` can only store
251
278
|_values_, not _blocks_. Hence, constructors like ` ${c.name}` only have
252
279
|value parameter lists, not block parameters.
253
280
| """ .stripMargin
254
281
255
- SymbolInfo (c, s " Constructor of data type ` ${c.tpe}` " , Some (DeclPrinter (c)), Some (ex))
282
+ SymbolInfo (c, s " Constructor of data type ` ${c.tpe}` " , Some (DeclPrinter (c)), Some (ex), doc )
256
283
257
284
case c : BlockParam =>
285
+ val doc = getDocumentationOf(c)
258
286
val signature = C .functionTypeOption(c).map { tpe => pp " { ${c.name}: ${tpe} } " }
259
287
260
288
val ex =
@@ -267,9 +295,10 @@ trait Intelligence {
267
295
|yielded to.
268
296
| """ .stripMargin
269
297
270
- SymbolInfo (c, " Block parameter" , signature, Some (ex))
298
+ SymbolInfo (c, " Block parameter" , signature, Some (ex), doc )
271
299
272
300
case c : ResumeParam =>
301
+ val doc = getDocumentationOf(c)
273
302
val tpe = C .functionTypeOption(c)
274
303
val signature = tpe.map { tpe => pp " { ${c.name}: ${tpe} } " }
275
304
val hint = tpe.map { tpe => pp " (i.e., ` ${tpe.result}`) " }.getOrElse { " " }
@@ -284,9 +313,10 @@ trait Intelligence {
284
313
|- the return type of the resumption.
285
314
| """ .stripMargin
286
315
287
- SymbolInfo (c, " Resumption" , signature, Some (ex))
316
+ SymbolInfo (c, " Resumption" , signature, Some (ex), doc )
288
317
289
318
case c : VarBinder =>
319
+ val doc = getDocumentationOf(c)
290
320
val signature = C .blockTypeOption(c).map(TState .extractType).orElse(c.tpe).map { tpe => pp " ${c.name}: ${tpe}" }
291
321
292
322
val ex =
@@ -299,9 +329,10 @@ trait Intelligence {
299
329
|combination with effect handlers.
300
330
""" .stripMargin
301
331
302
- SymbolInfo (c, " Mutable variable binder" , signature, Some (ex))
332
+ SymbolInfo (c, " Mutable variable binder" , signature, Some (ex), doc )
303
333
304
334
case s : RegBinder =>
335
+ val doc = getDocumentationOf(s)
305
336
val signature = C .blockTypeOption(s).map(TState .extractType).orElse(s.tpe).map { tpe => pp " ${s.name}: ${tpe}" }
306
337
307
338
val ex =
@@ -310,19 +341,22 @@ trait Intelligence {
310
341
|in combination with continuation capture and resumption.
311
342
| """ .stripMargin
312
343
313
- SymbolInfo (s, " Variable in region" , signature, Some (ex))
344
+ SymbolInfo (s, " Variable in region" , signature, Some (ex), doc )
314
345
315
346
case c : ValueParam =>
347
+ val doc = getDocumentationOf(c)
316
348
val signature = C .valueTypeOption(c).orElse(c.tpe).map { tpe => pp " ${c.name}: ${tpe}" }
317
- SymbolInfo (c, " Value parameter" , signature, None )
349
+ SymbolInfo (c, " Value parameter" , signature, None , doc )
318
350
319
351
case c : ValBinder =>
352
+ val doc = getDocumentationOf(c)
320
353
val signature = C .valueTypeOption(c).orElse(c.tpe).map { tpe => pp " ${c.name}: ${tpe}" }
321
- SymbolInfo (c, " Value binder" , signature, None )
354
+ SymbolInfo (c, " Value binder" , signature, None , doc )
322
355
323
356
case c : DefBinder =>
357
+ val doc = getDocumentationOf(c)
324
358
val signature = C .blockTypeOption(c).orElse(c.tpe).map { tpe => pp " ${c.name}: ${tpe}" }
325
- SymbolInfo (c, " Block binder" , signature, None )
359
+ SymbolInfo (c, " Block binder" , signature, None , doc )
326
360
}
327
361
}
328
362
0 commit comments