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

lint, fmt: support tags for approaches and concepts #822

Merged
merged 13 commits into from
Oct 6, 2023
20 changes: 19 additions & 1 deletion src/fmt/approaches.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import std/[json, strformat]
import std/[json, options, strformat]
import ".."/[helpers, sync/sync_common, types_approaches_config]

func approachesConfigKeyOrderForFmt(e: ApproachesConfig): seq[ApproachesConfigKey] =
Expand All @@ -23,6 +23,20 @@ func addApproachesIntroduction(result: var string;
result.addNewlineAndIndent(indentLevel)
result.add "},"

func addApproachTags(result: var string; val: ApproachConfigTags; indentLevel = 2) =
result.addNewlineAndIndent(indentLevel)
escapeJson("tags", result)
result.add ": {"
if val.all.len > 0:
result.addArray("all", val.all, indentLevel + 1)
if val.`any`.len > 0:
result.addArray("any", val.`any`, indentLevel + 1)
if val.`not`.len > 0:
result.addArray("not", val.`not`, indentLevel + 1)
result.removeComma()
result.addNewlineAndIndent(indentLevel)
result.add "},"

func addApproach(result: var string; val: ApproachConfig; indentLevel = 1) =
## Appends the pretty-printed JSON for an `approach` object with value `val` to
## `result`.
Expand All @@ -35,6 +49,10 @@ func addApproach(result: var string; val: ApproachConfig; indentLevel = 1) =
result.addArray("authors", val.authors, indentLevel + 1)
if val.contributors.len > 0:
result.addArray("contributors", val.contributors, indentLevel + 1)
if val.tags.isSome():
let tags = val.tags.get()
if tags.all.len + tags.`any`.len + tags.`not`.len > 0:
result.addApproachTags(tags, indentLevel + 1)
ee7 marked this conversation as resolved.
Show resolved Hide resolved
result.removeComma()
result.addNewlineAndIndent(indentLevel)
result.add "},"
Expand Down
18 changes: 18 additions & 0 deletions src/fmt/track_config.nim
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,20 @@ func addKeyFeatures(result: var string; val: KeyFeatures; indentLevel = 1) =
result.addNewlineAndIndent(indentLevel)
result.add "],"

func addConceptTags(result: var string; val: ConceptTags; indentLevel = 2) =
result.addNewlineAndIndent(indentLevel)
escapeJson("tags", result)
result.add ": {"
if val.all.len > 0:
result.addArray("all", val.all, indentLevel + 1)
if val.`any`.len > 0:
result.addArray("any", val.`any`, indentLevel + 1)
if val.`not`.len > 0:
result.addArray("not", val.`not`, indentLevel + 1)
result.removeComma()
result.addNewlineAndIndent(indentLevel)
result.add "},"

func addConcept(result: var string; val: Concept; indentLevel = 1) =
## Appends the pretty-printed JSON for a `concept` object with value `val` to
## `result`.
Expand All @@ -129,6 +143,10 @@ func addConcept(result: var string; val: Concept; indentLevel = 1) =
result.addString("uuid", val.uuid, indentLevel + 1)
result.addString("slug", val.slug, indentLevel + 1)
result.addString("name", val.name, indentLevel + 1)
if val.tags.isSome():
let tags = val.tags.get()
if tags.all.len + tags.`any`.len + tags.`not`.len > 0:
result.addConceptTags(tags, indentLevel + 1)
result.removeComma()
result.addNewlineAndIndent(indentLevel)
result.add "},"
Expand Down
12 changes: 10 additions & 2 deletions src/lint/approaches_and_articles.nim
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ proc hasValidIntroduction(data: JsonNode, path: Path): bool =
result.setFalseIfFileMissingOrEmpty(introductionPath, msg)

proc isValidApproachOrArticle(data: JsonNode, context: string,
path: Path): bool =
path: Path, checkTags: bool): bool =
if isObject(data, context, path):
let checks = [
hasString(data, "uuid", path, context, checkIsUuid = true),
Expand All @@ -41,6 +41,7 @@ proc isValidApproachOrArticle(data: JsonNode, context: string,
hasArrayOfStrings(data, "authors", path, context, uniqueValues = true),
hasArrayOfStrings(data, "contributors", path, context,
isRequired = false),
if checkTags: hasValidAnalyzerTags(data, path) else: true,
]
result = allTrue(checks)
if result:
Expand All @@ -63,6 +64,12 @@ proc isValidApproachOrArticle(data: JsonNode, context: string,
"there is no corresponding snippet file at the below location"
result.setFalseIfFileMissingOrEmpty(snippetPath, msg)

proc isValidApproach(data: JsonNode, context: string, path: Path): bool =
isValidApproachOrArticle(data, context, path, checkTags = true)

proc isValidArticle(data: JsonNode, context: string, path: Path): bool =
isValidApproachOrArticle(data, context, path, checkTags = false)

proc getSlugs(data: JsonNode, k: string): seq[string] =
result = @[]
if data.kind == JObject and data.hasKey(k):
Expand All @@ -77,7 +84,8 @@ proc isValidConfig(data: JsonNode, path: Path, dk: DocumentKind): bool =
let k = dk.`$`[1..^1] # Remove dot.
let checks = [
if dk == dkApproaches: hasValidIntroduction(data, path) else: true,
hasArrayOf(data, k, path, isValidApproachOrArticle, isRequired = false),
hasArrayOf(data, k, path, if dk == dkApproaches: isValidApproach else: isValidArticle,
isRequired = false),
]
result = allTrue(checks)
if result:
Expand Down
3 changes: 2 additions & 1 deletion src/lint/track_config.nim
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ proc isValidConcept(data: JsonNode; context: string; path: Path): bool =
hasString(data, "uuid", path, context, checkIsUuid = true),
hasString(data, "slug", path, context, maxLen = 255, checkIsKebab = true),
hasString(data, "name", path, context, maxLen = 255),
hasValidAnalyzerTags(data, path),
]
result = allTrue(checks)

Expand Down Expand Up @@ -625,7 +626,7 @@ proc checkExerciseSlugsAndForegone(exercises: Exercises; b: var bool;
"but there is an implemented exercise with that slug"
b.setFalseAndPrint(msg, path)

proc checkFilePatternsOverlap(filePatterns: FilePatterns; trackSlug: string,
proc checkFilePatternsOverlap(filePatterns: FilePatterns; trackSlug: string;
b: var bool; path: Path) =
const overlappingSolutionTestTrackSlugs = ["d", "plsql"]
const uniqueFilePatternCombinations = [
Expand Down
26 changes: 26 additions & 0 deletions src/lint/validators.nim
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,32 @@ proc hasInteger*(data: JsonNode; key: string; path: Path; context = "";
elif not isRequired:
result = true

proc hasValidAnalyzerTags*(data: JsonNode; path: Path): bool =
const k = "tags"
if data.hasKey(k):
if hasObject(data, k, path):
let checks = [
hasArrayOfStrings(data[k], "all", path, isRequired = false, uniqueValues = true),
hasArrayOfStrings(data[k], "any", path, isRequired = false, uniqueValues = true),
hasArrayOfStrings(data[k], "not", path, isRequired = false, uniqueValues = true),
]
result = allTrue(checks)
if result:
var anyAllLen = 0

if data[k].hasKey("all"):
anyAllLen += data[k]["all"].len

if data[k].hasKey("any"):
anyAllLen += data[k]["any"].len

if anyAllLen == 0:
const msg = "There must be at least one element in the `all` " &
"or `any` fields in the `tags` object"
result.setFalseAndPrint(msg, path)
else:
result = true

proc parseJson(s: Stream; filename: Path; rawIntegers = false;
rawFloats = false): JsonNode {.borrow.}

Expand Down
8 changes: 8 additions & 0 deletions src/types_approaches_config.nim
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import std/options
import "."/helpers

type
Expand All @@ -12,6 +13,7 @@ type
akBlurb = "blurb"
akAuthors = "authors"
akContributors = "contributors"
akTags = "tags"

ApproachIntroductionKey* = enum
aiAuthors = "authors"
Expand All @@ -21,13 +23,19 @@ type
authors*: seq[string]
contributors*: seq[string]

ApproachConfigTags* = object
all*: seq[string]
`any`*: seq[string]
`not`*: seq[string]

ApproachConfig* = object
uuid*: string
slug*: string
title*: string
blurb*: string
authors*: seq[string]
contributors*: seq[string]
tags*: Option[ApproachConfigTags]

ApproachesConfig* = object
introduction*: ApproachesIntroductionConfig
Expand Down
6 changes: 6 additions & 0 deletions src/types_track_config.nim
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,16 @@ type
indentSize*: int
highlightjsLanguage*: string

ConceptTags* = object
all*: seq[string]
`any`*: seq[string]
`not`*: seq[string]
ee7 marked this conversation as resolved.
Show resolved Hide resolved

Concept* = object
name*: string
slug*: string
uuid*: string
tags*: Option[ConceptTags]

Concepts* = seq[Concept]

Expand Down