Skip to content

Commit 05a8222

Browse files
committed
In names.ts:
Added comments. Updated regular expressions so they work for modules and non-module files. Added functions makeFilePathRegexPattern, makeFilePath, makeProjectInfoPath, isValidModuleFileName, isValidProjectInfoFileName.
1 parent 98d0d18 commit 05a8222

File tree

1 file changed

+131
-38
lines changed

1 file changed

+131
-38
lines changed

src/storage/names.ts

Lines changed: 131 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,80 @@
2222
import * as storageModule from './module';
2323

2424

25+
/**
26+
* Paths and file names for Blocks Projects
27+
*
28+
* Files in a project are stored in a directory whose name is the project name. All files have
29+
* the extension '.json' and contain JSON text.
30+
*
31+
* Project information is stored in a file called 'project.info.json'.
32+
*
33+
* Modules
34+
* Files that contain blocks are called modules. During deployment, a Python file is created for
35+
* each module. Each Python file contains a Python class definition.
36+
* There are three types of modules:
37+
* robot
38+
* mechanism
39+
* opmode
40+
* A project consists of:
41+
* one project information file named 'project.info.json'
42+
* one robot module, named 'Robot.robot.json'
43+
* zero or more mechanisms, with the extension '.mechanism.json'
44+
* zero or more opmodes, with the extension '.opmode.json'
45+
*
46+
* The file path of the project info file is <ProjectName>/project.info.json.
47+
* The file path of a module is <ProjectName>/<ClassName>.<ModuleType>.json.
48+
*/
49+
50+
// The class name of the Robot module that is created automatically when a new project is created.
2551
export const CLASS_NAME_ROBOT = 'Robot';
52+
53+
// The class name of the OpMode module that is created automatically when a new project is created.
2654
export const CLASS_NAME_TELEOP = 'Teleop';
2755

56+
// The extension of all JSON files is .json.
2857
export const JSON_FILE_EXTENSION = '.json';
58+
59+
// The extension of a downloaded project is .blocks.
2960
export const UPLOAD_DOWNLOAD_FILE_EXTENSION = '.blocks';
3061

62+
// The file name of the project info file.
63+
const PROJECT_INFO_FILE_NAME = 'project.info.json';
64+
65+
// The file name of the project info file.
66+
const ROBOT_MODULE_FILE_NAME = 'Robot.robot.json';
67+
68+
// A project name starts with an uppercase letter, followed by alphanumeric characters.
3169
const REGEX_PROJECT_NAME_PART = '[A-Z][A-Za-z0-9]*';
70+
71+
// A module's class name starts with an uppercase letter, followed by alphanumeric characters.
3272
const REGEX_CLASS_NAME_PART = '[A-Z][A-Za-z0-9]*';
73+
74+
// This regex is used to validate a class name
75+
const REGEX_CLASS_NAME = '^' + REGEX_CLASS_NAME_PART + '$'
76+
77+
// The module type of a module path is either .robot, .mechanism, or .opmode.
3378
const REGEX_MODULE_TYPE_PART = '\.(robot|mechanism|opmode)';
34-
const REGEX_MODULE_PATH = '^(' + REGEX_PROJECT_NAME_PART + ')/(' + REGEX_CLASS_NAME_PART + ')' +
79+
80+
// This regex is used to match the robot module path in any project.
81+
export const REGEX_ROBOT_MODULE_PATH = '^' + REGEX_PROJECT_NAME_PART + '/' + escapeRegExp(ROBOT_MODULE_FILE_NAME) + '$';
82+
83+
// This regex is used to extract the project name and file name from a file path.
84+
const REGEX_FILE_PATH = '^(' + REGEX_PROJECT_NAME_PART + ')/(.*' + escapeRegExp(JSON_FILE_EXTENSION) + ')$';
85+
86+
// This regex is used to extract the class name from a module path.
87+
const REGEX_MODULE_PATH = '^' + REGEX_PROJECT_NAME_PART + '/(' + REGEX_CLASS_NAME_PART + ')' +
3588
REGEX_MODULE_TYPE_PART + escapeRegExp(JSON_FILE_EXTENSION) + '$';
36-
const REGEX_MODULE_PATH_TO_FILE_NAME = '^' + REGEX_PROJECT_NAME_PART + '/(' + REGEX_CLASS_NAME_PART +
37-
REGEX_MODULE_TYPE_PART + escapeRegExp(JSON_FILE_EXTENSION) + ')$';
38-
const REGEX_FILE_NAME = '^(' + REGEX_CLASS_NAME_PART + ')' +
89+
90+
// This regex is used to extract the class name from a module file name.
91+
const REGEX_MODULE_FILE_NAME = '^(' + REGEX_CLASS_NAME_PART + ')' +
3992
REGEX_MODULE_TYPE_PART + escapeRegExp(JSON_FILE_EXTENSION) + '$';
4093

