An experimental TypeSpec syntax for Lexicon
56
fork

Configure Feed

Select the types of activity you want to include in your feed.

types

+49 -36
+16 -16
packages/emitter/src/decorators.ts
··· 1 - import { DecoratorContext, Program, Type } from "@typespec/compiler"; 1 + import { 2 + DecoratorContext, 3 + Program, 4 + Type, 5 + NumericLiteral, 6 + StringLiteral, 7 + Model, 8 + } from "@typespec/compiler"; 2 9 import { getDoc } from "@typespec/compiler"; 3 10 4 11 const maxGraphemesKey = Symbol("maxGraphemes"); ··· 28 35 value: Type, 29 36 ) { 30 37 const numValue = 31 - (value as any).kind === "Number" || (value as any).kind === "Numeric" 32 - ? (value as any).value 33 - : value; 38 + value.kind === "Number" ? (value as NumericLiteral).value : value; 34 39 context.program.stateMap(maxBytesKey).set(target, Number(numValue)); 35 40 } 36 41 ··· 47 52 value: Type, 48 53 ) { 49 54 const numValue = 50 - (value as any).kind === "Number" || (value as any).kind === "Numeric" 51 - ? (value as any).value 52 - : value; 55 + value.kind === "Number" ? (value as NumericLiteral).value : value; 53 56 context.program.stateMap(minBytesKey).set(target, Number(numValue)); 54 57 } 55 58 ··· 70 73 encoding: Type, 71 74 ) { 72 75 const encodingValue = 73 - (encoding as any).kind === "String" ? (encoding as any).value : encoding; 76 + encoding.kind === "String" ? (encoding as StringLiteral).value : encoding; 74 77 context.program.stateMap(encodingKey).set(target, encodingValue); 75 78 } 76 79 ··· 90 93 value: Type, 91 94 ) { 92 95 const numValue = 93 - (value as any).kind === "Number" || (value as any).kind === "Numeric" 94 - ? (value as any).value 95 - : value; 96 + value.kind === "Number" ? (value as NumericLiteral).value : value; 96 97 context.program.stateMap(maxGraphemesKey).set(target, Number(numValue)); 97 98 } 98 99 ··· 112 113 value: Type, 113 114 ) { 114 115 const numValue = 115 - (value as any).kind === "Number" || (value as any).kind === "Numeric" 116 - ? (value as any).value 117 - : value; 116 + value.kind === "Number" ? (value as NumericLiteral).value : value; 118 117 context.program.stateMap(minGraphemesKey).set(target, Number(numValue)); 119 118 } 120 119 ··· 129 128 * @rec decorator for record type lexicons 130 129 */ 131 130 export function $rec(context: DecoratorContext, target: Type, key: Type) { 132 - const keyValue = (key as any).kind === "String" ? (key as any).value : key; 131 + const keyValue = 132 + key.kind === "String" ? (key as StringLiteral).value : key; 133 133 context.program.stateMap(recordKey).set(target, keyValue); 134 134 } 135 135 ··· 231 231 const errorList = context.program.stateMap(errorKey).get(target) || []; 232 232 233 233 for (const errorModel of errorModels) { 234 - if ((errorModel as any).kind !== "Model") { 234 + if (errorModel.kind !== "Model") { 235 235 context.program.reportDiagnostic({ 236 236 code: "invalid-error-type", 237 237 severity: "error",
+33 -20
packages/emitter/src/emitter.ts
··· 5 5 ModelProperty, 6 6 Scalar, 7 7 Union, 8 + Namespace, 9 + Operation, 10 + StringLiteral, 11 + NumericLiteral, 12 + BooleanLiteral, 13 + IntrinsicType, 8 14 getDoc, 9 15 getNamespaceFullName, 10 16 isTemplateInstance, ··· 107 113 } 108 114 } 109 115 110 - private processNamespace(ns: any) { 116 + private processNamespace(ns: Namespace) { 111 117 const fullName = getNamespaceFullName(ns); 112 118 113 119 // Skip TypeSpec internal namespaces ··· 155 161 } 156 162 157 163 private classifyNamespace( 158 - ns: any, 164 + ns: Namespace, 159 165 ): "operation" | "content" | "defs" | "empty" { 160 166 const hasModels = ns.models.size > 0; 161 167 const hasScalars = ns.scalars.size > 0; ··· 179 185 return "empty"; 180 186 } 181 187 182 - private emitContentLexicon(ns: any, fullName: string) { 188 + private emitContentLexicon(ns: Namespace, fullName: string) { 183 189 const models = [...ns.models.values()]; 184 190 const isDefsFile = fullName.endsWith(".defs"); 185 191 const mainModel = isDefsFile ? null : models.find((m) => m.name === "Main"); ··· 214 220 this.currentLexiconId = null; 215 221 } 216 222 217 - private emitDefsLexicon(ns: any, fullName: string) { 223 + private emitDefsLexicon(ns: Namespace, fullName: string) { 218 224 const lexiconId = fullName.endsWith(".defs") 219 225 ? fullName 220 226 : fullName + ".defs"; ··· 225 231 this.currentLexiconId = null; 226 232 } 227 233 228 - private emitOperationLexicon(ns: any, fullName: string) { 234 + private emitOperationLexicon(ns: Namespace, fullName: string) { 229 235 this.currentLexiconId = fullName; 230 236 const lexicon = this.createLexicon(fullName, ns); 231 237 ··· 252 258 this.currentLexiconId = null; 253 259 } 254 260 255 - private createLexicon(id: string, ns: any): LexiconDocument { 261 + private createLexicon(id: string, ns: Namespace): LexiconDocument { 256 262 const description = getDoc(this.program, ns); 257 263 const lexicon: LexiconDocument = description 258 264 ? { lexicon: 1, id, description, defs: {} } ··· 281 287 return modelDef; 282 288 } 283 289 284 - private addDefs(lexicon: LexiconDocument, ns: any, models: Model[]) { 290 + private addDefs(lexicon: LexiconDocument, ns: Namespace, models: Model[]) { 285 291 for (const model of models) { 286 292 this.addModelToDefs(lexicon, model); 287 293 } ··· 343 349 } 344 350 345 351 private addUnionToDefs(lexicon: LexiconDocument, union: Union) { 346 - const name = (union as any).name; 352 + const name = union.name; 347 353 if (!name) return; 348 354 349 355 // Skip @inline unions - they should be inlined, not defined separately ··· 392 398 const tuple = acceptArg.type; 393 399 if (tuple.values?.length > 0) { 394 400 acceptTypes = tuple.values 395 - .map((v: any) => (v.kind === "String" ? v.value : null)) 401 + .map((v: Type) => 402 + v.kind === "String" ? (v as StringLiteral).value : null, 403 + ) 396 404 .filter((v: string | null) => v !== null) as string[]; 397 405 if (!acceptTypes.length) acceptTypes = undefined; 398 406 } ··· 518 526 if (ref) unionRefs.push(ref); 519 527 break; 520 528 case "String": 521 - stringLiterals.push((variant.type as any).value); 529 + stringLiterals.push((variant.type as StringLiteral).value); 522 530 break; 523 531 case "Number": 524 - numericLiterals.push((variant.type as any).value); 532 + numericLiterals.push((variant.type as NumericLiteral).value); 525 533 break; 526 534 case "Boolean": 527 - booleanLiterals.push((variant.type as any).value); 535 + booleanLiterals.push((variant.type as BooleanLiteral).value); 528 536 break; 529 537 case "Scalar": 530 538 if ((variant.type as Scalar).name === "string") { ··· 532 540 } 533 541 break; 534 542 case "Intrinsic": 535 - const intrinsicName = (variant.type as any).name; 543 + const intrinsicName = (variant.type as IntrinsicType).name; 536 544 if (intrinsicName === "unknown" || intrinsicName === "never") { 537 545 hasUnknown = true; 538 546 } ··· 816 824 } 817 825 818 826 // Validate that parameters is a plain object 819 - if (param2.type.kind !== "Model" || (param2.type as any).name) { 827 + if (param2.type.kind !== "Model" || (param2.type as Model).name) { 820 828 this.program.reportDiagnostic({ 821 829 code: "procedure-parameters-not-object", 822 830 severity: "error", ··· 830 838 this.addInput(def, param1); 831 839 832 840 // Add parameters 833 - this.addParametersFromModel(def, param2.type as any); 841 + this.addParametersFromModel(def, param2.type as Model); 834 842 } 835 843 836 - private addParametersFromModel(def: any, parametersModel: any) { 844 + private addParametersFromModel(def: any, parametersModel: Model) { 837 845 if (parametersModel.kind !== "Model" || !parametersModel.properties) { 838 846 return; 839 847 } ··· 934 942 if (prop.type.kind === "Union") { 935 943 const variants = Array.from((prop.type as Union).variants.values()); 936 944 const hasNull = variants.some( 937 - (v) => v.type.kind === "Intrinsic" && (v.type as any).name === "null", 945 + (v) => 946 + v.type.kind === "Intrinsic" && 947 + (v.type as IntrinsicType).name === "null", 938 948 ); 939 949 940 950 if (hasNull) { 941 951 nullable.push(name); 942 952 const nonNullVariant = variants.find( 943 953 (v) => 944 - !(v.type.kind === "Intrinsic" && (v.type as any).name === "null"), 954 + !( 955 + v.type.kind === "Intrinsic" && 956 + (v.type as IntrinsicType).name === "null" 957 + ), 945 958 ); 946 959 if (nonNullVariant) typeToProcess = nonNullVariant.type; 947 960 } ··· 1269 1282 } 1270 1283 1271 1284 private getUnionReference(union: Union): string | null { 1272 - const unionName = (union as any).name; 1273 - const namespace = (union as any).namespace; 1285 + const unionName = union.name; 1286 + const namespace = union.namespace; 1274 1287 if (!unionName || !namespace || namespace.name === "TypeSpec") return null; 1275 1288 1276 1289 // If union is marked as @inline, don't create a reference - inline it instead