Skip to content

Commit 4a3ffa6

Browse files
ckairenjnlycklama
authored andcommitted
[TypeSpec Validation] verify folder structure (#25712)
* folder structure * typespec folder depth limit * main.tsp and client.tsp * fix windows separator issue
1 parent d7a39b6 commit 4a3ffa6

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

eng/tools/TypeSpecValidation/src/rules/folder-structure.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { globby } from "globby";
2+
import path from "path";
23
import { Rule } from "../rule.js";
34
import { RuleResult } from "../rule-result.js";
5+
import { checkFileExists } from "../utils.js";
46

57
export class FolderStructureRule implements Rule {
68
readonly name = "FolderStructure";
@@ -18,6 +20,57 @@ export class FolderStructureRule implements Rule {
1820
}
1921
});
2022

23+
// Verify top level folder is lower case
24+
let folderStruct = folder.split("/");
25+
if (folderStruct[1].match(/[A-Z]/g)) {
26+
success = false;
27+
errorOutput += `Invalid folder name. Folders under specification/ must be lower case.\n`;
28+
}
29+
30+
let packageFolder = folderStruct[folderStruct.length - 1];
31+
32+
// Verify package folder is at most 3 levels deep
33+
if (folderStruct.length > 4) {
34+
success = false;
35+
errorOutput += `Please limit TypeSpec folder depth to 3 levels or less`;
36+
}
37+
38+
// Verify second level folder is capitalized after each '.'
39+
if (
40+
/(^|\. *)([a-z])/g.test(packageFolder) &&
41+
!["data-plane", "resource-manager"].includes(packageFolder)
42+
) {
43+
success = false;
44+
errorOutput += `Invalid folder name. Folders under specification/${folderStruct[1]} must be capitalized after each '.'\n`;
45+
}
46+
47+
// Verify 'Shared' follows 'Management'
48+
if (packageFolder.includes("Management") && packageFolder.includes("Shared")) {
49+
if (!packageFolder.includes("Management.Shared")) {
50+
success = false;
51+
errorOutput += `Invalid folder name. For management libraries with a shared component, 'Shared' should follow 'Management'.`;
52+
}
53+
}
54+
55+
// Verify tspconfig, main.tsp, examples/
56+
let containsMinStruct =
57+
(await checkFileExists(path.join(folder, "main.tsp"))) ||
58+
(await checkFileExists(path.join(folder, "client.tsp")));
59+
60+
if (await checkFileExists(path.join(folder, "main.tsp"))) {
61+
containsMinStruct =
62+
containsMinStruct && (await checkFileExists(path.join(folder, "examples")));
63+
}
64+
65+
if (!packageFolder.includes("Shared")) {
66+
containsMinStruct =
67+
containsMinStruct && (await checkFileExists(path.join(folder, "tspconfig.yaml")));
68+
}
69+
if (!containsMinStruct) {
70+
success = false;
71+
errorOutput += `Invalid folder structure. Package must contain main.tsp or client.tsp, tspconfig.yaml, and examples folder if there's main.tsp.`;
72+
}
73+
2174
return {
2275
success: success,
2376
stdOutput: stdOutput,

0 commit comments

Comments
 (0)