Skip to content

Commit

Permalink
Merge pull request #307 from mo-alras/rules/boolean-property-name-rule
Browse files Browse the repository at this point in the history
Rule: Boolean property name
  • Loading branch information
jenschude authored Jan 15, 2024
2 parents 200e5e9 + 524a745 commit 7990f22
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 2 deletions.
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Allows to validate RAML files and generate code from them
Commands:
generate Generate source code from a RAML specification.
verify Allows to verify if a raml spec is valid.
validate Validate the raml spec against defined rules and generate a validation report.
```

Generating Client SDKs or normalized RAML for documentation:
Expand Down Expand Up @@ -83,7 +85,7 @@ Generate source code from a RAML specification.
```

Validating a RAML API:
Verifying a RAML API:

```
Usage: rmf-codegen verify [-hw] <ramlFileLocation>
Expand All @@ -93,6 +95,31 @@ Allows to verify if a RAML spec is valid.
-w, --watch Watches the files for changes
```

Validating a RAML API and generating a validity report:

```
Usage: <main class> validate [-hvw] [--list-rules] [-f=<outputFormat>]
[-l=<linkBase>] [-lf=<linkFormat>]
[-o=<outputTarget>] [-r=<rulesetFile>]
[-s=<checkSeverity>] [-t=<tempFile>]
<ramlFileLocation>
Allows to verify if a raml spec is valid according to CT guidelines and generates a validation report
<ramlFileLocation> Api file location
-f, --format=<outputFormat> Specifies the output format. Valid values: CLI, JSON, MARKDOWN
-h, --help display this help message
-l, --link-base=<linkBase>
-lf, --link-format=<linkFormat> Specifies the link format. Valid values: CLI, GITHUB
--list-rules Show all rules
-o, --outputTarget=<outputTarget>
-r, --ruleset=<rulesetFile> Ruleset configuration
-s, --severity=<checkSeverity> Diagnostic severity. Valid values: info, warn, error
-t, --temp=<tempFile> Temporary folder
-v, --verbose Verbose
-w, --watch Watches the files for changes
```

## Development

### Build the "fat jar"
Expand Down
4 changes: 3 additions & 1 deletion ctp-validators/src/main/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@

This rule states that all resources should be plural. But some Platform APIs don't follow this and they are explicitly excluded.

* Add the new validator rule in this [folder](https://github.com/commercetools/rmf-codegen/tree/main/ctp-validators/src/main/kotlin/com/commercetools/rmf/validators). A new `case` method should be added to the rule class which validates the test examples added above.
* Add the new validator rule in this [folder](https://github.com/commercetools/rmf-codegen/tree/main/ctp-validators/src/main/kotlin/com/commercetools/rmf/validators). A new `case` method should be added to the rule class which validates the test examples added above.

* Add a description of the rule in this [page](https://github.com/commercetools/commercetools-docs/tree/main/api-specs#validator-rules)
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.commercetools.rmf.validators

import io.vrap.rmf.raml.model.types.*
import org.eclipse.emf.common.util.Diagnostic
import java.util.*

@ValidatorSet
class BooleanPropertyNameRule(severity: RuleSeverity, options: List<RuleOption>? = null) : TypesRule(severity, options) {

private val exclude: List<String> =
(options?.filter { ruleOption -> ruleOption.type.lowercase(Locale.getDefault()) == RuleOptionType.EXCLUDE.toString() }?.map { ruleOption -> ruleOption.value }?.plus("") ?: defaultExcludes)

override fun caseObjectType(type: ObjectType): List<Diagnostic> {
val validationResults: MutableList<Diagnostic> = ArrayList()

type.properties.filter { property -> property.type.isBoolean() }.forEach { property ->
if (exclude.contains(property.name).not()) {
if (property.name.matches(Regex("^is[A-Z].*$"))) {
validationResults.add(error(type, "Property \"{0}\" of type \"{1}\" must not have \"is\" as a prefix", property.name, type.name))
}
}
}
return validationResults
}

private fun AnyType.isBoolean(): Boolean {
return when(this) {
is BooleanType -> true
else -> false
}
}

companion object : ValidatorFactory<BooleanPropertyNameRule> {
private val defaultExcludes by lazy { listOf("") }

@JvmStatic
override fun create(options: List<RuleOption>?): BooleanPropertyNameRule {
return BooleanPropertyNameRule(RuleSeverity.ERROR, options)
}

@JvmStatic
override fun create(severity: RuleSeverity, options: List<RuleOption>?): BooleanPropertyNameRule {
return BooleanPropertyNameRule(severity, options)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ class ValidatorRulesTest extends Specification implements ValidatorFixtures {
result.validationResults[11].message == "Property \"fooTimeUntil\" of type \"InvalidTimeRangeUntil\" indicates a range, property ending with \"From\" is missing"
}

def "boolean property name rule"() {
when:
def validators = Arrays.asList(new TypesValidator(Arrays.asList(BooleanPropertyNameRule.create(emptyList()))))
def uri = uriFromClasspath("/boolean-property-name-rule.raml")
def result = new RamlModelBuilder(validators).buildApi(uri)
then:
result.validationResults.size == 2
result.validationResults[0].message == "Property \"isBad\" of type \"InvalidBoolean\" must not have \"is\" as a prefix"
result.validationResults[1].message == "Property \"isNotGood\" of type \"InvalidBoolean\" must not have \"is\" as a prefix"
}

def "discriminator name rule"() {
when:
def validators = Arrays.asList(new TypesValidator(Arrays.asList(DiscriminatorNameRule.create(emptyList()))))
Expand Down
49 changes: 49 additions & 0 deletions ctp-validators/src/test/resources/boolean-property-name-rule.raml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#%RAML 1.0
title: boolean property name rule

annotationTypes:
package: string
sdkBaseUri: string

baseUri: https://api.europe-west1.commercetools.com

types:
InvalidBoolean:
(package): Common
type: object
properties: # invalid because it is a boolean that is prefixed with "is"
isBad:
description: xyz
type: boolean
isNotGood: boolean
ValidBoolean:
(package): Common
type: object
properties:
/a-z/: # rule can't apply on dynamic properties
description: xyz
type: boolean
good: # name is not prefixed with "is"
description: xyz
type: boolean
alsoGood: boolean
isolated: # name starts with "is" but not as a prefix
description: xyz
type: boolean
ValidNonBoolean:
(package): Common
type: object
properties: # type is not a boolean
isFine:
description: xyz
type: string
isAlsoFine: number
ValidBooleanArray:
(package): Common
type: object
properties:
isGoods:
description: xyz
type: array
items: boolean

0 comments on commit 7990f22

Please sign in to comment.