UNPKG

19.7 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const include_1 = require("./include");
4const erros_1 = require("./erros");
5const fonte_1 = require("./fonte");
6class ValidaAdvpl {
7 constructor(comentFontePad, local) {
8 this.local = local;
9 this.aErros = [];
10 this.includes = [];
11 this.error = 0;
12 this.warning = 0;
13 this.information = 0;
14 this.hint = 0;
15 this.versao = "";
16 //Se não está preenchido seta com valor padrão
17 this.comentFontPad = comentFontePad;
18 this.ownerDb = [];
19 this.empresas = [];
20 }
21 validacao(texto, path) {
22 this.aErros = [];
23 this.includes = [];
24 this.fonte = new fonte_1.Fonte(path);
25 let objeto = this;
26 let conteudoSComentario = "";
27 let linhas = texto.split("\n");
28 //Pega as linhas do documento ativo e separa o array por linha
29 let comentFuncoes = new Array();
30 let funcoes = new Array();
31 let prepareEnvionment = new Array();
32 let cBeginSql = false;
33 let FromQuery = false;
34 let JoinQuery = false;
35 let cSelect = false;
36 let ProtheusDoc = false;
37 let emComentario = false;
38 //Percorre todas as linhas
39 for (var key in linhas) {
40 //seta linha atual em caixa alta
41 let linha = linhas[key].toLocaleUpperCase();
42 let linhaClean = "";
43 //se estiver no PotheusDoc vê se está fechando
44 if (ProtheusDoc && linha.search("\\/\\*\\/") !== -1) {
45 ProtheusDoc = false;
46 }
47 //verifica se é protheusDoc
48 if (linha.search(/\/\*\/+( |)+\{PROTHEUS\.DOC\}/) !== -1) {
49 ProtheusDoc = true;
50 //reseta todas as ariáveis de controle pois se entrou em ProtheusDoc está fora de qualquer função
51 cBeginSql = false;
52 FromQuery = false;
53 JoinQuery = false;
54 cSelect = false;
55 //verifica se é um comentário de função e adiciona no array
56 comentFuncoes.push([
57 linha
58 .trim()
59 .replace(/\/\*\/+( |)+\{PROTHEUS\.DOC\}/, "")
60 .trim()
61 .toLocaleUpperCase(),
62 key
63 ]);
64 }
65 //verifica se a linha está toda comentada
66 let posComentLinha = linha.search(/\/\//);
67 let posComentBloco = linha.search(/\/\*/);
68 posComentBloco = posComentBloco === -1 ? 999999 : posComentBloco;
69 posComentLinha = posComentLinha === -1 ? 999999 : posComentLinha;
70 if (!emComentario && posComentLinha < posComentBloco) {
71 linha = linha.split("//")[0];
72 }
73 //Verifica se está em comentário de bloco
74 //trata comentários dentro da linha
75 linha = linha.replace(/\/\*+.+\*\//, "");
76 if (linha.search(/\*\//) !== -1 && emComentario) {
77 emComentario = false;
78 linha = linha.split(/\*\//)[1];
79 }
80 //se não estiver dentro do Protheus DOC valida linha
81 if (!emComentario) {
82 if (linha
83 .replace(/\"+.+\"/, "")
84 .replace(/\'+.+\'/, "")
85 .search(/\/\*/) !== -1) {
86 emComentario = true;
87 linha = linha.split(/\/\*/)[0];
88 }
89 //Se não estiver em comentário verifica se o último caracter da linha é ;
90 if (!emComentario && linha.charAt(linha.length - 1) === ";") {
91 linhas[parseInt(key) + 1] = linha + " " + linhas[parseInt(key) + 1];
92 linha = "";
93 }
94 //trata comentários em linha ou strings em aspas simples ou duplas
95 //não remove aspas quando for include
96 linha = linha.split("//")[0];
97 linhaClean = linha;
98 if (linha.search(/#INCLUDE/) === -1) {
99 while (linhaClean.search(/\"+.+\"/) !== -1 ||
100 linhaClean.search(/\'+.+\'/) !== -1) {
101 let colunaDupla = linhaClean.search(/\"+.+\"/);
102 let colunaSimples = linhaClean.search(/\'+.+\'/);
103 //se a primeira for a dupla
104 if (colunaDupla !== -1 &&
105 (colunaDupla < colunaSimples || colunaSimples === -1)) {
106 let quebra = linhaClean.split('"');
107 linhaClean = linhaClean.replace('"' + quebra[1] + '"', "");
108 }
109 else {
110 let quebra = linhaClean.split("'");
111 linhaClean = linhaClean.replace("'" + quebra[1] + "'", "");
112 }
113 }
114 }
115 conteudoSComentario = conteudoSComentario + linhaClean + "\n";
116 //verifica se é função e adiciona no array
117 if (linhaClean.search(/(STATIC|USER|)+(\ |\t)+FUNCTION+(\ |\t)/) !== -1 &&
118 linhaClean
119 .trim()
120 .split(" ")[0]
121 .match(/STATIC|USER|FUNCTION/)) {
122 //reseta todas as ariáveis de controle pois está fora de qualquer função
123 cBeginSql = false;
124 FromQuery = false;
125 JoinQuery = false;
126 cSelect = false;
127 let nomeFuncao = linhaClean.replace("\t", " ").trim()
128 .split(" ")
129 .filter(x => x)[2]
130 .concat("")
131 .split("(")
132 .filter(x => x)[0]
133 .concat("");
134 //verifica se é um função e adiciona no array
135 funcoes.push([nomeFuncao, key]);
136 //verifica o TIPO
137 if (linhaClean.search(/(USER)+(\ |\t)+FUNCTION+(\ |\t)/) !== -1) {
138 this.fonte.addFunction(fonte_1.Tipos["User Function"], nomeFuncao, parseInt(key));
139 }
140 else if (linhaClean.split(" ")[0].split("\t")[0] === "FUNCTION") {
141 //verifica se a primeira palavra é FUNCTION
142 this.fonte.addFunction(fonte_1.Tipos["Function"], nomeFuncao, parseInt(key));
143 }
144 }
145 //Verifica se é CLASSE ou WEBSERVICE
146 if (linhaClean.search("METHOD\\ .*?CLASS") !== -1 ||
147 linhaClean.split(" ").filter(x => x)[0].concat("").split("\t").filter(x => x)[0].concat("") === "CLASS" ||
148 linhaClean.search("WSMETHOD.*?WSSERVICE") !== -1 ||
149 linhaClean.search("WSSERVICE\\ ") !== -1) {
150 //reseta todas as ariáveis de controle pois está fora de qualquer função
151 cBeginSql = false;
152 FromQuery = false;
153 JoinQuery = false;
154 cSelect = false;
155 //verifica se é um função e adiciona no array
156 funcoes.push([
157 linhaClean
158 .trim()
159 .split(" ")
160 .filter(x => x)[1]
161 .concat("")
162 .split("(")
163 .filter(x => x)[0]
164 .concat(""),
165 key
166 ]);
167 if (linhaClean.split(" ")[0].split("\t")[0] === "CLASS") {
168 this.fonte.addFunction(fonte_1.Tipos["Class"], linhaClean
169 .trim()
170 .split(" ")
171 .filter(x => x)[1]
172 .concat("")
173 .split("(")
174 .filter(x => x)[0]
175 .concat(""), parseInt(key));
176 }
177 }
178 //Verifica se adicionou o include TOTVS.CH
179 if (linha.search(/#INCLUDE/) !== -1) {
180 //REMOVE as aspas a palavra #include e os espacos e tabulações
181 objeto.includes.push({
182 include: linha
183 .replace(/#INCLUDE/g, "")
184 .replace(/\t/g, "")
185 .replace(/\'/g, "")
186 .replace(/\"/g, "")
187 .trim(),
188 linha: parseInt(key)
189 });
190 }
191 if (linhaClean.search(/BEGINSQL+(\ |\t)+ALIAS/) !== -1) {
192 cBeginSql = true;
193 }
194 if (linhaClean.search(/PREPARE+(\ |\t)+ENVIRONMENT+(\ |\t)/) !== -1) {
195 prepareEnvionment.push(parseInt(key));
196 }
197 if (linha.match(/(\ |\t|\'|\"|)+SELECT+(\ |\t)/) ||
198 linha.match(/(\ |\t|\'|\"|)+DELETE+(\ |\t)/) ||
199 linha.match(/(\ |\t|\'|\"|)+UPDATE+(\ |\t)/)) {
200 cSelect = true;
201 }
202 if (!cBeginSql &&
203 (linha.search(/(\ |\t|\'|\"|)+DBUSEAREA+(\ |\t|)+\(+.+TOPCONN+.+TCGENQRY/) !== -1 ||
204 linhaClean.search(/TCQUERY+(\ |\t)/) !== -1)) {
205 objeto.aErros.push(new erros_1.Erro(parseInt(key), parseInt(key), traduz("validaAdvpl.queryNoEmbedded", this.local), erros_1.Severity.Warning));
206 FromQuery = false;
207 cSelect = false;
208 }
209 if (linha.search(/(\ |\t|\'|\")+DELETE+(\ |\t)+FROM+(\ |\t)/) !== -1) {
210 objeto.aErros.push(new erros_1.Erro(parseInt(key), parseInt(key), traduz("validaAdvpl.deleteFrom", this.local), erros_1.Severity.Warning));
211 }
212 if (linhaClean.search(/MSGBOX\(/) !== -1) {
213 objeto.aErros.push(new erros_1.Erro(parseInt(key), parseInt(key), traduz("validaAdvpl.msgBox", this.local), erros_1.Severity.Information));
214 }
215 if (linha.search(/GETMV\(+(\ |\t|)+(\"|\')+MV_FOLMES+(\"|\')+(\ |\t|)\)/) !== -1) {
216 objeto.aErros.push(new erros_1.Erro(parseInt(key), parseInt(key), traduz("validaAdvpl.folMes", this.local), erros_1.Severity.Information));
217 }
218 if (linha.search("\\<\\<\\<\\<\\<\\<\\<\\ HEAD") !== -1) {
219 //Verifica linha onde terminou o conflito
220 let nFim = key;
221 for (var key2 in linhas) {
222 if (linhas[key2].search("\\>\\>\\>\\>\\>\\>\\>") !== -1 &&
223 nFim === key &&
224 key2 > key) {
225 nFim = key2;
226 }
227 }
228 objeto.aErros.push(new erros_1.Erro(parseInt(key), parseInt(nFim), traduz("validaAdvpl.conflictMerge", this.local), erros_1.Severity.Error));
229 }
230 if (linha.search(/(\ |\t|\'|\"|)+SELECT+(\ |\t)/) !== -1 &&
231 linha.search("\\ \\*\\ ") !== -1) {
232 objeto.aErros.push(new erros_1.Erro(parseInt(key), parseInt(key), traduz("validaAdvpl.selectAll", this.local), erros_1.Severity.Warning));
233 }
234 if (linha.search("CHR\\(13\\)") !== -1 &&
235 linha.search("CHR\\(10\\)") !== -1) {
236 objeto.aErros.push(new erros_1.Erro(parseInt(key), parseInt(key), traduz("validaAdvpl.crlf", this.local), erros_1.Severity.Warning));
237 }
238 if (cSelect && linha.search("FROM") !== -1) {
239 FromQuery = true;
240 }
241 if (cSelect && FromQuery && linha.search("JOIN") !== -1) {
242 JoinQuery = true;
243 }
244 if (linha.search("ENDSQL") !== -1 ||
245 linha.search("WHERE") !== -1 ||
246 linha.search("TCQUERY") !== -1) {
247 FromQuery = false;
248 cSelect = false;
249 }
250 //Implementação para aceitar vários bancos de dados
251 this.ownerDb.forEach(banco => {
252 if (cSelect && FromQuery && linha.search(banco) !== -1) {
253 objeto.aErros.push(new erros_1.Erro(parseInt(key), parseInt(key), traduz("validaAdvpl.noSchema", this.local) +
254 banco +
255 traduz("validaAdvpl.inQuery", this.local), erros_1.Severity.Error));
256 }
257 });
258 if (cSelect &&
259 (FromQuery || JoinQuery || linha.search("SET") !== -1) &&
260 linha.search("exp:cTable") === -1) {
261 //procura códigos de empresas nas queryes
262 this.empresas.forEach(empresa => {
263 //para melhorar a análise vou quebrar a string por espaços
264 //e removendo as quebras de linhas, vou varrer os itens do array e verificar o tamanho
265 //e o código da empresa chumbado
266 let palavras = linha
267 .replace(/\r/g, "")
268 .replace(/\t/g, "")
269 .split(" ");
270 palavras.forEach(palavra => {
271 if (palavra.search(empresa + "0") !== -1 &&
272 palavra.length === 6) {
273 objeto.aErros.push(new erros_1.Erro(parseInt(key), parseInt(key), traduz("validaAdvpl.tableFixed", this.local), erros_1.Severity.Error));
274 }
275 });
276 });
277 }
278 if (cSelect && JoinQuery && linha.search("ON") !== -1) {
279 JoinQuery = false;
280 }
281 if (linhaClean.search(/CONOUT\(/) !== -1) {
282 objeto.aErros.push(new erros_1.Erro(parseInt(key), parseInt(key), traduz("validaAdvpl.conout", this.local), erros_1.Severity.Warning));
283 }
284 //recomendação para melhorar identificação de problemas em queryes
285 if ((linha.match(/(\ |\t|)+SELECT+(\ |\t)/) ||
286 linha.match(/(\ |\t|)+DELETE+(\ |\t)/) ||
287 linha.match(/(\ |\t|)+UPDATE+(\ |\t)/) ||
288 linha.match(/(\ |\t|)+JOIN+(\ |\t)/)) &&
289 (linha.match(/(\ |\t|)+FROM+(\ |\t)/) ||
290 linha.match(/(\ |\t|)+ON+(\ |\t)/) ||
291 linha.match(/(\ |\t|)+WHERE+(\ |\t)/)) &&
292 linha.search(/(\ |\t)+TCSQLEXEC+\(/) === -1) {
293 //verifica o caracter anterior tem que ser ou ESPACO ou ' ou " ou nada
294 let itens1 = ["FROM", "ON", "WHERE"];
295 let addErro = false;
296 itens1.forEach(item => {
297 addErro = addErro || linha.search("\\'" + item) !== -1;
298 addErro = addErro || linha.search('\\"' + item) !== -1;
299 addErro = addErro || linha.search("\\ " + item) !== -1;
300 });
301 if (addErro) {
302 objeto.aErros.push(new erros_1.Erro(parseInt(key), parseInt(key), traduz("validaAdvpl.bestAnalitc", this.local) +
303 " SELECT, DELETE, UPDATE, JOIN, FROM, ON, WHERE.", erros_1.Severity.Information));
304 }
305 }
306 }
307 else {
308 conteudoSComentario += "\n";
309 }
310 }
311 //Validação de padrão de comentáris de fontes
312 let comentariosFonte = true;
313 for (var _i = 0; _i < objeto.comentFontPad.length; _i++) {
314 let cExpressao = objeto.comentFontPad[_i];
315 let linha = linhas[_i];
316 comentariosFonte = comentariosFonte && linha.search(cExpressao) !== -1;
317 }
318 if (!comentariosFonte) {
319 objeto.aErros.push(new erros_1.Erro(0, 0, traduz("validaAdvpl.padComment", this.local), erros_1.Severity.Information));
320 }
321 //Validação funções sem comentários
322 funcoes.forEach(funcao => {
323 let achou = false;
324 comentFuncoes.forEach(comentario => {
325 achou = achou || comentario[0] === funcao[0];
326 });
327 if (!achou) {
328 objeto.aErros.push(new erros_1.Erro(parseInt(funcao[1]), parseInt(funcao[1]), traduz("validaAdvpl.functionNoCommented", this.local), erros_1.Severity.Warning));
329 }
330 });
331 //Validação comentários sem funções
332 comentFuncoes.forEach(comentario => {
333 let achou = false;
334 funcoes.forEach(funcao => {
335 achou = achou || comentario[0] === funcao[0];
336 });
337 if (!achou) {
338 objeto.aErros.push(new erros_1.Erro(parseInt(comentario[1]), parseInt(comentario[1]), traduz("validaAdvpl.CommentNoFunction", this.local), erros_1.Severity.Warning));
339 }
340 });
341 //Validador de includes
342 let oInclude = new include_1.Include(objeto.local);
343 oInclude.valida(objeto, conteudoSComentario);
344 //Conta os erros por tipo e totaliza no objeto
345 this.hint = 0;
346 this.information = 0;
347 this.warning = 0;
348 this.error = 0;
349 objeto.aErros.forEach((erro) => {
350 if (erro.severity === erros_1.Severity.Hint) {
351 this.hint++;
352 }
353 if (erro.severity === erros_1.Severity.Information) {
354 this.information++;
355 }
356 if (erro.severity === erros_1.Severity.Warning) {
357 this.warning++;
358 }
359 if (erro.severity === erros_1.Severity.Error) {
360 this.error++;
361 }
362 });
363 if (this.error > 0 ||
364 this.hint > 0 ||
365 this.warning > 0 ||
366 this.information > 0) {
367 console.log(`\t${traduz("validaAdvpl.foundFile", this.local)} ${path}:`);
368 if (this.error > 0) {
369 console.log(`\t\t${this.error} Errors .`);
370 }
371 if (this.warning > 0) {
372 console.log(`\t\t${this.warning} Warnings .`);
373 }
374 if (this.information > 0) {
375 console.log(`\t\t${this.information} Informations .`);
376 }
377 if (this.hint > 0) {
378 console.log(`\t\t${this.hint} Hints .`);
379 }
380 }
381 }
382}
383exports.ValidaAdvpl = ValidaAdvpl;
384function traduz(key, local) {
385 let locales = ["en", "pt-br"];
386 let i18n = require("i18n");
387 i18n.configure({
388 locales: locales,
389 directory: __dirname + "/locales"
390 });
391 i18n.setLocale(locales.indexOf(local) + 1 ? local : "en");
392 return i18n.__(key);
393}
394//# sourceMappingURL=validaAdvpl.js.map
\No newline at end of file