Skip to content

Commit

Permalink
Merge pull request #491 from iheartradio/javakky/skip-file-nodocs
Browse files Browse the repository at this point in the history
feat: comments that can be skipped in a file at once
  • Loading branch information
Javakky-pxv authored Aug 8, 2022
2 parents c8cb26d + e5b814e commit f7b79a2
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 40 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,23 @@ e.g.
GET /docs/swagger-ui/*file controllers.Assets.at(path:String="/public/lib/swagger-ui", file:String)
```

##### Skip entire file

The entire file can be skipped by adding `### SkipFileForDocs ###` at the beginning of the routes file.

Alternatively, the routes file can be split into multiple files, so that you can skip practically only a part of the file.

https://www.playframework.com/documentation/ja/2.4.x/SBTSubProjects

```
### SkipFileForDocs ###
GET /api/hidden/a controllers.hiddenEndPointA()
GET /api/hidden/b controllers.hiddenEndPointB()
GET /api/hidden/c controllers.hiddenEndPointC()
```


#### How to specify body content in a POST endpoint
Body content is specified as a special parameter in swagger. So you need to create a parameter in your swagger spec comment as "body", for example
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,45 +95,49 @@ final case class SwaggerSpecGenerator(

// TODO: better error handling
ResourceReader.read(routesFile).flatMap { lines
val content = lines.mkString("\n")
// artificial file to conform to api, used by play for error reporting
val file = new File(routesFile)

def errorMessage(error: RoutesCompilationError) = {
val lineNumber = error.line.fold("")(":" + _ + error.column.fold("")(":" + _))
val errorLine = error.line.flatMap { line
val caret = error.column.map(c (" " * (c - 1)) + "^").getOrElse("")
lines.lift(line - 1).map(_ + "\n" + caret)
}.getOrElse("")
s"""|Error parsing routes file: ${error.source.getName}$lineNumber ${error.message}
|$errorLine
|""".stripMargin
}

RoutesFileParser.parseContent(content, file).fold(
{ errors
val message = errors.map(errorMessage).mkString("\n")
Failure(new Exception(message))
},
{ rules
val routerName = tagFromFile(routesFile)
val init: RoutesData = Success(ListMap(routerName (path, Seq.empty)))
rules.foldLeft(init) {
case (Success(acc), route: Route)
val (prefix, routes) = acc(routerName)
Success(acc + (routerName (prefix, routes :+ route)))
case (Success(acc), Include(prefix, router))
val reference = router.replace(".Routes", ".routes")
val isIncludedRoutesFile = cl.getResource(reference) != null
if (isIncludedRoutesFile) {
val updated = if (path.nonEmpty) path + "/" + prefix else prefix
loop(updated, reference).map(acc ++ _)
} else Success(acc)

case (l @ Failure(_), _) l
lines.headOption match {
case Some("### SkipFileForDocs ###") => Success { ListMap.empty }
case _ =>
val content = lines.mkString("\n")

// artificial file to conform to api, used by play for error reporting
val file = new File(routesFile)

def errorMessage(error: RoutesCompilationError) = {
val lineNumber = error.line.fold("")(":" + _ + error.column.fold("")(":" + _))
val errorLine = error.line.flatMap { line
val caret = error.column.map(c (" " * (c - 1)) + "^").getOrElse("")
lines.lift(line - 1).map(_ + "\n" + caret)
}.getOrElse("")
s"""|Error parsing routes file: ${error.source.getName}$lineNumber ${error.message}
|$errorLine
|""".stripMargin
}
}
)

RoutesFileParser.parseContent(content, file).fold(
{ errors
val message = errors.map(errorMessage).mkString("\n")
Failure(new Exception(message))
},
{ rules
val routerName = tagFromFile(routesFile)
val init: RoutesData = Success(ListMap(routerName (path, Seq.empty)))
rules.foldLeft(init) {
case (Success(acc), route: Route)
val (prefix, routes) = acc(routerName)
Success(acc + (routerName (prefix, routes :+ route)))
case (Success(acc), Include(prefix, router))
val reference = router.replace(".Routes", ".routes")
val isIncludedRoutesFile = cl.getResource(reference) != null
if (isIncludedRoutesFile) {
val updated = if (path.nonEmpty) path + "/" + prefix else prefix
loop(updated, reference).map(acc ++ _)
} else Success(acc)
case (l @ Failure(_), _) l
}
}
)
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions core/src/test/resources/hidden.route
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### SkipFileForDocs ###

GET a controllers.LiveMeta.hiddenEndPointA()

GET b controllers.LiveMeta.hiddenEndPointB()

GET c controllers.LiveMeta.hiddenEndPointC()
4 changes: 3 additions & 1 deletion core/src/test/resources/liveMeta.routes
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ GET /api/station/:sid/playedTracks/last @controllers.LiveMeta.pl
POST /api/station/playedTracks controllers.LiveMeta.addPlayedTracks()

### NoDocs ###
GET /api/station/hidden controllers.LiveMeta.hiddenEndPoint()
GET /api/station/hidden controllers.LiveMeta.hiddenEndPoint()

-> /api/station/hidden hidden.Routes
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,20 @@ class SwaggerSpecGeneratorIntegrationSpec extends Specification {
}

"does not generate for end points marked as hidden" >> {
(pathJson \ "/api/station/hidden" \ "get").toOption must beEmpty
"single" >> {
(pathJson \ "/api/station/hidden" \ "get").toOption must beEmpty
}
"can batch skip within a file" >> {
"multiple-a" >> {
(pathJson \ "/api/station/hidden/a" \ "get").toOption must beEmpty
}
"multiple-b" >> {
(pathJson \ "/api/station/hidden/b" \ "get").toOption must beEmpty
}
"multiple-c" >> {
(pathJson \ "/api/station/hidden/c" \ "get").toOption must beEmpty
}
}
}

"generate path correctly with missing type (String by default) in controller description" >> {
Expand Down

0 comments on commit f7b79a2

Please sign in to comment.