forked from microsoft/vscode-comment
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathargParser.ts
177 lines (170 loc) · 6.02 KB
/
argParser.ts
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
export class paramDef {
constructor(public paramName: string, public paramType: string) {
this.paramName = paramName;
this.paramType = paramType;
}
}
export function getParameterText(functionParams: paramDef[], returnParams: paramDef[]): string {
var textToInsert: string = "";
textToInsert = textToInsert + '/**\n * @notice .\n * @dev .\n';
functionParams.forEach(element => {
if (element.paramName != '') {
textToInsert = textToInsert + ' * @param ';
// textToInsert = textToInsert + '{' + element.paramType + '}' + ' '; // for type insertion
textToInsert = textToInsert + element.paramName + ' .' + '\n';
}
});
returnParams.forEach(element => {
if (element.paramType != '') {
textToInsert = textToInsert + ' * @return ';
// textToInsert = textToInsert + '{' + element.paramType + '}' + ' '; // for type insertion
if (element.paramName != '') {
textToInsert = textToInsert + element.paramName + ' .' + '\n';
} else {
// textToInsert = textToInsert + 'UNNAMED' + '\n'; // for type insertion
textToInsert = textToInsert + element.paramType + ' .' + '\n';
}
}
});
textToInsert = textToInsert + ' */';
return textToInsert;
}
// split a given line by a keyword
// for Solidity keyword is expected to be used with 'returns'
// everything before 'returns' will be used to build lines[0] for function parameters
// everything after 'returns' will be used to build lines[1] for the return parameters
export function splitTextByKeyword(text: string, keyword: string): string[] {
const result = text.trim().split(/\s+/);
const index = result.indexOf("{", 0);
if (index > -1) {
result.splice(index, 1);
}
let lines: string[] = [];
const rPos = result.indexOf(keyword);
if (rPos != -1) {
lines[0] = result.slice(0, rPos).join(" ");
lines[1] = result.slice(rPos + 1, result.length).join(" ");
} else {
lines[0] = result.slice(0, result.length).join(" ");
lines[1] = "";
}
return lines;
}
// removes keywords from the parts array
export function removeKeywords(parts: string[]): string[] {
let keywordsToRemove = ["memory", "calldata", "storage", "payable"];
keywordsToRemove.forEach(element => {
let idx = parts.indexOf(element, 0);
if (idx > -1) {
parts.splice(idx, 1);
}
});
return parts;
}
//Assumes that the string passed in starts with ( and continues to ) and does not contain any comments
export function getFunctionParams(text: string): paramDef[] {
var params: paramDef[] = [];
//Start by looking for the function name declaration
var index = 0;
text = text.trim(); // delete the leading and trailing spaces
//if there is no '(' then this is not a valid function declaration
if (text.charAt(index) == '(') {
//count the number of matching opening and closing braces. Keep parsing until 0
var numBraces = 1;
index++;
while ((numBraces != 0) && (index != text.length)) {
var name_type: string = '';
while ((text.charAt(index) != ',') && (text.charAt(index) != ')') && (index < text.length)) {
name_type = name_type + text.charAt(index);
index++;
}
if (text.charAt(index) == ')') {
numBraces--;
}
name_type = name_type.trim() // trim leading and trailing whitespace
let parts = name_type.split(" "); // spitting a returns element (bool b, uint256 u, ...)
parts = removeKeywords(parts);
if (parts.length == 1) {
params.push(new paramDef("", ""));
} else if (parts.length == 2) {
params.push(new paramDef(parts[1], parts[0]));
} else {
const errorMessage = "Arguments are malformed in the selected code";
throw new Error(errorMessage);
}
if (index < text.length) {
index++;
while (text.charAt(index) == ' ') index++; // consume whitespace
}
}
}
return params;
}
//Assumes that the string passed in starts with ( and continues to ) and does not contain any comments
export function getReturnParams(text: string): paramDef[] {
var params: paramDef[] = [];
//Start by looking for the function name declaration
var index = 0;
text = text.trim(); // delete the leading and trailing spaces
//if there is no '(' then this is not a valid function declaration
if (text.charAt(index) == '(') {
//count the number of matching opening and closing braces. Keep parsing until 0
var numBraces = 1;
index++;
while ((numBraces != 0) && (index != text.length)) {
var name_type: string = '';
while ((text.charAt(index) != ',') && (text.charAt(index) != ')') && (index < text.length)) {
name_type = name_type + text.charAt(index);
index++;
}
if (text.charAt(index) == ')') {
numBraces--;
}
name_type = name_type.trim() // trim leading and trailing whitespace
let parts = name_type.split(" "); // spitting a returns element (bool b, uint256 u, ...) or (bool, uint256, ...)
parts = removeKeywords(parts);
if (parts.length == 0) {
params.push(new paramDef("", ""));
} else if (parts.length == 2) {
params.push(new paramDef(parts[1], parts[0]));
} else if (parts.length == 1) {
params.push(new paramDef("", parts[0]));
} else {
const errorMessage = "Elements of returns are malformed in the selected code";
throw new Error(errorMessage);
}
if (index < text.length) {
index++;
while (text.charAt(index) == ' ') index++; // consume whitespace
}
}
}
return params;
}
export function stripComments(text: string): string {
var uncommentedText: string = '';
var index = 0;
while (index != text.length) {
if ((text.charAt(index) == '/') && (text.charAt(index + 1) == '*')) {
//parse comment
if ((index + 2) != text.length) { //Check for the corner case that the selected text contains a /* right at the end
index = index + 2;
while ((text.charAt(index) != '*') && (text.charAt(index + 1) != '/')) {
index++;
}
}
index = index + 2;
}
else if ((text.charAt(index) == '/') && (text.charAt(index + 1) == '/')) {
//read to end of line
while ((text.charAt(index) != '\n') && (index < text.length)) {
index++;
}
}
else {
uncommentedText = uncommentedText + text.charAt(index);
index++;
}
}
return uncommentedText;
}