Migration tool (#1310)
This commit is contained in:
Родитель
d062362de0
Коммит
616d9831b3
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@cadl-lang/compiler",
|
||||
"comment": "Fix typing and export format command",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "@cadl-lang/compiler"
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@cadl-lang/migrate",
|
||||
"comment": "Add migration for `model is` to `scalar extends`",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "@cadl-lang/migrate"
|
||||
}
|
|
@ -3,6 +3,7 @@ lockfileVersion: 5.3
|
|||
specifiers:
|
||||
'@babel/code-frame': ~7.18.6
|
||||
'@babel/core': ^7.0.0
|
||||
'@cadl-lang/compiler-v0.37': npm:@cadl-lang/compiler@0.37.0
|
||||
'@docusaurus/core': ^2.2.0
|
||||
'@docusaurus/module-type-aliases': ^2.2.0
|
||||
'@docusaurus/preset-classic': ^2.2.0
|
||||
|
@ -27,6 +28,7 @@ specifiers:
|
|||
'@rush-temp/internal-build-utils': file:./projects/internal-build-utils.tgz
|
||||
'@rush-temp/library-linter': file:./projects/library-linter.tgz
|
||||
'@rush-temp/lint': file:./projects/lint.tgz
|
||||
'@rush-temp/migrate': file:./projects/migrate.tgz
|
||||
'@rush-temp/openapi': file:./projects/openapi.tgz
|
||||
'@rush-temp/openapi3': file:./projects/openapi3.tgz
|
||||
'@rush-temp/playground': file:./projects/playground.tgz
|
||||
|
@ -119,6 +121,7 @@ specifiers:
|
|||
dependencies:
|
||||
'@babel/code-frame': 7.18.6
|
||||
'@babel/core': 7.20.2
|
||||
'@cadl-lang/compiler-v0.37': /@cadl-lang/compiler/0.37.0
|
||||
'@docusaurus/core': 2.2.0_539090e1c80922bd93bda78b83dd9524
|
||||
'@docusaurus/module-type-aliases': 2.2.0_react-dom@18.2.0+react@18.2.0
|
||||
'@docusaurus/preset-classic': 2.2.0_454741b2b5ce645f4e539818791bb544
|
||||
|
@ -143,6 +146,7 @@ dependencies:
|
|||
'@rush-temp/internal-build-utils': file:projects/internal-build-utils.tgz
|
||||
'@rush-temp/library-linter': file:projects/library-linter.tgz
|
||||
'@rush-temp/lint': file:projects/lint.tgz
|
||||
'@rush-temp/migrate': file:projects/migrate.tgz
|
||||
'@rush-temp/openapi': file:projects/openapi.tgz
|
||||
'@rush-temp/openapi3': file:projects/openapi3.tgz
|
||||
'@rush-temp/playground': file:projects/playground.tgz_rollup@3.4.0
|
||||
|
@ -362,6 +366,13 @@ packages:
|
|||
'@babel/highlight': 7.18.6
|
||||
dev: false
|
||||
|
||||
/@babel/code-frame/7.16.7:
|
||||
resolution: {integrity: sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/highlight': 7.18.6
|
||||
dev: false
|
||||
|
||||
/@babel/code-frame/7.18.6:
|
||||
resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
@ -1739,6 +1750,28 @@ packages:
|
|||
resolution: {integrity: sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg==}
|
||||
dev: false
|
||||
|
||||
/@cadl-lang/compiler/0.37.0:
|
||||
resolution: {integrity: sha512-jHMqPZmM4evQlu7oY9vj6PEM+f+OhnfPqAdwxALrU2gwsLcwYG1h8rkjX/iK2KfeewCbXuRT/hztOTo3pcbYWA==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.16.7
|
||||
ajv: 8.9.0
|
||||
change-case: 4.1.2
|
||||
globby: 13.1.2
|
||||
js-yaml: 4.1.0
|
||||
mkdirp: 1.0.4
|
||||
mustache: 4.2.0
|
||||
node-fetch: 3.2.8
|
||||
node-watch: 0.7.3
|
||||
picocolors: 1.0.0
|
||||
prettier: 2.7.1
|
||||
prompts: 2.4.2
|
||||
vscode-languageserver: 7.0.0
|
||||
vscode-languageserver-textdocument: 1.0.7
|
||||
yargs: 17.3.1
|
||||
dev: false
|
||||
|
||||
/@colors/colors/1.5.0:
|
||||
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
|
||||
engines: {node: '>=0.1.90'}
|
||||
|
@ -4884,6 +4917,15 @@ packages:
|
|||
uri-js: 4.4.1
|
||||
dev: false
|
||||
|
||||
/ajv/8.9.0:
|
||||
resolution: {integrity: sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==}
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
json-schema-traverse: 1.0.0
|
||||
require-from-string: 2.0.2
|
||||
uri-js: 4.4.1
|
||||
dev: false
|
||||
|
||||
/algoliasearch-helper/3.11.1_algoliasearch@4.14.2:
|
||||
resolution: {integrity: sha512-mvsPN3eK4E0bZG0/WlWJjeqe/bUD2KOEVOl0GyL/TGXn6wcpZU8NOuztGHCUKXkyg5gq6YzUakVTmnmSSO5Yiw==}
|
||||
peerDependencies:
|
||||
|
@ -13127,6 +13169,11 @@ packages:
|
|||
yazl: 2.5.1
|
||||
dev: false
|
||||
|
||||
/vscode-jsonrpc/6.0.0:
|
||||
resolution: {integrity: sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==}
|
||||
engines: {node: '>=8.0.0 || >=10.0.0'}
|
||||
dev: false
|
||||
|
||||
/vscode-jsonrpc/8.0.2:
|
||||
resolution: {integrity: sha512-RY7HwI/ydoC1Wwg4gJ3y6LpU9FJRZAUnTYMXthqhFXXu77ErDd/xkREpGuk4MyYkk4a+XDWAMqe0S3KkelYQEQ==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
@ -13141,6 +13188,13 @@ packages:
|
|||
vscode-languageserver-protocol: 3.17.2
|
||||
dev: false
|
||||
|
||||
/vscode-languageserver-protocol/3.16.0:
|
||||
resolution: {integrity: sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==}
|
||||
dependencies:
|
||||
vscode-jsonrpc: 6.0.0
|
||||
vscode-languageserver-types: 3.16.0
|
||||
dev: false
|
||||
|
||||
/vscode-languageserver-protocol/3.17.2:
|
||||
resolution: {integrity: sha512-8kYisQ3z/SQ2kyjlNeQxbkkTNmVFoQCqkmGrzLH6A9ecPlgTbp3wDTnUNqaUxYr4vlAcloxx8zwy7G5WdguYNg==}
|
||||
dependencies:
|
||||
|
@ -13152,10 +13206,21 @@ packages:
|
|||
resolution: {integrity: sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg==}
|
||||
dev: false
|
||||
|
||||
/vscode-languageserver-types/3.16.0:
|
||||
resolution: {integrity: sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==}
|
||||
dev: false
|
||||
|
||||
/vscode-languageserver-types/3.17.2:
|
||||
resolution: {integrity: sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==}
|
||||
dev: false
|
||||
|
||||
/vscode-languageserver/7.0.0:
|
||||
resolution: {integrity: sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
vscode-languageserver-protocol: 3.16.0
|
||||
dev: false
|
||||
|
||||
/vscode-languageserver/8.0.2:
|
||||
resolution: {integrity: sha512-bpEt2ggPxKzsAOZlXmCJ50bV7VrxwCS5BI4+egUmure/oI/t4OlFzi/YNtVvY24A2UDOZAgwFGgnZPwqSJubkA==}
|
||||
hasBin: true
|
||||
|
@ -13662,6 +13727,19 @@ packages:
|
|||
yargs-parser: 20.2.9
|
||||
dev: false
|
||||
|
||||
/yargs/17.3.1:
|
||||
resolution: {integrity: sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
cliui: 7.0.4
|
||||
escalade: 3.1.1
|
||||
get-caller-file: 2.0.5
|
||||
require-directory: 2.1.1
|
||||
string-width: 4.2.3
|
||||
y18n: 5.0.8
|
||||
yargs-parser: 21.1.1
|
||||
dev: false
|
||||
|
||||
/yargs/17.6.2:
|
||||
resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==}
|
||||
engines: {node: '>=12'}
|
||||
|
@ -13938,6 +14016,26 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/migrate.tgz:
|
||||
resolution: {integrity: sha512-TkrCkt1/vCz/OFoqCIz613PlJJIOS3ZcvicpSQpZzcIh+R2p4iGHI3S/wlF/LfTyHJB4QctP/A0wHJEm6blXaQ==, tarball: file:projects/migrate.tgz}
|
||||
name: '@rush-temp/migrate'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@cadl-lang/compiler-v0.37': /@cadl-lang/compiler/0.37.0
|
||||
'@types/mocha': 10.0.0
|
||||
'@types/node': 18.11.9
|
||||
c8: 7.12.0
|
||||
eslint: 8.28.0
|
||||
globby: 13.1.2
|
||||
mocha: 10.1.0
|
||||
mocha-junit-reporter: 2.2.0_mocha@10.1.0
|
||||
mocha-multi-reporters: 1.5.1_mocha@10.1.0
|
||||
rimraf: 3.0.2
|
||||
typescript: 4.9.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/openapi.tgz:
|
||||
resolution: {integrity: sha512-Q1H5xFEpWcLHJ3PJlCdHbBp9je+9sVa+96ZJ6I0F5m23PvGNvJfcekmFzc/AoM21SWEnO6cfnEOdCGsuboTkJA==, tarball: file:projects/openapi.tgz}
|
||||
name: '@rush-temp/openapi'
|
||||
|
|
|
@ -56,7 +56,7 @@ jobs:
|
|||
|
||||
- task: AzureFileCopy@4
|
||||
inputs:
|
||||
sourcePath: "packages/website/dist/*"
|
||||
sourcePath: "packages/website/build/*"
|
||||
azureSubscription: "Azure SDK Playground"
|
||||
destination: "AzureBlob"
|
||||
storage: "cadlwebsite"
|
||||
|
|
|
@ -5,6 +5,7 @@ export * from "./checker.js";
|
|||
export * from "./decorator-utils.js";
|
||||
export * from "./diagnostics.js";
|
||||
export * from "./emitter-utils.js";
|
||||
export * from "./formatter.js";
|
||||
export * from "./helpers/index.js";
|
||||
export { createCadlLibrary, paramMessage, setCadlNamespace } from "./library.js";
|
||||
export * from "./manifest.js";
|
||||
|
|
|
@ -5,7 +5,7 @@ import { fileURLToPath, pathToFileURL } from "url";
|
|||
import { createSourceFile } from "./diagnostics.js";
|
||||
import { createConsoleSink } from "./logger/index.js";
|
||||
import { joinPaths, resolvePath } from "./path-utils.js";
|
||||
import { CompilerHost, RmOptions } from "./types";
|
||||
import { CompilerHost, RmOptions } from "./types.js";
|
||||
import { getSourceFileKindFromExt } from "./util.js";
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ParseOptions } from "./types";
|
||||
import { ParseOptions } from "./types.js";
|
||||
|
||||
export interface CompilerOptions {
|
||||
miscOptions?: Record<string, unknown>;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"reporter": ["cobertura", "json", "text"]
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
require("@cadl-lang/eslint-config-cadl/patch/modern-module-resolution");
|
||||
|
||||
module.exports = {
|
||||
plugins: ["@cadl-lang/eslint-plugin"],
|
||||
extends: ["@cadl-lang/eslint-config-cadl", "plugin:@cadl-lang/eslint-plugin/recommended"],
|
||||
parserOptions: { tsconfigRootDir: __dirname },
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
timeout: 5000
|
||||
require: source-map-support/register
|
||||
spec: "dist/test/**/*.test.js"
|
||||
ignore: "dist/test/manual/**/*.js"
|
||||
|
||||
# Config for https://www.npmjs.com/package/mocha-multi-reporters
|
||||
reporterOptions: "configFile=mocha.reporter.config.json"
|
|
@ -0,0 +1,9 @@
|
|||
# Cadl Migrate
|
||||
|
||||
Help with migration of breaking and deprecated changes between cadl versions.
|
||||
|
||||
Run
|
||||
|
||||
```bash
|
||||
npx @cadl-lang/migrate
|
||||
```
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"reporterEnabled": "spec, mocha-junit-reporter"
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"name": "@cadl-lang/migrate",
|
||||
"version": "0.1.0",
|
||||
"author": "Microsoft Corporation",
|
||||
"description": "Migration tool for cadl.",
|
||||
"homepage": "https://github.com/Microsoft/cadl",
|
||||
"readme": "https://github.com/Microsoft/cadl/blob/main/README.md",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Microsoft/cadl.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Microsoft/cadl/issues"
|
||||
},
|
||||
"keywords": [
|
||||
"cadl"
|
||||
],
|
||||
"type": "module",
|
||||
"main": "dist/src/index.js",
|
||||
"bin": {
|
||||
"cadl-migrate": "./dist/src/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf ./dist ./temp",
|
||||
"build": "tsc -p .",
|
||||
"watch": "tsc -p . --watch",
|
||||
"test": "mocha",
|
||||
"test-official": "c8 mocha --forbid-only --reporter mocha-multi-reporters",
|
||||
"lint": "eslint . --ext .ts --max-warnings=0",
|
||||
"lint:fix": "eslint . --fix --ext .ts"
|
||||
},
|
||||
"files": [
|
||||
"dist/**",
|
||||
"!dist/test/**"
|
||||
],
|
||||
"dependencies": {
|
||||
"globby": "~13.1.1",
|
||||
"@cadl-lang/compiler": "~0.37.0",
|
||||
"@cadl-lang/compiler-v0.37": "npm:@cadl-lang/compiler@0.37.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "~10.0.0",
|
||||
"@types/node": "~18.11.9",
|
||||
"@cadl-lang/compiler": "~0.37.0",
|
||||
"@cadl-lang/eslint-config-cadl": "~0.4.1",
|
||||
"@cadl-lang/eslint-plugin": "~0.1.1",
|
||||
"eslint": "^8.12.0",
|
||||
"mocha": "~10.1.0",
|
||||
"mocha-junit-reporter": "~2.2.0",
|
||||
"mocha-multi-reporters": "~1.5.1",
|
||||
"c8": "~7.12.0",
|
||||
"rimraf": "~3.0.2",
|
||||
"typescript": "~4.9.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/* eslint-disable no-console */
|
||||
import { migrateCadlFiles } from "./migrate.js";
|
||||
import { migrateModelToScalar } from "./migrations/v0.38/model-to-scalars.js";
|
||||
import { findCadlFiles } from "./utils.js";
|
||||
|
||||
async function main() {
|
||||
const files = await findCadlFiles(process.cwd());
|
||||
const result = await migrateCadlFiles(files, migrateModelToScalar);
|
||||
|
||||
if (result.fileChanged.length === 0) {
|
||||
console.log("No cadl files migrated, no change detected.");
|
||||
} else {
|
||||
console.log(`Updated ${result.fileChanged.length} cadl files:`);
|
||||
for (const file of result.fileChanged) {
|
||||
console.log(` - ${file}`);
|
||||
}
|
||||
console.log("This is a best effort migration, double check everything was migrated correctly.");
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
|
@ -0,0 +1,115 @@
|
|||
import { TextRange } from "@cadl-lang/compiler";
|
||||
import { readFile, writeFile } from "fs/promises";
|
||||
import {
|
||||
CadlCompiler,
|
||||
CadlCompilers,
|
||||
CadlCompilerVersion,
|
||||
Migration,
|
||||
} from "./migrations/migration.js";
|
||||
export interface MigrationResult {
|
||||
fileChanged: string[];
|
||||
}
|
||||
|
||||
export async function migrateCadlFiles(files: string[], migration: Migration<any>) {
|
||||
const fromCompiler = await loadCompiler(migration.from);
|
||||
const toCompiler = await loadCompiler(migration.to);
|
||||
return migrateCadlFilesInternal(fromCompiler, toCompiler, files, migration);
|
||||
}
|
||||
|
||||
export async function migrateCadlContent(content: string, migration: Migration<any>) {
|
||||
const fromCompiler = await loadCompiler(migration.from);
|
||||
const toCompiler = await loadCompiler(migration.to);
|
||||
return migrateCadlContentInternal(fromCompiler, toCompiler, content, migration);
|
||||
}
|
||||
|
||||
async function loadCompiler<V extends CadlCompilerVersion>(version: V): Promise<CadlCompilers[V]> {
|
||||
try {
|
||||
return await import(`@cadl-lang/compiler-v${version}`);
|
||||
} catch {
|
||||
return await import("@cadl-lang/compiler");
|
||||
}
|
||||
}
|
||||
|
||||
async function migrateCadlFilesInternal(
|
||||
fromCompiler: CadlCompiler,
|
||||
toCompiler: CadlCompiler,
|
||||
files: string[],
|
||||
migration: Migration<any>
|
||||
): Promise<MigrationResult> {
|
||||
const result: MigrationResult = {
|
||||
fileChanged: [],
|
||||
};
|
||||
for (const file of files) {
|
||||
if (await migrateCadlFile(fromCompiler, toCompiler, file, migration)) {
|
||||
result.fileChanged.push(file);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async function migrateCadlFile(
|
||||
fromCompiler: CadlCompiler,
|
||||
toCompiler: CadlCompiler,
|
||||
filename: string,
|
||||
migration: Migration<any>
|
||||
): Promise<boolean> {
|
||||
const buffer = await readFile(filename);
|
||||
const content = buffer.toString();
|
||||
const [newContent, changed] = migrateCadlContentInternal(
|
||||
fromCompiler,
|
||||
toCompiler,
|
||||
content,
|
||||
migration
|
||||
);
|
||||
|
||||
await writeFile(filename, newContent);
|
||||
return changed;
|
||||
}
|
||||
|
||||
function migrateCadlContentInternal(
|
||||
fromCompiler: CadlCompiler,
|
||||
toCompiler: CadlCompiler,
|
||||
content: string,
|
||||
migration: Migration<any>
|
||||
): [string, boolean] {
|
||||
const parsed = fromCompiler.parse(content);
|
||||
const actions = migration
|
||||
.migrate(createMigrationContext(parsed), fromCompiler, parsed as any)
|
||||
.sort((a, b) => a.target.pos - b.target.pos);
|
||||
|
||||
if (actions.length === 0) {
|
||||
return [content, false];
|
||||
}
|
||||
const segments = [];
|
||||
let last = 0;
|
||||
for (const action of actions) {
|
||||
segments.push(content.slice(last, action.target.pos));
|
||||
segments.push(action.content);
|
||||
last = action.target.end;
|
||||
}
|
||||
const newContent = segments.join("");
|
||||
|
||||
try {
|
||||
return [(toCompiler as any).formatCadl(newContent), true];
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Failed to format new code", e);
|
||||
return [newContent, true];
|
||||
}
|
||||
}
|
||||
|
||||
function createMigrationContext(root: any) {
|
||||
function printNode(node: TextRange) {
|
||||
return root.file.text.slice(node.pos, node.end);
|
||||
}
|
||||
function printNodes(nodes: readonly TextRange[]): string {
|
||||
if (nodes.length === 0) {
|
||||
return "";
|
||||
}
|
||||
const first = nodes[0];
|
||||
const last = nodes[nodes.length - 1];
|
||||
return root.file.text.slice(first.pos, last.end);
|
||||
}
|
||||
|
||||
return { printNode, printNodes };
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
import { TextRange } from "@cadl-lang/compiler";
|
||||
|
||||
export type MigrationKind = "Syntax";
|
||||
|
||||
// Update here before release.
|
||||
export type CadlCompilerCurrent = typeof import("@cadl-lang/compiler");
|
||||
export type CadlCompilerV0_38 = CadlCompilerCurrent;
|
||||
export type CadlCompilerV0_37 = typeof import("@cadl-lang/compiler-v0.37");
|
||||
|
||||
export type CadlCompilers = {
|
||||
"0.37": CadlCompilerV0_37;
|
||||
"0.38": CadlCompilerV0_38;
|
||||
};
|
||||
|
||||
export type CadlCompiler = CadlCompilers[keyof CadlCompilers];
|
||||
export type CadlCompilerVersion = keyof CadlCompilers;
|
||||
|
||||
export interface MigrationContext {
|
||||
/**
|
||||
* Print the text range as it is.
|
||||
*/
|
||||
printNode(node: TextRange): string;
|
||||
|
||||
/**
|
||||
* Print the entire text range from teh first node to the last.(Including anything in between the nodes.)
|
||||
*/
|
||||
printNodes(node: readonly TextRange[]): string;
|
||||
}
|
||||
|
||||
export interface Migration<TFrom extends CadlCompilerVersion> {
|
||||
name: string;
|
||||
kind: "Syntax";
|
||||
/**
|
||||
* Compiler version.
|
||||
*/
|
||||
from: TFrom;
|
||||
|
||||
/**
|
||||
* Target version
|
||||
*/
|
||||
to: CadlCompilerVersion;
|
||||
|
||||
/**
|
||||
* Migrate logic.
|
||||
* @param compilerInstance Instance of the compiler at the `from` version.
|
||||
* @param script Cadl Script source node.
|
||||
*/
|
||||
migrate(
|
||||
context: MigrationContext,
|
||||
compilerInstance: CadlCompilers[TFrom],
|
||||
script: unknown
|
||||
): MigrateAction[];
|
||||
}
|
||||
|
||||
export interface MigrateAction {
|
||||
target: TextRange; // Cadl compiler node
|
||||
/**
|
||||
* Replaced content
|
||||
*/
|
||||
content: string;
|
||||
}
|
||||
|
||||
export function createMigration<TFrom extends CadlCompilerVersion>(
|
||||
migration: Migration<TFrom>
|
||||
): Migration<TFrom> {
|
||||
return migration;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
import type { CadlScriptNode, TemplateParameterDeclarationNode } from "@cadl-lang/compiler-v0.37";
|
||||
import {
|
||||
CadlCompilerV0_37,
|
||||
createMigration,
|
||||
MigrateAction,
|
||||
MigrationContext,
|
||||
} from "../migration.js";
|
||||
|
||||
export const migrateModelToScalar = createMigration({
|
||||
name: "Migrate Model To scalar",
|
||||
kind: "Syntax",
|
||||
from: "0.37",
|
||||
to: "0.38",
|
||||
migrate: (
|
||||
{ printNode, printNodes }: MigrationContext,
|
||||
compilerV37: CadlCompilerV0_37,
|
||||
root: CadlScriptNode
|
||||
) => {
|
||||
function printTemplateParameters(parameters: readonly TemplateParameterDeclarationNode[]) {
|
||||
if (parameters.length === 0) {
|
||||
return "";
|
||||
}
|
||||
return `<${parameters.map((x) => printNode(x)).join(", ")}>`;
|
||||
}
|
||||
|
||||
const actions: MigrateAction[] = [];
|
||||
compilerV37.visitChildren(root, (node) => {
|
||||
if (
|
||||
node.kind === compilerV37.SyntaxKind.ModelStatement &&
|
||||
node.is &&
|
||||
node.is.kind === compilerV37.SyntaxKind.TypeReference &&
|
||||
node.is.target.kind === compilerV37.SyntaxKind.Identifier &&
|
||||
builtInTypes.has(node.is.target.sv) &&
|
||||
node.properties.length === 0
|
||||
) {
|
||||
const decorators = printNodes(node.decorators);
|
||||
actions.push({
|
||||
target: node,
|
||||
content: `${decorators ? decorators + " " : ""}scalar ${
|
||||
node.id.sv
|
||||
}${printTemplateParameters(node.templateParameters)} extends ${printNode(node.is)};`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return actions;
|
||||
},
|
||||
});
|
||||
|
||||
const builtInTypes = new Set([
|
||||
"bytes",
|
||||
"numeric",
|
||||
"integer",
|
||||
"float",
|
||||
"int64",
|
||||
"safeint",
|
||||
"int32",
|
||||
"int16",
|
||||
"int8",
|
||||
"uint64",
|
||||
"uint32",
|
||||
"uint16",
|
||||
"uint8",
|
||||
"float64",
|
||||
"float32",
|
||||
"string",
|
||||
"plainDate",
|
||||
"plainTime",
|
||||
"zonedDateTime",
|
||||
"duration",
|
||||
"boolean",
|
||||
]);
|
|
@ -0,0 +1,15 @@
|
|||
import { globby } from "globby";
|
||||
import { join } from "path";
|
||||
|
||||
export async function findCadlFiles(root: string, ignore: string[] = []) {
|
||||
return findFiles([normalizePath(join(root, "**/*.cadl"))], ignore);
|
||||
}
|
||||
|
||||
export async function findFiles(include: string[], ignore: string[] = []): Promise<string[]> {
|
||||
const patterns = [...include, "!**/node_modules", ...ignore.map((x) => `!${x}`)];
|
||||
return globby(patterns);
|
||||
}
|
||||
|
||||
export function normalizePath(path: string): string {
|
||||
return path.replace(/\\/g, "/");
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
import { strictEqual } from "assert";
|
||||
import { migrateCadlContent } from "../src/migrate.js";
|
||||
import { migrateModelToScalar } from "../src/migrations/v0.38/model-to-scalars.js";
|
||||
|
||||
describe("migration: model to scalars", () => {
|
||||
it("convert", async () => {
|
||||
const [result] = await migrateCadlContent(
|
||||
`
|
||||
model foo is string;
|
||||
|
||||
model bar {}
|
||||
|
||||
model foo is bar;
|
||||
|
||||
@test
|
||||
@other
|
||||
@get model Resource<T> is int32;
|
||||
`,
|
||||
migrateModelToScalar
|
||||
);
|
||||
|
||||
strictEqual(
|
||||
result.trim(),
|
||||
`
|
||||
scalar foo extends string;
|
||||
|
||||
model bar {}
|
||||
|
||||
model foo is bar;
|
||||
|
||||
@test
|
||||
@other
|
||||
@get
|
||||
scalar Resource<T> extends int32;
|
||||
`.trim()
|
||||
);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"references": [{ "path": "../compiler/tsconfig.json" }],
|
||||
"compilerOptions": {
|
||||
"module": "Node16",
|
||||
"moduleResolution": "Node16",
|
||||
"skipLibCheck": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": ".",
|
||||
"tsBuildInfoFile": "temp/tsconfig.tsbuildinfo",
|
||||
"types": ["node", "mocha"]
|
||||
},
|
||||
"include": ["src/**/*.ts", "test/**/*.ts"]
|
||||
}
|
|
@ -126,6 +126,12 @@
|
|||
"reviewCategory": "production",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@cadl-lang/migrate",
|
||||
"projectFolder": "packages/migrate",
|
||||
"reviewCategory": "production",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@cadl-lang/library-linter",
|
||||
"projectFolder": "packages/library-linter",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
{ "path": "packages/openapi/tsconfig.json" },
|
||||
{ "path": "packages/openapi3/tsconfig.json" },
|
||||
{ "path": "packages/lint/tsconfig.json" },
|
||||
{ "path": "packages/migrate/tsconfig.json" },
|
||||
{ "path": "packages/cadl-vscode/tsconfig.json" },
|
||||
{ "path": "packages/internal-build-utils/tsconfig.json" },
|
||||
{ "path": "packages/tmlanguage-generator/tsconfig.json" },
|
||||
|
|
Загрузка…
Ссылка в новой задаче