4194
/**
4295
* Returns true if the given name is a valid class name.
4396
*/
4497
export function isValidClassName(name: string): boolean {
45-
if (name) {
46-
return new RegExp('^' + REGEX_CLASS_NAME_PART + '$').test(name);
47-
}
48-
return false;
98+
return new RegExp(REGEX_CLASS_NAME).test(name);
4999
}
50100

51101
/**
@@ -84,88 +134,131 @@ export function snakeCaseToPascalCase(snakeCaseName: string): string {
84134
}
85135

86136
/**
87-
* Returns the module path regex pattern for modules in the given project.
137+
* Returns a regex pattern that matches all file paths in the given project.
138+
*/
139+
export function makeFilePathRegexPattern(projectName: string): string {
140+
return '^' + escapeRegExp(projectName) + '/' +
141+
'.*' + escapeRegExp(JSON_FILE_EXTENSION) + '$';
142+
}
143+
144+
/**
145+
* Returns a regex pattern that matches all module paths in the given project.
88146
*/
89147
export function makeModulePathRegexPattern(projectName: string): string {
90-
return '^' + escapeRegExp(projectName) + '/' + REGEX_CLASS_NAME_PART +
91-
REGEX_MODULE_TYPE_PART + escapeRegExp(JSON_FILE_EXTENSION) + '$';
148+
return '^' + escapeRegExp(projectName) + '/' +
149+
REGEX_CLASS_NAME_PART + REGEX_MODULE_TYPE_PART + escapeRegExp(JSON_FILE_EXTENSION) + '$';
92150
}
93151

152+
/**
153+
* Escapes the given text so it can be used literally in a regular expression.
154+
*/
94155
function escapeRegExp(text: string): string {
95156
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
96157
}
97158

159+
/**
160+
* Returns the file path for the given project name and file name.
161+
*/
162+
export function makeFilePath(projectName: string, fileName: string): string {
163+
return projectName + '/' + fileName;
164+
}
165+
166+
/**
167+
* Returns the project info path for the given project name.
168+
*/
169+
export function makeProjectInfoPath(projectName: string): string {
170+
return makeFilePath(projectName, PROJECT_INFO_FILE_NAME);
171+
}
172+
98173
/**
99174
* Returns the module path for the given project name and class name.
100175
*/
101176
export function makeModulePath(
102177
projectName: string, className: string, moduleType: storageModule.ModuleType): string {
103-
return projectName + '/' + className + '.' + moduleType + JSON_FILE_EXTENSION;
178+
return makeFilePath(projectName, className + '.' + moduleType + JSON_FILE_EXTENSION);
104179
}
105180

106181
/**
107-
* Returns the robot module path for the given project names.
182+
* Returns the robot module path for the given project name.
108183
*/
109184
export function makeRobotPath(projectName: string): string {
110185
return makeModulePath(projectName, CLASS_NAME_ROBOT, storageModule.ModuleType.ROBOT);
111186
}
112187

