Skip to content

Commit 5543470

Browse files
authored
Merge pull request #2 from roguib/path-resolver
Path resolver
2 parents 6c898b5 + c32e690 commit 5543470

12 files changed

+243
-119
lines changed

.vscode/launch.json

+3-9
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,11 @@
1919
"request": "launch",
2020
"name": "End to end execution",
2121
"preLaunchTask": "npm: build:cjs",
22-
"program": "./build/ng-vs-snippets",
23-
"args":
24-
[
25-
"--dir",
26-
"./src",
27-
"--output",
28-
"./.vscode"
29-
],
22+
"program": "./build/@roguib/ng-vs-snippets.js",
23+
"args": ["--dir", "./src", "--output", "./.vscode"],
3024
"console": "integratedTerminal",
3125
"internalConsoleOptions": "neverOpen",
32-
"disableOptimisticBPs": true,
26+
"disableOptimisticBPs": true
3327
}
3428
]
3529
}

README.md

+16-15
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,34 @@
11
# ng-vs-snippets
2-
![ts](https://badgen.net/badge/Built%20With/TypeScript/blue) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![made-for-VSCode](https://img.shields.io/badge/Made%20for-VSCode-1f425f.svg)](https://code.visualstudio.com/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)
3-
42

3+
![ts](https://badgen.net/badge/Built%20With/TypeScript/blue) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![made-for-VSCode](https://img.shields.io/badge/Made%20for-VSCode-1f425f.svg)](https://code.visualstudio.com/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)
54

65
Automatic VS Code snippet file generation for Angular codebases. Seamlessly maintain up-to-date VS Code snippets of all of your code.
76

87
Currently, we support snippet generation from the following Angular elements:
98

109
<center>
1110

12-
| Element | Status |
13-
|-----------|:-----------------------------------------:|
14-
| Component | :white_check_mark: Supported |
15-
| Directive | :construction_worker: Not yet supported |
16-
| Pipe | :construction_worker: Not yet supported |
11+
| Element | Status |
12+
| --------- | :-------------------------------------: |
13+
| Component | :white_check_mark: Supported |
14+
| Directive | :construction_worker: Not yet supported |
15+
| Pipe | :construction_worker: Not yet supported |
1716

1817
</center>
1918

2019
## Installation
2120

22-
Install ```ng-vs-snippets``` as a dev-dependency in your Angular project. To do so, run:
21+
Install `ng-vs-snippets` as a dev-dependency in your Angular project. To do so, run:
2322

2423
```
25-
npm i ng-vs-snippets --save-dev
24+
npm i @roguib/ng-vs-snippets --save-dev
2625
```
2726

28-
Create a ```package.json``` script to extract snippets from your codebase:
27+
Create a `package.json` script to extract snippets from your codebase:
2928

3029
```json
3130
"scripts": {
32-
"ng-vs-snippets": "ng-vs-snippets --dir ./src --output ./.vscode",
31+
"ng-vs-snippets": "ng-vs-snippets --dir . --output ./.vscode",
3332
},
3433
```
3534

@@ -39,21 +38,23 @@ Execute the script by running:
3938
npm run ng-vs-snippets
4039
```
4140

42-
The script will generate a ```out.code-snippets``` file containing all the definitions. **Make sure you don't have any file with the same name** since the data contained in that file **is going to be replaced**.
41+
The script will generate a `out.code-snippets` file containing all the definitions. **Make sure you don't have any file with the same name** since the data contained in that file **is going to be replaced**.
4342

4443
## Troubleshooting
45-
Sometimes, due to VS Code configuration issues, snippets don't appear in the suggestion's dropdown. Make sure to specify, in VS Code ```settings.json``` configuration file the following properties:
44+
45+
Sometimes, due to VS Code configuration issues, snippets don't appear in the suggestion's dropdown. Make sure to specify, in VS Code `settings.json` configuration file the following properties:
4646

4747
```json
4848
"editor.tabCompletion": "on",
4949
"editor.snippetSuggestions": "top"
5050
```
51-
If this doesn't fix the problem, open the command palette and search for ```Preferences: Configure User Snippets``` to ensure the editor is considering the fille where your generated snippets are defined.
51+
52+
If this doesn't fix the problem, open the command palette and search for `Preferences: Configure User Snippets` to ensure the editor is considering the fille where your generated snippets are defined.
5253

5354
## Documentation
5455

5556
You can find the [full document design at this url]().
5657

5758
## Contributing
5859

59-
Pull requests are welcome :) Make sure to create an issue first so anyone's work is overlaped.
60+
Pull requests are welcome :) Make sure to create an issue first so anyone's work is overlaped.

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414
"angular",
1515
"vs snippets"
1616
],
17-
"main": "build/ng-vs-snippets.js",
18-
"types": "build/ng-vs-snippets.d.ts",
17+
"main": "build/@roguib/ng-vs-snippets.js",
18+
"types": "build/@roguib/ng-vs-snippets.d.ts",
1919
"bin": {
20-
"ng-vs-snippets": "build/ng-vs-snippets.js"
20+
"ng-vs-snippets": "build/@roguib/ng-vs-snippets.js"
2121
},
2222
"scripts": {
2323
"build:cjs": "rollup -c",
2424
"check": "tsc",
25-
"run": "node ./build/index.js",
25+
"run": "node ./build/@roguib/ng-vs-snippets.js",
2626
"test": "npm run build:cjs && jest ./tests/*"
2727
},
2828
"dependencies": {

src/index.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
const fs = require("fs");
21
const path = require("path");
3-
const readline = require("readline");
42
const argv = process.argv;
53
import * as walker from "./walker";
64
import * as parser from "./parser";
@@ -17,6 +15,9 @@ let config: ICLIConfig = {
1715

1816
const parseArgs = (args: string[]) => {
1917
// TODO: Include multiple options
18+
19+
logger.log("args:", args);
20+
2021
while (args.length > 0) {
2122
const arg = args.shift();
2223

@@ -52,25 +53,24 @@ export const verifyArgs = () => {
5253
if (config.outputDir == null) {
5354
logger.err("No output directory specified. Aborting.");
5455
}
55-
}
56+
};
5657

5758
export const run = async (args: string[]) => {
5859
parseArgs(args);
5960
verifyArgs();
60-
// const config = parseArgs(args);
6161

6262
if (config.debug) {
6363
logger.enableDebugger();
6464
}
65+
66+
process.env.ROOT_PROJECT_PATH = config.workingDir || path.posix.resolve();
67+
6568
let candidateFilePaths: Array<string> = walker.walker(
66-
config.workingDir || path.posix.resolve(),
69+
process.env.ROOT_PROJECT_PATH as string,
6770
[]
6871
);
6972
let fileData: Array<File> = parser.parser(candidateFilePaths);
70-
generator.generator(
71-
fileData,
72-
config.outputDir as string
73-
);
73+
generator.generator(fileData, config.outputDir as string);
7474
};
7575

7676
run(argv.slice(2, argv.length));

src/parser.ts

+36-64
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const path = require("path");
33

44
import { File, Input, Output } from "./shared/IFile";
55
import logger from "./shared/logger";
6+
import pathResolver from "./utils/path-resolver";
67

78
// selectors
89
const componentSelector = /export(\s+)class(\s+)[a-zA-Z0-9-_]+/g;
@@ -31,11 +32,11 @@ const regularOutputSelector = /@Output\(\)(\s+)[a-zA-Z0-9-_]+:(\s+)EventEmitter<
3132

3233
// other
3334
const extendedClassSelector = /export(\s+)class(\s+)[a-zA-Z0-9-_]+(\s+)extends(\s+)[a-zA-Z0-9-_]+/g;
34-
const extendedClassPathSelector = /import(\s+){(\s+)[a-zA-Z0-9-_]+(\s+)}(\s+)from(\s+)[\/A-Za-z0-9."'_-]+/g;
35+
const extendedClassPathSelector = /import(\s+){(\s+)[a-zA-Z0-9-_]+(\s+)}(\s+)from(\s+)[\/\@A-Za-z0-9."'_-]+/g;
3536
// TODO: class implementation with inputs/outputs defined
3637

37-
// TODO: Test in in other OS (github actions)
38-
// TODO: Read files synchronously
38+
// TODO: Test in other OS (github actions)
39+
// TODO: Read files asynchronously to improve performance?
3940
export const parser = (filePaths: Array<string>): Array<File> => {
4041
let result: Array<File> = [];
4142
// a temporal variable used for storing @Inputs/@Outputs declared on a parent class
@@ -61,8 +62,7 @@ export const parser = (filePaths: Array<string>): Array<File> => {
6162
continue;
6263
}
6364

64-
let fileNameData: Array<string> =
65-
file?.match(componentSelector) || [];
65+
let fileNameData: Array<string> = file?.match(componentSelector) || [];
6666
if (fileNameData.length === 0) {
6767
logger.warn("Component tag not defined by any class.");
6868
continue;
@@ -93,15 +93,14 @@ export const parser = (filePaths: Array<string>): Array<File> => {
9393
// Input() foo: 'type1' | 'type2'
9494
let inputs: Array<Input> = [];
9595
let inputsData: Array<string> =
96-
file?.match(
97-
regularInputLiteralTypeSelector
98-
) || [];
96+
file?.match(regularInputLiteralTypeSelector) || [];
9997
for (let input of inputsData) {
100-
logger.log('inputs parsed:', inputsData);
98+
logger.log("inputs parsed:", inputsData);
10199
let tmp: Array<string> = input.replace(/(\s)+/g, " ").split(" ");
102100
let type = tmp
103101
.slice(2, tmp.length)
104102
.join()
103+
.replace(/\"/g, "'")
105104
.replace(";", "")
106105
.replace(/,/g, "");
107106
inputs.push({
@@ -113,13 +112,9 @@ export const parser = (filePaths: Array<string>): Array<File> => {
113112

114113
// @Input() variableName: type; and @Input() variableName: number = 9;
115114
inputsData = [];
116-
inputsData =
117-
file?.match(
118-
regularInputWithTypeSelector
119-
) || [];
115+
inputsData = file?.match(regularInputWithTypeSelector) || [];
120116
for (let input of inputsData) {
121117
let tmp: Array<string> = input.replace(/(\s+)/g, " ").split(" ");
122-
logger.log("input data", inputsData);
123118
inputs.push({
124119
inputName: tmp[1].replace(":", ""),
125120
type: tmp[2].replace(";", ""),
@@ -129,16 +124,11 @@ export const parser = (filePaths: Array<string>): Array<File> => {
129124

130125
inputsData = [];
131126
// @Input('inputName') varName: type; and @Input("inputName") varName: type
132-
inputsData =
133-
file?.match(
134-
customNameInputWithTypeSelector
135-
) || [];
127+
inputsData = file?.match(customNameInputWithTypeSelector) || [];
136128
for (let input of inputsData) {
137129
let tmp: Array<string> = input.replace(/(\s+)/g, " ").split(" ");
138-
const inputName = (tmp[0].match(/('|")[a-zA-Z0-9-_]+('|")/g) || [])[0].replace(
139-
/'|"/g,
140-
""
141-
);
130+
const inputName = (tmp[0].match(/('|")[a-zA-Z0-9-_]+('|")/g) ||
131+
[])[0].replace(/'|"/g, "");
142132
inputs.push({
143133
inputName,
144134
type: tmp[2].replace(";", ""),
@@ -149,10 +139,7 @@ export const parser = (filePaths: Array<string>): Array<File> => {
149139
// @Input('inputNameC') varName = 'adv';
150140
// @Input("inputNameD") varName = 2354;
151141
inputsData = [];
152-
inputsData =
153-
file?.match(
154-
setterInputCustomNameSelector
155-
) || [];
142+
inputsData = file?.match(setterInputCustomNameSelector) || [];
156143
for (let input of inputsData) {
157144
let tmp: Array<string> = input.replace(/(\s+)/g, " ").split(" ");
158145
const inputName = (tmp[0].match(/('|")[a-zA-Z0-9-_]+('|")/g) || [
@@ -167,10 +154,7 @@ export const parser = (filePaths: Array<string>): Array<File> => {
167154

168155
//@Input() set foo(value) {}
169156
inputsData = [];
170-
inputsData =
171-
file?.match(
172-
setterInputSelector
173-
) || [];
157+
inputsData = file?.match(setterInputSelector) || [];
174158
for (let input of inputsData) {
175159
let tmp: Array<string> = input.replace(/(\s+)/g, " ").split(" ");
176160
const inputName = tmp[2].replace(/(\s+)/g, "").split("(")[0];
@@ -183,10 +167,7 @@ export const parser = (filePaths: Array<string>): Array<File> => {
183167

184168
//@Input() set foo(value: type) {}
185169
inputsData = [];
186-
inputsData =
187-
file?.match(
188-
setterInputWithTypeSelector
189-
) || [];
170+
inputsData = file?.match(setterInputWithTypeSelector) || [];
190171
for (let input of inputsData) {
191172
let tmp: Array<string> = input.replace(/(\s+)/g, " ").split(" ");
192173
const inputName = tmp[2].replace(/(\s+)/g, "").split("(")[0];
@@ -200,18 +181,15 @@ export const parser = (filePaths: Array<string>): Array<File> => {
200181

201182
//@Input() set foo(value: 'type1' | 'type2') {}
202183
inputsData = [];
203-
inputsData =
204-
file?.match(
205-
setterInputLiteralTypeSelector
206-
) || [];
184+
inputsData = file?.match(setterInputLiteralTypeSelector) || [];
207185
for (let input of inputsData) {
208186
let tmp: Array<string> = input.replace(/(\s+)/g, " ").split(" ");
209187
const inputName = tmp[2].replace(/(\s+)/g, "").split("(")[0];
210188
const type = tmp
211-
.slice(3, tmp.length)
212-
.join()
213-
.replace(/'|"|\)/g, "")
214-
.replace(/,/g, " ");
189+
.slice(3, tmp.length)
190+
.join()
191+
.replace(/'|"|\)/g, "")
192+
.replace(/,/g, " ");
215193
inputs.push({
216194
inputName,
217195
type,
@@ -239,10 +217,7 @@ export const parser = (filePaths: Array<string>): Array<File> => {
239217

240218
let outputs: Array<Output> = [];
241219
// only @Output() buttonClick: EventEmitter<any> = new EventEmitter(); for now
242-
let outputsData: Array<string> =
243-
file?.match(
244-
regularOutputSelector
245-
) || [];
220+
let outputsData: Array<string> = file?.match(regularOutputSelector) || [];
246221
for (let output of outputsData) {
247222
let tmp: Array<string> = output.replace(/(\s+)/g, " ").split(" ");
248223
outputs.push({
@@ -257,33 +232,23 @@ export const parser = (filePaths: Array<string>): Array<File> => {
257232
logger.log("Outputs detected:", outputs);
258233

259234
let extendedClassPath;
260-
if (
261-
file?.match(
262-
extendedClassSelector
263-
)
264-
) {
235+
if (file?.match(extendedClassSelector)) {
265236
// we should see if the extended class is in tmp and if not extract the inputs defined inside
266237
let matchExtendedClass: Array<string> =
267-
file?.match(
268-
extendedClassSelector
269-
) || [];
238+
file?.match(extendedClassSelector) || [];
270239
// resolve the path of the class
271240
let extendedClass: string = matchExtendedClass[0]
272241
.replace(/(\s+)/g, " ")
273242
.split(" ")[4];
274243
logger.log("extendedClassName:", extendedClass);
275244
let matchExtendedClassPath: Array<string> =
276-
file?.match(
277-
extendedClassPathSelector
278-
) || [];
279-
// TODO: Document this in notes. Notice that by using path.join(path.dirname(fullComponentClassPath), relative path of the base path from ComponentClassPath) resolves into the full path of the base path
280-
extendedClassPath = path.join(
281-
path.dirname(filePath),
245+
file?.match(extendedClassPathSelector) || [];
246+
247+
extendedClassPath = pathResolver.resolve(
248+
filePath,
282249
matchExtendedClassPath[0]
283-
.replace(/(\s+)/g, " ")
284-
.replace(/"/g, "")
285-
.split(" ")[5] + ".ts"
286250
);
251+
287252
logger.log("path:", extendedClassPath);
288253
}
289254

@@ -297,8 +262,15 @@ export const parser = (filePaths: Array<string>): Array<File> => {
297262
extendedClassFilepath: extendedClassPath || undefined,
298263
});
299264
} else {
265+
/**
266+
* TODO: Instead of working with relative paths and converting them
267+
* to absolute when needed, we can start the exec by transforming every
268+
* relative path to absolute, and then clean up the resolve calls in the program
269+
* that transforms the code into an spaguetti one. Also it could help by reducing
270+
* the amount of times we call path.join(path.posix.resolve(), path);
271+
*/
300272
tmp.push({
301-
fileLocation: filePath,
273+
fileLocation: path.resolve(filePath),
302274
inputs: inputs,
303275
outputs: outputs,
304276
extendedClassFilepath: undefined,

0 commit comments

Comments
 (0)