in tools/tslint-rules/validateDecoratorsRule.ts [73:115]
private _validatedDecorator(decorator: any) {
// Get the rules that are relevant for the current decorator.
const rules = this._rules[decorator.expression.getText()];
// Don't do anything if there are no rules.
if (!rules) {
return;
}
// Extract the property names and values.
const props = decorator.arguments[0].properties.map((node: ts.PropertyAssignment) => ({
name: node.name.getText(),
value: node.initializer.getText(),
node
}));
// Find all of the required rule properties that are missing from the decorator.
const missing = Object.keys(rules.required)
.filter(key => !props.find((prop: any) => prop.name === key));
if (missing.length) {
// Exit early if any of the properties are missing.
this.addFailureAtNode(decorator.parent, 'Missing required properties: ' + missing.join(', '));
} else {
// If all the necessary properties are defined, ensure that
// they match the pattern and aren't in the forbidden list.
props
.filter((prop: any) => rules.required[prop.name] || rules.forbidden[prop.name])
.forEach((prop: any) => {
const {name, value, node} = prop;
const requiredPattern = rules.required[name];
const forbiddenPattern = rules.forbidden[name];
if (requiredPattern && !requiredPattern.test(value)) {
this.addFailureAtNode(node, `Invalid value for property. ` +
`Expected value to match "${requiredPattern}".`);
} else if (forbiddenPattern && forbiddenPattern.test(value)) {
this.addFailureAtNode(node, `Property value not allowed. ` +
`Value should not match "${forbiddenPattern}".`);
}
});
}
}