Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: comments that can be skipped in a file at once #491

Merged
merged 1 commit into from
Aug 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 }
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the keyword is at the beginning of the file, it is not read in the first place.

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