113188
/**
114-
* Returns the project name for given module path.
189+
* Returns the project name for given file path.
115190
*/
116-
export function getProjectName(modulePath: string): string {
117-
const regex = new RegExp(REGEX_MODULE_PATH);
118-
const result = regex.exec(modulePath)
191+
export function getProjectName(filePath: string): string {
192+
const regex = new RegExp(REGEX_FILE_PATH);
193+
const result = regex.exec(filePath)
119194
if (!result) {
120-
throw new Error('Unable to extract the project name from "' + modulePath + '"');
195+
throw new Error('Unable to extract the project name from "' + filePath + '"');
121196
}
122197
return result[1];
123198
}
124199

125200
/**
126-
* Returns the file name for given module path.
201+
* Returns the file name for given file path.
127202
*/
128-
export function getFileName(modulePath: string): string {
129-
const regex = new RegExp(REGEX_MODULE_PATH_TO_FILE_NAME);
130-
const result = regex.exec(modulePath)
203+
export function getFileName(filePath: string): string {
204+
const regex = new RegExp(REGEX_FILE_PATH);
205+
const result = regex.exec(filePath)
131206
if (!result) {
132-
throw new Error('Unable to extract the project name from "' + modulePath + '"');
207+
throw new Error('Unable to extract the file name from "' + filePath + '"');
133208
}
134-
return result[1];
209+
return result[2];
210+
}
211+
212+
/**
213+
* Returns true if the given file name is a valid module file name.
214+
*/
215+
export function isValidModuleFileName(fileName: string): boolean {
216+
return new RegExp(REGEX_MODULE_FILE_NAME).test(fileName);
217+
}
218+
219+
/**
220+
* Returns true if the given file name is a valid project info file name.
221+
*/
222+
export function isValidProjectInfoFileName(fileName: string): boolean {
223+
if (fileName === PROJECT_INFO_FILE_NAME) {
224+
return true;
225+
}
226+
return false;
135227
}
136228

229+
137230
/**
138-
* Returns the class name for given module path or file name.
231+
* Returns the class name for given module path or module file name.
139232
*/
140-
export function getClassName(modulePathOrFileName: string): string {
233+
export function getClassName(modulePathOrModuleFileName: string): string {
141234
let regex = new RegExp(REGEX_MODULE_PATH);
142-
let result = regex.exec(modulePathOrFileName);
235+
let result = regex.exec(modulePathOrModuleFileName);
143236
if (result) {
144-
return result[2];
237+
return result[1];
145238
}
146-
regex = new RegExp(REGEX_FILE_NAME);
147-
result = regex.exec(modulePathOrFileName);
239+
regex = new RegExp(REGEX_MODULE_FILE_NAME);
240+
result = regex.exec(modulePathOrModuleFileName);
148241
if (result) {
149242
return result[1];
150243
}
151-
throw new Error('Unable to extract the class name from "' + modulePathOrFileName + '"');
244+
throw new Error('Unable to extract the class name from "' + modulePathOrModuleFileName + '"');
152245
}
153246

154247
/**
155-
* Returns the module type for given module path or file name.
248+
* Returns the module type for given module path or module file name.
156249
*/
157-
export function getModuleType(modulePathOrFileName: string): storageModule.ModuleType {
250+
export function getModuleType(modulePathOrModuleFileName: string): storageModule.ModuleType {
158251
let regex = new RegExp(REGEX_MODULE_PATH);
159-
let result = regex.exec(modulePathOrFileName);
252+
let result = regex.exec(modulePathOrModuleFileName);
160253
if (result) {
161-
return storageModule.stringToModuleType(result[3]);
254+
return storageModule.stringToModuleType(result[2]);
162255
}
163-
regex = new RegExp(REGEX_FILE_NAME);
164-
result = regex.exec(modulePathOrFileName);
256+
regex = new RegExp(REGEX_MODULE_FILE_NAME);
257+
result = regex.exec(modulePathOrModuleFileName);
165258
if (result) {
166259
return storageModule.stringToModuleType(result[2]);
167260
}
168-
throw new Error('Unable to extract the module type from "' + modulePathOrFileName + '"');
261+
throw new Error('Unable to extract the module type from "' + modulePathOrModuleFileName + '"');
169262
}
170263

171264
/**

0 commit comments

Comments
 (0)