File size: 2,799 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | import { createRule, paramMessage } from '@typespec/compiler'
import {
isCamelCaseNoAcronyms,
isPascalCaseNoAcronyms,
isSnakeCase,
} from './utils.js'
export const casingRule = createRule({
name: 'casing',
severity: 'warning',
description: 'Ensure proper casing style for AIP naming conventions.',
messages: {
name: paramMessage`The names of ${'type'} types must use ${'casing'}`,
},
create: (context) => ({
model: (model) => {
if (!isPascalCaseNoAcronyms(model.name)) {
context.reportDiagnostic({
format: { type: 'Model', casing: 'PascalCase' },
target: model,
messageId: 'name',
})
}
},
modelProperty: (property) => {
const isPath = property.decorators.find(
(d) => d.decorator.name === '$path',
)
if (isPath) {
if (!isCamelCaseNoAcronyms(property.name)) {
context.reportDiagnostic({
format: { type: 'Model Property', casing: 'camelCase' },
target: property,
messageId: 'name',
})
}
return
}
if (
!['_', 'contentType'].includes(property.name) &&
!isSnakeCase(property.name)
) {
context.reportDiagnostic({
format: { type: 'Model Property', casing: 'snake_case' },
target: property,
messageId: 'name',
})
}
},
enum: (model) => {
// Check enum name is PascalCase
if (!isPascalCaseNoAcronyms(model.name)) {
context.reportDiagnostic({
format: { type: 'Enum', casing: 'PascalCase' },
target: model,
messageId: 'name',
})
}
// Check enum member names are PascalCase
for (const member of model.members.values()) {
if (!isPascalCaseNoAcronyms(member.name)) {
context.reportDiagnostic({
format: { type: 'Enum Member', casing: 'PascalCase' },
target: member,
messageId: 'name',
})
}
}
},
}),
})
export const casingErrorsRule = createRule({
name: 'casing-aip-errors',
severity: 'error',
description: 'Ensure proper casing style for AIP naming conventions.',
messages: {
value: paramMessage`The values of ${'type'} types must use ${'casing'}`,
},
create: (context) => ({
enum: (model) => {
// Check enum member values are snake_case
for (const member of model.members.values()) {
if (member.value && typeof member.value === 'string') {
if (!isSnakeCase(member.value)) {
context.reportDiagnostic({
format: { type: 'Enum Value', casing: 'snake_case' },
target: member,
messageId: 'value',
})
}
}
}
},
}),
})
|