-
Notifications
You must be signed in to change notification settings - Fork 3
/
extension.js
149 lines (120 loc) · 5.41 KB
/
extension.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
const vscode = require('vscode');
const fs = require("fs");
const path = require("path");
const extensionLink = "https://marketplace.visualstudio.com/items?itemName=elmsec.dart-flutter-exports";
const skipFolders = ["l10n"]; // folders to skip
const skipFiles = [".g.dart"]; // file patterns to skip
let userChoice = null; // Variable to store user's choice for the current operation
function activate(context) {
let disposable = vscode.commands.registerCommand('dart-flutter-exports.createExporterFiles', (uri) => {
const folder = uri ? uri.fsPath : null;
if (folder) {
userChoice = null; // Reset user's choice for a new operation
createExporterFilesRecursively(folder).then(() => {
vscode.window.showInformationMessage(`Exporter files created recursively in ${folder}`);
});
}
});
context.subscriptions.push(disposable);
}
async function createExporterFilesRecursively(folder) {
const folderName = path.basename(folder);
const filePath = path.join(folder, `${folderName}.dart`);
if (shouldSkip(folderName)) {
return;
}
// Check if the exporter file already exists
if (fs.existsSync(filePath)) {
// Check if the existing file is likely an export file
const existingContent = fs.readFileSync(filePath, 'utf-8');
const exportRegex = /export ['"](.+?)['"];/;
const isLikelyExportFile = exportRegex.test(existingContent);
if (isLikelyExportFile) {
// Show a confirmation dialog for overwrite, skip, or overwrite all
const choices = ['Overwrite', 'Skip', 'Overwrite All'];
const overwriteChoice = userChoice ? choices[2] : await vscode.window.showInformationMessage(
`Exporter file '${folderName}.dart' already exists in ${folder}. Do you want to overwrite it?`,
...choices
);
if (overwriteChoice === 'Overwrite All') {
userChoice = 'Overwrite';
}
if (overwriteChoice === 'Overwrite' || userChoice === 'Overwrite') {
// Continue with overwriting
await generateAndWriteExporterFile(folder, filePath);
} else if (overwriteChoice === 'Skip') {
// Skip the folder
vscode.window.showWarningMessage(`Skipping folder '${folderName}' as requested.`);
return;
}
} else {
// Existing file is not likely an export file, show an error message and skip the folder
vscode.window.showErrorMessage(`File '${folderName}.dart' already exists in ${folder}, and it may not be an export file. Skipping this folder.`);
return;
}
}
// Export file doesn't exist, proceed with generating and writing
await generateAndWriteExporterFile(folder, filePath);
}
async function generateAndWriteExporterFile(folder, filePath) {
const subfolders = getSubdirectories(folder);
// Generate exporter files for subfolders first
for (const subfolder of subfolders) {
await createExporterFilesRecursively(subfolder);
}
const folderName = path.basename(folder);
// Only export files with a .dart extension
const files = fs.readdirSync(folder)
.filter(file => !shouldSkip(file) && path.extname(file) === '.dart' && fs.statSync(path.join(folder, file)).isFile() && file !== `${folderName}.dart`);
// Generate exporter file for the current folder
const fileContent = generateFileContent(folder, subfolders, files);
try {
fs.writeFileSync(filePath, fileContent);
} catch (error) {
vscode.window.showErrorMessage(`Failed to create exporter files in ${folder}. Error: ${error.message}`);
return;
}
}
function generateFileContent(folderName, subfolders, files) {
const subfolderExports = subfolders.map(subfolder => {
const relativePath = path.relative(folderName, subfolder);
return `export '${relativePath}/${path.basename(subfolder)}.dart';`;
}).join('\n');
// Only export files that do not contain part-of statements
const fileExports = files
.filter(file => !containsPartOfStatement(path.join(folderName, file)))
.map(file => `export '${file}';`)
.join('\n');
const exports = `${subfolderExports}\n${fileExports}`;
const fileName = folderName.split('/').pop();
return `// ${fileName}.dart exports\n// generated by: ${extensionLink}:\n\n${exports}`;
}
function containsPartOfStatement(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf-8');
return /part of ['"].+\.dart['"];/i.test(content);
} catch (error) {
console.error(`Error reading file ${filePath}: ${error.message}`);
return false;
}
}
function shouldSkip(name) {
// Skip hidden files and files listed in skipFiles and folders listed in skipFolders
const isHiddenFile = name.startsWith('.');
const isSkippedFile = skipFiles.some(pattern => name.endsWith(pattern));
const isSkippedFolder = skipFolders.includes(name);
return isHiddenFile || isSkippedFile || isSkippedFolder;
}
function getSubdirectories(folder) {
return fs.readdirSync(folder)
.filter(file => fs.statSync(path.join(folder, file)).isDirectory())
.map(subfolder => path.join(folder, subfolder));
}
function deactivate() {}
module.exports = {
activate,
deactivate,
generateFileContent,
shouldSkip,
extensionLink,
};