File size: 1,604 Bytes
048b1e8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | import {
createRule,
getDiscriminator,
getTypeName,
isTemplateInstance,
paramMessage,
} from '@typespec/compiler'
import { SyntaxKind } from '@typespec/compiler/ast'
export const compositionOverInheritanceRule = createRule({
name: 'composition-over-inheritance',
description:
'Check that if a model is used in an operation and has derived models that it has a discriminator or recommend to use composition via spread or `is`.',
severity: 'warning',
messages: {
default: paramMessage`Model '${'name'}' is extending '${'baseModel'}' that doesn't define a discriminator. If '${'baseModel'}' is meant to be used:
- For composition consider using spread \`...\` or \`model is\` instead.
- As a polymorphic relation, add the \`@discriminator\` decorator on the base model.`,
instance: paramMessage`Model '${'name'}' is extending a template '${'baseModel'}'. Consider using composition with spread \`...\` or \`model is\` instead.`,
},
create(context) {
return {
model: (model) => {
if (
model.baseModel &&
model.node?.kind === SyntaxKind.ModelStatement &&
model.node.extends &&
getDiscriminator(context.program, model.baseModel) === undefined
) {
context.reportDiagnostic({
messageId: isTemplateInstance(model.baseModel)
? 'instance'
: 'default',
format: {
name: model.name,
baseModel: getTypeName(model.baseModel),
},
target: model.node.extends,
})
}
},
}
},
})
|