@@ -2,36 +2,45 @@ 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
- def pathToString (p : Path ) = p.toString.replace('\\ ' , '/' )
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 mapping = Map (
26
+ " \\ {\\ { path \\ }\\ }" .r -> pathToString(path),
27
+ " \\ {\\ { line \\ }\\ }" .r -> line.fold(" " )(_.toString),
28
+ " \\ {\\ { ext \\ }\\ }" .r -> Some (
29
+ pathToString(path)).filter(_.lastIndexOf(" ." ) == - 1 ).fold(" " )(p => p.substring(p.lastIndexOf(" ." ))
30
+ ),
31
+ " \\ {\\ { path_no_ext \\ }\\ }" .r -> Some (
32
+ pathToString(path)).filter(_.lastIndexOf(" ." ) == - 1 ).fold(pathToString(path))(p => p.substring(0 , p.lastIndexOf(" ." ))
33
+ ),
34
+ " \\ {\\ { name \\ }\\ }" .r -> memberName
35
+ )
36
+ mapping.foldLeft(urlTemplate) {
37
+ case (sourceLink, (regex, value)) => regex.replaceAllIn(sourceLink, Regex .quoteReplacement(value))
38
+ }
29
39
30
- urlTemplate.render(config)
31
40
32
41
case class WebBasedSourceLink (prefix : String , revision : String , subPath : String ) extends SourceLink :
33
42
override val path : Option [Path ] = None
34
- override def render (path : Path , operation : String , line : Option [Int ]): String =
43
+ override def render (memberName : String , path : Path , operation : String , line : Option [Int ]): String =
35
44
val action = if operation == " view" then " blob" else operation
36
45
val linePart = line.fold(" " )(l => s " #L $l" )
37
46
s " $prefix/ $action/ $revision$subPath/ $path$linePart"
@@ -40,10 +49,13 @@ object SourceLink:
40
49
val SubPath = " ([^=]+)=(.+)" .r
41
50
val KnownProvider = raw " (\w+):\/\/([^\/#]+)\/([^\/#]+)(\/[^\/#]+)?(#.+)? " .r
42
51
val BrokenKnownProvider = raw " (\w+):\/\/.+ " .r
43
- val ScalaDocPatten = raw " €\{(TPL_NAME|TPL_NAME |FILE_PATH|FILE_EXT|FILE_LINE|FILE_PATH_EXT)\} " .r
52
+ val ScalaDocPatten = raw " €\{(TPL_NAME|TPL_OWNER |FILE_PATH|FILE_EXT|FILE_LINE|FILE_PATH_EXT)\} " .r
44
53
val SupportedScalaDocPatternReplacements = Map (
45
54
" €{FILE_PATH_EXT}" -> " {{ path }}" ,
46
- " €{FILE_LINE}" -> " {{ line }}"
55
+ " €{FILE_LINE}" -> " {{ line }}" ,
56
+ " €{TPL_NAME}" -> " {{ name }}" ,
57
+ " €{FILE_EXT}" -> " {{ ext }}" ,
58
+ " €{FILE_PATH}" -> " {{ path_no_ext }}"
47
59
)
48
60
49
61
def githubPrefix (org : String , repo : String ) = s " https://github.com/ $org/ $repo"
@@ -54,10 +66,6 @@ object SourceLink:
54
66
private def parseLinkDefinition (s : String ): Option [SourceLink ] = ???
55
67
56
68
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
69
62
70
string match
63
71
case KnownProvider (name, organization, repo, rawRevision, rawSubPath) =>
@@ -90,28 +98,28 @@ object SourceLink:
90
98
val all = ScalaDocPatten .findAllIn(scaladocSetting)
91
99
val (supported, unsupported) = all.partition(SupportedScalaDocPatternReplacements .contains)
92
100
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 )
101
+ else Right ( TemplateSourceLink (supported.foldLeft(string)((template, pattern) =>
102
+ template.replace(pattern, SupportedScalaDocPatternReplacements (pattern)))))
103
+ case other =>
104
+ Right ( TemplateSourceLink ( " " ) )
97
105
98
106
99
107
type Operation = " view" | " edit"
100
108
101
109
case class SourceLinks (links : Seq [SourceLink ], projectRoot : Path ):
102
- def pathTo (rawPath : Path , line : Option [Int ] = None , operation : Operation = " view" ): Option [String ] =
110
+ def pathTo (rawPath : Path , memberName : String = " " , line : Option [Int ] = None , operation : Operation = " view" ): Option [String ] =
103
111
def resolveRelativePath (path : Path ) =
104
112
links
105
113
.find(_.path.forall(p => path.startsWith(p)))
106
- .map(_.render(path, operation, line))
114
+ .map(_.render(memberName, path, operation, line))
107
115
108
116
if rawPath.isAbsolute then
109
117
if rawPath.startsWith(projectRoot) then resolveRelativePath(projectRoot.relativize(rawPath))
110
118
else None
111
119
else resolveRelativePath(rawPath)
112
120
113
121
def pathTo (member : Member ): Option [String ] =
114
- member.sources.flatMap(s => pathTo(Paths .get(s.path), Option (s.lineNumber).map(_ + 1 )))
122
+ member.sources.flatMap(s => pathTo(Paths .get(s.path), member.name, Option (s.lineNumber).map(_ + 1 )))
115
123
116
124
object SourceLinks :
117
125
@@ -130,15 +138,10 @@ object SourceLinks:
130
138
| will match https://gitlab.com/$organization/$repository/-/[blob|edit]/$revision[/$subpath]/$filePath[$lineNumber]
131
139
| when revision is not provided then requires revision to be specified as argument for scala3doc
132
140
| - <scaladoc-template>
133
- | - <template>
134
141
|
135
142
|<scaladoc-template> is a format for `doc-source-url` parameter scaladoc.
136
143
|NOTE: We only supports `€{FILE_PATH_EXT}` and €{FILE_LINE} patterns
137
144
|
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
145
|
143
146
|
144
147
|Template can defined only by subset of sources defined by path prefix represented by `<sub-path>`.
0 commit comments