@@ -2,48 +2,61 @@ package dotty.dokka
2
2
3
3
import java .nio .file .Path
4
4
import java .nio .file .Paths
5
- import liqp .Template
6
5
import dotty .dokka .model .api ._
7
6
import dotty .tools .dotc .core .Contexts .Context
7
+ import scala .util .matching .Regex
8
8
9
9
def pathToString (p : Path ) = p.toString.replace('\\ ' , '/' )
10
10
11
11
trait SourceLink :
12
12
val path : Option [Path ] = None
13
- def render (path : Path , operation : String , line : Option [Int ]): String
13
+ def render (memberName : String , path : Path , operation : String , line : Option [Int ]): String
14
14
15
15
case class PrefixedSourceLink (val myPath : Path , nested : SourceLink ) extends SourceLink :
16
16
val myPrefix = pathToString(myPath)
17
17
override val path = Some (myPath)
18
- override def render (path : Path , operation : String , line : Option [Int ]): String =
19
- nested.render(myPath.relativize(path), operation, line)
18
+ override def render (memberName : String , path : Path , operation : String , line : Option [Int ]): String =
19
+ nested.render(memberName, myPath.relativize(path), operation, line)
20
20
21
21
22
- case class TemplateSourceLink (val urlTemplate : Template ) extends SourceLink :
22
+ case class TemplateSourceLink (val urlTemplate : String ) extends SourceLink :
23
23
override val path : Option [Path ] = None
24
- override def render (path : Path , operation : String , line : Option [Int ]): String =
25
- val config = java.util.HashMap [String , Object ]()
26
- config.put(" path" , pathToString(path))
27
- line.foreach(l => config.put(" line" , l.toString))
28
- config.put(" operation" , operation)
24
+ override def render (memberName : String , path : Path , operation : String , line : Option [Int ]): String =
25
+ val pathString = " /" + pathToString(path)
26
+ val mapping = Map (
27
+ " \\ {\\ { path \\ }\\ }" .r -> pathString,
28
+ " \\ {\\ { line \\ }\\ }" .r -> line.fold(" " )(_.toString),
29
+ " \\ {\\ { ext \\ }\\ }" .r -> Some (
30
+ pathString).filter(_.lastIndexOf(" ." ) == - 1 ).fold(" " )(p => p.substring(p.lastIndexOf(" ." ))
31
+ ),
32
+ " \\ {\\ { path_no_ext \\ }\\ }" .r -> Some (
33
+ pathString).filter(_.lastIndexOf(" ." ) == - 1 ).fold(pathString)(p => p.substring(0 , p.lastIndexOf(" ." ))
34
+ ),
35
+ " \\ {\\ { name \\ }\\ }" .r -> memberName
36
+ )
37
+ mapping.foldLeft(urlTemplate) {
38
+ case (sourceLink, (regex, value)) => regex.replaceAllIn(sourceLink, Regex .quoteReplacement(value))
39
+ }
29
40
30
- urlTemplate.render(config)
31
41
32
42
case class WebBasedSourceLink (prefix : String , revision : String , subPath : String ) extends SourceLink :
33
43
override val path : Option [Path ] = None
34
- override def render (path : Path , operation : String , line : Option [Int ]): String =
44
+ override def render (memberName : String , path : Path , operation : String , line : Option [Int ]): String =
35
45
val action = if operation == " view" then " blob" else operation
36
46
val linePart = line.fold(" " )(l => s " #L $l" )
37
- s " $prefix/ $action/ $revision$subPath/ $path$linePart"
47
+ s " $prefix/ $action/ $revision$subPath/ ${pathToString( path)} $linePart"
38
48
39
49
object SourceLink :
40
50
val SubPath = " ([^=]+)=(.+)" .r
41
51
val KnownProvider = raw " (\w+):\/\/([^\/#]+)\/([^\/#]+)(\/[^\/#]+)?(#.+)? " .r
42
52
val BrokenKnownProvider = raw " (\w+):\/\/.+ " .r
43
- val ScalaDocPatten = raw " €\{(TPL_NAME|TPL_NAME |FILE_PATH|FILE_EXT|FILE_LINE|FILE_PATH_EXT)\} " .r
53
+ val ScalaDocPatten = raw " €\{(TPL_NAME|TPL_OWNER |FILE_PATH|FILE_EXT|FILE_LINE|FILE_PATH_EXT)\} " .r
44
54
val SupportedScalaDocPatternReplacements = Map (
45
55
" €{FILE_PATH_EXT}" -> " {{ path }}" ,
46
- " €{FILE_LINE}" -> " {{ line }}"
56
+ " €{FILE_LINE}" -> " {{ line }}" ,
57
+ " €{TPL_NAME}" -> " {{ name }}" ,
58
+ " €{FILE_EXT}" -> " {{ ext }}" ,
59
+ " €{FILE_PATH}" -> " {{ path_no_ext }}"
47
60
)
48
61
49
62
def githubPrefix (org : String , repo : String ) = s " https://github.com/ $org/ $repo"
@@ -54,10 +67,6 @@ object SourceLink:
54
67
private def parseLinkDefinition (s : String ): Option [SourceLink ] = ???
55
68
56
69
def parse (string : String , revision : Option [String ]): Either [String , SourceLink ] =
57
- def asTemplate (template : String ) =
58
- try Right (TemplateSourceLink (Template .parse(template))) catch
59
- case e : RuntimeException =>
60
- Left (s " Failed to parse template: ${e.getMessage}" )
61
70
62
71
string match
63
72
case KnownProvider (name, organization, repo, rawRevision, rawSubPath) =>
@@ -90,28 +99,28 @@ object SourceLink:
90
99
val all = ScalaDocPatten .findAllIn(scaladocSetting)
91
100
val (supported, unsupported) = all.partition(SupportedScalaDocPatternReplacements .contains)
92
101
if unsupported.nonEmpty then Left (s " Unsupported patterns from scaladoc format are used: ${unsupported.mkString(" " )}" )
93
- else asTemplate (supported.foldLeft(string)((template, pattern) =>
94
- template.replace(pattern, SupportedScalaDocPatternReplacements (pattern))))
95
-
96
- case template => asTemplate(template )
102
+ else Right ( TemplateSourceLink (supported.foldLeft(string)((template, pattern) =>
103
+ template.replace(pattern, SupportedScalaDocPatternReplacements (pattern)))))
104
+ case other =>
105
+ Right ( TemplateSourceLink ( " " ) )
97
106
98
107
99
108
type Operation = " view" | " edit"
100
109
101
110
case class SourceLinks (links : Seq [SourceLink ], projectRoot : Path ):
102
- def pathTo (rawPath : Path , line : Option [Int ] = None , operation : Operation = " view" ): Option [String ] =
111
+ def pathTo (rawPath : Path , memberName : String = " " , line : Option [Int ] = None , operation : Operation = " view" ): Option [String ] =
103
112
def resolveRelativePath (path : Path ) =
104
113
links
105
114
.find(_.path.forall(p => path.startsWith(p)))
106
- .map(_.render(path, operation, line))
115
+ .map(_.render(memberName, path, operation, line))
107
116
108
117
if rawPath.isAbsolute then
109
118
if rawPath.startsWith(projectRoot) then resolveRelativePath(projectRoot.relativize(rawPath))
110
119
else None
111
120
else resolveRelativePath(rawPath)
112
121
113
122
def pathTo (member : Member ): Option [String ] =
114
- member.sources.flatMap(s => pathTo(Paths .get(s.path), Option (s.lineNumber).map(_ + 1 )))
123
+ member.sources.flatMap(s => pathTo(Paths .get(s.path), member.name, Option (s.lineNumber).map(_ + 1 )))
115
124
116
125
object SourceLinks :
117
126
@@ -130,15 +139,10 @@ object SourceLinks:
130
139
| will match https://gitlab.com/$organization/$repository/-/[blob|edit]/$revision[/$subpath]/$filePath[$lineNumber]
131
140
| when revision is not provided then requires revision to be specified as argument for scala3doc
132
141
| - <scaladoc-template>
133
- | - <template>
134
142
|
135
143
|<scaladoc-template> is a format for `doc-source-url` parameter scaladoc.
136
144
|NOTE: We only supports `€{FILE_PATH_EXT}` and €{FILE_LINE} patterns
137
145
|
138
- |<template> is a liqid template string that can accepts follwoing arguments:
139
- | - `operation`: either "view" or "edit"
140
- | - `path`: relative path of file to provide link to
141
- | - `line`: optional parameter that specify line number within a file
142
146
|
143
147
|
144
148
|Template can defined only by subset of sources defined by path prefix represented by `<sub-path>`.
0 commit comments