-
Notifications
You must be signed in to change notification settings - Fork 0
/
correction_auto_2.py
927 lines (733 loc) · 33.2 KB
/
correction_auto_2.py
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
# Copyright (C) 2014-2024 CEA, EDF
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#
import os, os.path, sys, re, argparse
from utils import *
#### définition des hooks.
# chaque hook doit :
# * avoir le prototype suivant : def <nom_hook>(<unicode>) avec <unicode> la ligne de texte à corriger
# * retourner deux valeurs : la ligne corrigée, en unicode et un booléen indiquant s'il faut faire un check humain avant de corriger
# * être inséré dans HOOKS_DICT en y faisant correspondre un dico explicitant les critères de séléction de ce hook
####
### whitespace/semicolon ###
def extra_space_before_last_semicolon(ligne, previous_ligne = None, warning=None):
liste=ligne.split(';\n')
ligne2=liste[0]
ligne3=ligne2.rstrip()
ligne=ligne3 + ';\n'
return ligne, previous_ligne, False
def missing_space_after_semicolon(ligne, previous_ligne = None, warning=None):
ligne=ligne.replace(';','; ')
return ligne, previous_ligne, False
#########################
### whitespace/operators ###
def missing_space_around_operator_egal(ligne, previous_ligne = None, warning=None):
i=ligne.find('=')
nextchar=ligne[i+1]
previouschar=ligne[i-1]
if nextchar not in OPERATORS and previouschar not in OPERATORS:
if nextchar.isspace() == False and previouschar.isspace()==True:
ligne=ligne.replace('=', '= ')
elif nextchar.isspace() == True and previouschar.isspace()==False:
ligne=ligne.replace('=', ' =')
elif nextchar.isspace() == False and previouschar.isspace()==False:
ligne=ligne.replace('=', ' = ')
else:
pass
return ligne, previous_ligne, False
def extra_space_for_operator_add(ligne, previous_ligne = None, warning=None):
while ligne.find('++ ') > -1:
ligne = ligne.replace('++ ','++')
while ligne.find(' ++') > -1 and ligne.find('; ++') == -1:
ligne = ligne.replace(' ++','++')
return ligne, previous_ligne, False
def extra_space_for_operator_diff(ligne, previous_ligne = None, warning=None):
while ligne.find('! ') > -1:
ligne = ligne.replace('! ','!')
return ligne, previous_ligne, False
def missing_space_around_operator_double_chevron(ligne, previous_ligne = None, warning=None):
i=ligne.find('<<')
nextchar=ligne[i+1]
previouschar=ligne[i-1]
if nextchar.isspace() == False and previouschar.isspace()==True:
ligne=ligne.replace('<<', '<< ')
elif nextchar.isspace() == True and previouschar.isspace()==False:
ligne=ligne.replace('<<', ' <<')
elif nextchar.isspace() == False and previouschar.isspace()==False:
ligne=ligne.replace('<<', ' << ')
else:
pass
return ligne, previous_ligne, False
def missing_space_around_operator_simple_chevron(ligne, previous_ligne = None, warning=None):
i=ligne.find('<')
nextchar=ligne[i+1]
previouschar=ligne[i-1]
if nextchar not in OPERATORS and previouschar not in OPERATORS:
if nextchar.isspace() == False and previouschar.isspace()==True:
ligne=ligne.replace('<', '< ')
elif nextchar.isspace() == True and previouschar.isspace()==False:
ligne=ligne.replace('<', ' <')
elif nextchar.isspace() == False and previouschar.isspace()==False:
ligne=ligne.replace('<', ' < ')
else:
pass
return ligne, previous_ligne, False
def missing_space_around_operator_diff_egal(ligne, previous_ligne = None, warning=None):
i=ligne.find('!=')
nextchar=ligne[i+1]
previouschar=ligne[i-1]
if nextchar.isspace() == False and previouschar.isspace()==True:
ligne=ligne.replace('!=', '!= ')
elif nextchar.isspace() == True and previouschar.isspace()==False:
ligne=ligne.replace('!=', ' !=')
elif nextchar.isspace() == False and previouschar.isspace()==False:
ligne=ligne.replace('!=', ' != ')
else:
pass
return ligne, previous_ligne, False
def missing_space_around_operator_double_egal(ligne, previous_ligne = None, warning=None):
i=ligne.find('==')
nextchar=ligne[i+1]
previouschar=ligne[i-1]
if nextchar.isspace() == False and previouschar.isspace()==True:
ligne=ligne.replace('==', '== ')
elif nextchar.isspace() == True and previouschar.isspace()==False:
ligne=ligne.replace('==', ' ==')
elif nextchar.isspace() == False and previouschar.isspace()==False:
ligne=ligne.replace('==', ' == ')
else:
pass
return ligne, previous_ligne, False
#########################
### whitespace/comments ###
def space_between_comments_and_code(ligne, previous_ligne = None, warning=None):
if ligne.find('//')>=0 :
ligne=ligne.replace('//', ' //')
elif ligne.find(' //')>=0 :
ligne=ligne.replace(' //', ' //')
else:
pass
return ligne, previous_ligne, False
def space_between_comments_and_double_slash(ligne, previous_ligne = None, warning=None):
return ligne.replace('//', '// '), previous_ligne, False
#########################
### legal/copyright ###
def legal_copyright(ficpath, ficline, warning=None):
replace_fic_copyright(ficpath)
#########################
### build/header_guard
def ifndef_header(ficpath, ficline, warning):
replace_fic_ifndef(ficpath, ficline, warning, "wrong_style")
#def no_ifndef_header(ficpath, ficline, warning):
# replace_fic_ifndef(ficpath, ficline, warning, "no_guard_found")
def endif_line(ligne, previous_ligne = None, warning=None):
liste1=warning.split('// ')
ligne1=liste1[1]
liste2=ligne1.split('"')
header_guard=liste2[0]
ligne= '#endif // ' + header_guard +'\n'
return ligne, previous_ligne, False
#########################
### whitespace/end_of_ligne ###
def whitespace_end_of_line(ligne, previous_ligne = None, warning=None):
ligne = ligne.rstrip()+'\n'
return ligne, previous_ligne, False
#########################
### whitespace/comma ###
def missing_space_after_comma(ligne, previous_ligne = None, warning=None):
ligne=ligne.replace(',',', ')
return ligne, previous_ligne, False
#########################
### readability/namespace ###
def namespace_should_be_terminated(ligne, previous_ligne = None, warning=None):
ligne2=ligne.rstrip('\n')
liste = warning.split('"')
namespace=liste[1]
if ligne.find('\r')>=0:
ligne=ligne2+' '+namespace+'\r\n'
else:
ligne=ligne2+' '+namespace+'\n'
return ligne, previous_ligne, False
def anonymous_namespace_should_be_terminated(ligne, previous_ligne = None, warning=None):
ligne2=ligne.rstrip('\n')
ligne=ligne2+' // namespace\n'
return ligne, previous_ligne, False
#########################
### whitespace/parens ###
def extra_space_after_opening_paranthesis(ligne, previous_ligne = None, warning=None):
while ligne.find('( ') > -1:
ligne = ligne.replace('( ','(')
return ligne, previous_ligne, False
def extra_space_before_closing_paranthesis(ligne, previous_ligne = None, warning=None):
while ligne.find(' )') > -1:
ligne = ligne.replace(' )',')')
return ligne, previous_ligne, False
def extra_space_before_opening_paranthesis_in_function_call(ligne, previous_ligne = None, warning=None):
while ligne.find(' (') > -1 and ligne.find(', (')==-1:
ligne = ligne.replace(' (','(')
return ligne, previous_ligne, False
def missing_space_before_opening_parenthesis_in_for(ligne, previous_ligne = None, warning=None):
return ligne.replace('for(','for ('), previous_ligne, False
def missing_space_before_opening_parenthesis_in_if(ligne, previous_ligne = None, warning=None):
return ligne.replace('if(','if ('), previous_ligne, False
def missing_space_before_opening_parenthesis_in_switch(ligne, previous_ligne = None, warning=None):
return ligne.replace('switch(','switch ('), previous_ligne, False
def missing_space_before_opening_parenthesis_in_while(ligne, previous_ligne = None, warning=None):
return ligne.replace('while(','while ('), previous_ligne, False
def mismatching_spaces_inside_paranthesis(ligne, previous_ligne = None, warning=None):
while ligne.find('( ') > -1:
ligne = ligne.replace('( ','(')
while ligne.find(' )') > -1:
ligne = ligne.replace(' )',')')
return ligne, previous_ligne, False
#########################
### whitespace/newline ###
def else_should_be_previous_line(ligne, previous_ligne=None, warning=None):
return position_of_else(ligne, previous_ligne, warning)
#########################
### whitespace/indent ###
def missing_space_before_public_protected_private(ligne, previous_ligne = None, warning=None):
# Ajout d'un espace avant public:, protected: et :private
if re.match("public.*:|protected.*:|private.*:", ligne):
ligne = " " + ligne
return ligne, previous_ligne, False
def wrong_number_of_spaces_while_indenting(ligne, previous_ligne = None, warning=None):
# Le nombre d'espaces pour l'indentation doit être pair
if re.match("\s{1}\S+|\s{3}\S+|\s{5}\S+|\s{7}\S+|\s{9}\S+", ligne):
if not re.match(" public.*:| protected.*:| private.*:| \*", ligne):
ligne = " " + ligne
# Suppression des espaces superflus sur une ligne sans code
if ligne.isspace():
ligne = "\n"
# Remplacement des tabulations par 8 espaces en début de ligne
ligne = ligne.replace("\t", " ")
return ligne, previous_ligne, False
#########################
### whitespace/ending_newline ###
def no_newline_at_the_end_of_file(ligne, previous_ligne = None, warning=None):
ligne += '\n\n'
return ligne, None, False
#################################
### build/storage_class ###
def order_of_storage_class_specifier(ligne, previous_ligne = None, warning=None):
if re.match("\s*const static", ligne):
# Inversion de const static en static const
ligne = ligne.replace("const static", "static const")
return ligne, previous_ligne, False
###########################
### whitespace/tab ###
def use_spaces_instead_of_tab(ligne, previous_ligne = None, warning=None):
if re.match(".*\t", ligne):
# Remplacement des tabulations par 8 espaces
ligne = ligne.replace("\t", " ")
return ligne, previous_ligne, False
######################
### readability/braces ###
def no_semicolon_after_brace(ligne, previous_ligne = None, warning=None):
return ligne.replace('};','}'), previous_ligne, False
def position_of_else(ligne, previous_ligne=None, warning=None):
'''Remonte une ligne du type } else {'''
if '}' not in previous_ligne:
# Si on ne trouve pas de '}' sur la ligne précédente, on ne fait rien
return ligne, None, False
m = re.match("(.*)else(.*)", ligne)
previous_ligne = previous_ligne.rstrip("\n") + ' else' + m.group(2) + '\n'
ligne = ''
return ligne, previous_ligne, False
##########################
### whitespace/braces ###
def position_of_opening_brace(ligne, previous_ligne=None, warning=None):
'''Remonte le { sur la ligne du dessus'''
m = re.match("(\s*){(.*)", ligne)
# On ne fait rien si on trouve un commentaire sur la ligne précédente (ce sera une correction manuelle)
if previous_ligne.find('//') == -1:
previous_ligne = previous_ligne.rstrip("\n") + ' {' + m.group(2) + '\n'
ligne = ''
else:
print("The previous line contains a comment, fixing has to be manual.")
return ligne, previous_ligne, False
def missing_space_before_opening_brace(ligne, previous_ligne = None, warning=None):
m = re.match("(.+)(\S){(.*)", ligne)
if(m):
print('group_0', m.group(0))
print('group_1', m.group(1))
print('group_2', m.group(2))
print('group_3', m.group(3))
ligne = m.group(1) + m.group(2) + ' {' + m.group(3) + '\n'
return ligne, previous_ligne, False
#########################
def missing_space_before_else(ligne, previous_ligne = None, warning=None):
m = re.match("(.+)(\S)else(.*)", ligne)
if(m):
print('group_0', m.group(0))
print('group_1', m.group(1))
print('group_2', m.group(2))
print('group_3', m.group(3))
ligne = m.group(1) + m.group(2) + ' else' + m.group(3) + '\n'
return ligne, previous_ligne, False
### runtime/references ###
def make_const_reference(ficpath, ligne, previous_ligne = None, warning=None):
""" Adding keyword 'const' """
print("ficpath = ", ficpath)
print("ligne = ", ligne)
print("warning = ", warning)
m = re.match("(.+)Is this a non-const reference\? If so, make const or use a pointer: (.+) (.+)", warning)
if(m):
print('group_0', m.group(0))
print('group_1', m.group(1))
print('group_2', m.group(2))
print('group_3', m.group(3))
arg_to_modify = m.group(2)
ligne = ligne.replace(arg_to_modify, "const "+arg_to_modify)
# Répercution des corrections dans le fichier ".cpp" correspondant si c'est un fichier ".h"
if ficpath.find('.h') > -1:
cpp_file_path = ficpath.replace('.h', '.cpp')
make_const_reference_cpp_file(cpp_file_path, arg_to_modify)
global H_FILE_MAKE_CONST_REFERENCE_MODIFIED
H_FILE_MAKE_CONST_REFERENCE_MODIFIED = True
else:
print("ERROR : The following pattern was not found : 'Is this a non-const reference? If so, make const or use a pointer:'")
return ligne, previous_ligne, False
def make_const_reference_cpp_file(ficpath, arg_to_modify):
if not os.path.isfile(ficpath):
print("WARNING : The file ", ficpath, " doesn't exist, manual fixing is required in methods of the file ", ficpath.replace('.cpp', '.h'), " in which arguments have been declared 'const'")
return
fic = open(get_src_path(ficpath),'r')
liste = fic_readlines(fic)
new_liste = []
for ligne in liste:
# Recherche de l'argument à modifier
if(ligne.find(arg_to_modify) > -1 and ligne.find('const '+arg_to_modify) == -1):
new_liste.append(ligne.replace(arg_to_modify, "const "+arg_to_modify))
else:
new_liste.append(ligne)
newliste=fic_writelines(new_liste)
fichier = open(get_src_path(ficpath), "w")
fichier.writelines(newliste)
##########################
### runtime/int ###
def replace_short_by_int16(ligne, previous_ligne = None, warning=None):
ligne = ligne.replace('short', 'int16_t')
return ligne, None, False
def replace_long_by_int64(ligne, previous_ligne = None, warning=None):
ligne = ligne.replace('long', 'int64_t')
return ligne, None, False
###################
### runtime/explicit ###
def make_constructor_explicit(ligne, previous_ligne = None, warning=None):
m = re.match("(\s*)(.+)", ligne)
if(m):
print('group_0', m.group(0))
print('group_1', m.group(1))
print('group_2', m.group(2))
ligne = ligne.replace(m.group(2), 'explicit '+m.group(2))
return ligne, None, False
########################
### build/include ###
def cpp_file_should_include_h_file(ficpath, ficline, warning):
fic = open(get_src_path(ficpath),'r')
liste = fic_readlines(fic)
new_liste = []
m = re.match("(.+) should include its header file (.+) (.+)", warning)
if(m):
print('group_0', m.group(0))
print('group_1', m.group(1))
print('group_2', m.group(2))
# Nouveau chemin du fichier .h
new_h_file_path = m.group(2)
# Nom du fichier .h
h_file_name = os.path.basename(new_h_file_path)
# Recherche de la ligne à modifier
for ligne in liste:
m2 = re.match("#include.*"+h_file_name+".*", ligne)
if(m2):
print("FOUND : ", ligne)
new_liste.append("#include \""+new_h_file_path+"\"\n")
else:
print("NOT FOUND : ", ligne)
new_liste.append(ligne)
else:
print("ERROR : Pattern not found : \"should include its header file\"")
newliste=fic_writelines(new_liste)
fichier = open(get_src_path(ficpath), "w")
fichier.writelines(newliste)
def _h_file_already_included(ligne, previous_ligne = None, warning=None):
return "", None, False
#####################
### whitespace/blank_line ###
def do_not_leave_blank_line_after_public_protected_private(ficpath, ficline, warning):
fic = open(get_src_path(ficpath),'r')
liste = fic_readlines(fic)
new_liste = []
flag = False
for ligne in liste:
if re.match(".*public.*:|.*protected.*:|.*private.*:", ligne):
# Détection d'une ligne public:, protected: ou :private
flag = True
if flag and ligne.isspace():
# Supprimer les lignes vides après public:, protected: et :private
print("Deleting empty line")
new_liste.append("")
continue
if not ligne.isspace() and not re.match(".*public.*:|.*protected.*:|.*private.*:", ligne):
flag = False
new_liste.append(ligne)
newliste=fic_writelines(new_liste)
fichier = open(get_src_path(ficpath), "w")
fichier.writelines(newliste)
def do_not_leave_blank_line_at_the_start_of_code_block(ficpath, ficline, warning):
fic = open(get_src_path(ficpath),'r')
liste = fic_readlines(fic)
new_liste = []
flag = False
for ligne in liste:
if re.match(".*{", ligne):
# Détection d'un début de bloc
flag = True
if flag and ligne.isspace():
# Supprimer les lignes vides après un début de bloc
print("Deleting empty line")
new_liste.append("")
continue
if not ligne.isspace() and not re.match(".*{", ligne):
flag = False
new_liste.append(ligne)
newliste=fic_writelines(new_liste)
fichier = open(get_src_path(ficpath), "w")
fichier.writelines(newliste)
def do_not_leave_blank_line_at_the_end_of_code_block(ficpath, ficline, warning):
fic = open(get_src_path(ficpath),'r')
liste = fic_readlines(fic)
new_liste = []
nb_blank_lines = 0
for ligne in liste:
if re.match(".*}", ligne):
# Détection d'une fin de bloc -> suppression des nb_blank_lines lignes vides précédentes
for i in range(0, nb_blank_lines):
new_liste.pop()
if ligne.isspace():
nb_blank_lines += 1
else:
nb_blank_lines = 0
new_liste.append(ligne)
newliste=fic_writelines(new_liste)
fichier = open(get_src_path(ficpath), "w")
fichier.writelines(newliste)
def add_blank_line_before_public(ligne, previous_ligne = None, warning=None):
ligne = "\n" + ligne
return ligne, None, False
def add_blank_line_before_protected(ligne, previous_ligne = None, warning=None):
ligne = "\n" + ligne
return ligne, None, False
def add_blank_line_before_private(ligne, previous_ligne = None, warning=None):
ligne = "\n" + ligne
return ligne, None, False
##############################
### build/include_what_you_use ###
def add_include_what_you_use(ficpath, ficline, warning):
"""
Ajoute le #include suggéré dans le warning
"""
fic = open(get_src_path(ficpath), "r")
liste = fic_readlines(fic)
m = re.match("\s*Add (.+) for (.+)", warning)
if(m):
print('group_0', m.group(0))
print('group_1', m.group(1))
include = m.group(1)
# Recherche la ligne dans laquelle ajouter le #include
# On l'ajoutera après le dernier "#include <..."
num_ligne = 0
num_ligne_include_system = 0
num_ligne_include_local = 0
for ligne in liste:
num_ligne += 1
if ligne.find('#include <') > -1:
num_ligne_include_system = num_ligne
elif ligne.find('#include "') > -1:
num_ligne_include_local = num_ligne
num_ligne_include = max(num_ligne_include_system, num_ligne_include_local)
if num_ligne_include == 0:
print("WARNING : #include not found in file ", ficpath)
return
new_liste = []
num_ligne = 0
fic2 = open(get_src_path(ficpath), "r")
liste2 = fic_readlines(fic2)
for ligne in liste2:
num_ligne += 1
new_liste.append(ligne)
if num_ligne == num_ligne_include:
new_liste.append(include+'\n')
newliste=fic_writelines(new_liste)
fichier = open(get_src_path(ficpath), "w")
fichier.writelines(newliste)
else:
print("ERROR : Pattern of include_what_you_use not found")
return
##################################
HOOKS_DICT = {
extra_space_before_last_semicolon:{'pattern':'whitespace/semicolon', 'pattern_AND':'Extra space before last semicolon'},
missing_space_after_semicolon:{'pattern':'whitespace/semicolon', 'pattern_AND':'Missing space after'},
missing_space_around_operator_egal:{'pattern':'whitespace/operators', 'pattern_AND':'Missing spaces around = '},
extra_space_for_operator_add:{'pattern':'whitespace/operators', 'pattern_AND':'Extra space for operator ++'},
extra_space_for_operator_diff:{'pattern':'whitespace/operators', 'pattern_AND':'Extra space for operator !'},
missing_space_around_operator_double_chevron:{'pattern':'whitespace/operators', 'pattern_AND':'Missing spaces around << '},
missing_space_around_operator_simple_chevron:{'pattern':'whitespace/operators', 'pattern_AND':'Missing spaces around < '},
missing_space_around_operator_diff_egal:{'pattern':'whitespace/operators', 'pattern_AND':'Missing spaces around !='},
missing_space_around_operator_double_egal:{'pattern':'whitespace/operators', 'pattern_AND':'Missing spaces around =='},
space_between_comments_and_code:{'pattern':'whitespace/comments', 'pattern_AND':'At least two spaces is best between code and comments'},
space_between_comments_and_double_slash:{'pattern':'whitespace/comments', 'pattern_AND':'Should have a space between // and comment '},
legal_copyright:{'pattern':'legal/copyright'}, # Script à n'executer qu'une fois
ifndef_header:{'pattern':'build/header_guard', 'pattern_AND':'#ifndef header guard has wrong style, please use'},
# no_ifndef_header:{'pattern':u'build/header_guard', 'pattern_AND':u'No #ifndef header guard found'},
endif_line:{'pattern':'build/header_guard', 'pattern_AND':'#endif line should be'},
whitespace_end_of_line:{'pattern':'whitespace/end_of_line', 'pattern_AND':'Line ends in whitespace'},
missing_space_after_comma:{'pattern':'whitespace/comma'},
namespace_should_be_terminated:{'pattern':'readability/namespace', 'pattern_AND':'Namespace should be terminated with'},
anonymous_namespace_should_be_terminated:{'pattern':'readability/namespace', 'pattern_AND':'Anonymous namespace should be terminated with'},
extra_space_after_opening_paranthesis:{'pattern':'whitespace/parens', 'pattern_AND':'Extra space after ('},
extra_space_before_closing_paranthesis:{'pattern':'whitespace/parens', 'pattern_AND':'Extra space before )'},
extra_space_before_opening_paranthesis_in_function_call:{'pattern':'whitespace/parens', 'pattern':'Extra space before ( in function call'},
missing_space_before_opening_parenthesis_in_for:{'pattern':'whitespace/parens', 'pattern_AND':'Missing space before ( in for('},
missing_space_before_opening_parenthesis_in_if:{'pattern':'whitespace/parens', 'pattern_AND':'Missing space before ( in if('},
missing_space_before_opening_parenthesis_in_switch:{'pattern':'whitespace/parens', 'pattern_AND':'Missing space before ( in switch('},
missing_space_before_opening_parenthesis_in_while:{'pattern':'whitespace/parens', 'pattern_AND':'Missing space before ( in while('},
mismatching_spaces_inside_paranthesis:{'pattern':'whitespace/parens', 'pattern_AND':'Mismatching spaces inside ()'},
missing_space_before_public_protected_private:{'pattern':'whitespace/indent', 'pattern_AND':' should be indented +1 space inside class'},
wrong_number_of_spaces_while_indenting:{'pattern':'whitespace/indent', 'pattern_AND':'Weird number of spaces at line-start'},
no_newline_at_the_end_of_file:{'pattern':'whitespace/ending_newline'},
order_of_storage_class_specifier:{'pattern':'build/storage_class'},
use_spaces_instead_of_tab:{'pattern':'whitespace/tab'},
no_semicolon_after_brace:{'pattern':'readability/braces', 'pattern_AND':'You don\'t need a ; after a }'},
# position_of_else:{'pattern':u'readability/braces', 'pattern_AND':u'If an else has a brace on one side'},
# else_should_be_previous_line:{'pattern':u'whitespace/newline', 'pattern_AND':u'An else should appear on the same line as the preceding'},
position_of_opening_brace:{'pattern':'whitespace/braces', 'pattern_AND':'{ should almost always be at the end of the previous line'},
missing_space_before_opening_brace:{'pattern':'whitespace/braces', 'pattern_AND':'Missing space before {'},
missing_space_before_else:{'pattern':'whitespace/braces', 'pattern_AND':'Missing space before else'},
make_const_reference:{'pattern':'runtime/references', 'pattern_AND':'Is this a non-const reference? If so, make const or use a pointer'},
make_constructor_explicit:{'pattern':'runtime/explicit'},
cpp_file_should_include_h_file:{'pattern':'build/include', 'pattern_AND':'should include its header file'},
_h_file_already_included:{'pattern':'build/include', 'pattern_AND':'already included at'},
replace_short_by_int16:{'pattern':'runtime/int', 'pattern_AND':'Use int16/int64/etc, rather than the C type short'},
replace_long_by_int64:{'pattern':'runtime/int', 'pattern_AND':'Use int16/int64/etc, rather than the C type long'},
do_not_leave_blank_line_after_public_protected_private:{'pattern':'whitespace/blank_line', 'pattern_AND':'Do not leave a blank line after'},
do_not_leave_blank_line_at_the_start_of_code_block:{'pattern':'whitespace/blank_line', 'pattern_AND':'Redundant blank line at the start of a code block should be deleted'},
do_not_leave_blank_line_at_the_end_of_code_block:{'pattern':'whitespace/blank_line', 'pattern_AND':'Redundant blank line at the end of a code block should be deleted'},
add_blank_line_before_public:{'pattern':'whitespace/blank_line', 'pattern_AND':'"public:" should be preceded by a blank line'},
add_blank_line_before_protected:{'pattern':'whitespace/blank_line', 'pattern_AND':'"protected:" should be preceded by a blank line'},
add_blank_line_before_private:{'pattern':'whitespace/blank_line', 'pattern_AND':'"private:" should be preceded by a blank line'},
add_include_what_you_use:{'pattern':'build/include_what_you_use'},
}
HOOKS_DELETING_OR_ADDING_LINES = [no_newline_at_the_end_of_file, position_of_opening_brace, _h_file_already_included,
add_blank_line_before_public, add_blank_line_before_protected, add_blank_line_before_private, do_not_leave_blank_line_after_public_protected_private, do_not_leave_blank_line_at_the_start_of_code_block, do_not_leave_blank_line_at_the_end_of_code_block, legal_copyright, add_include_what_you_use]
HOOKS_PARSING_THE_WHOLE_FILE = [cpp_file_should_include_h_file, do_not_leave_blank_line_after_public_protected_private,
do_not_leave_blank_line_at_the_start_of_code_block, do_not_leave_blank_line_at_the_end_of_code_block, legal_copyright, ifndef_header, add_include_what_you_use] #Hook à éxecuter avant les autres hooks
def replace_line_no(path, nol, oldline, newline):
"""
Remplace, la ligne No nol du fichier path (relatif à SRCROOTDIR) par la chaîne newline (un unicode)
oldline sert uniquement pour vérifier que tout est ok
"""
print("replace_line_no : ", oldline, " by ", newline)
# récupérer le contenu du fichier
fic = open(get_src_path(path), "r")
liste = fic.readlines()
fic.close()
# test de corruption
if liste[nol-1].decode(ENCODING) != oldline :
raise Exception("Le fichier source %s semble être corrompu" %path)
# remplacement de la ligne
liste[nol-1] = newline.encode(ENCODING)
# recréation du fichier corrigé
fic = open(get_src_path(path), "w")
fic.writelines(liste)
fic.close()
def replace_fic_copyright(ficpath, warning=None):
"""
Remplace le fichier sans la ligne copyright par le fichier avec la ligne copyright
"""
fic = open(get_src_path(ficpath), "r")
liste=fic_readlines(fic)
fic.close()
new_liste = []
if liste[0].find('/ Copyright (C) 2014-20xx CEA/DEN, EDF R&D\n\n')== -1:
newliste=['// Copyright (C) 2014-20xx CEA/DEN, EDF R&D\n\n']+liste
newliste=fic_writelines(newliste)
fic = open(get_src_path(ficpath), "w")
fic.writelines(newliste)
fic.close()
def replace_fic_ifndef(ficpath, ficline, warning, mode):
"""
Remplace dans le fichier, toutes les erreurs sur le style des #define et #ifndef à partir du warning
"""
fic = open(get_src_path(ficpath),'r')
liste = fic_readlines(fic)
new_liste = []
if mode == "no_guard_found":
m = re.match("(.*)No #ifndef header guard found, suggested CPP variable is: (.+) (.+)", warning)
else:
m = re.match("(.*)ifndef header guard has wrong style, please use: (.+) (.+)", warning)
if(m):
print('group_0', m.group(0))
print('group_1', m.group(1))
print('group_2', m.group(2))
# Header à changer
header_guard=m.group(2)
# Recherche de la ligne à modifier
i = 0
trouve = False
for ligne in liste:
i += 1
if i == ficline:
if ligne.find('#ifndef') >= 0:
new_liste.append("#ifndef "+header_guard+"\n")
trouve = True
else:
print("ERROR : Pattern #ifndef not found in line ", ficline)
return
else:
if trouve == True:
if ligne.find('#define') >= 0:
new_liste.append("#define "+header_guard+"\n")
trouve = False
else:
print("WARNING : Pattern #define not found in the line following the pattern #ifndef, we abandon.")
return
else:
new_liste.append(ligne)
else:
print("ERROR : Pattern not found : \"#ifndef header guard has wrong style, please use\"")
newliste=fic_writelines(new_liste)
fichier = open(get_src_path(ficpath), "w")
fichier.writelines(newliste)
def get_hook(warning, fichier):
"""
Fait le matching entre un warning et le hook permettant de le traiter.
Les critères pour sélectionner un ou l'autre des hook sont consignés dans un dict associé (dans HOOKS_DICT) à chaque hook disponible.
Le format de chaque dict de critère est le suivant :
{
"pattern": <motif principal devant se trouver dans le texte du warning>,
"pattern_AND": <motif secondaire devant se trouver également dans le texte du warning>,
"pattern_NOT": <motif secondaire ne devant pas se trouver dans le texte du warning>,
"ext": <extension du fichier considéré>
}
Seul le premier hook trouvé est renvoyé.
Les arguments sont les suivants :
* warning : le texte unicode du warning
* fichier : le chemin vers le fichier concerné
"""
def test_it(condition, data, warning, fichier):
if condition in ["pattern", "pattern_AND"] :
if data in warning:
return True
elif condition in ["PATTERN_NOT"]:
if data not in warning:
return True
elif condition in ["ext"]:
if data not in os.path.splitext(fichier)[1]:
return True
return False
for key, val in HOOKS_DICT.items(): # boucle sur les hooks existants
test = None
for condition, data in val.items():
if test is False:
# si une condition n'est pas réalisée => c'est pas le bon hook
continue
test = test_it(condition, data, warning, fichier)
if test is True:
return key
return
def main_routine(cpplint_output_file):
logfile = open(cpplint_output_file,"r")
generateur_w = create_warning_generator(logfile)
last_ficpath_with_modified_nb_lines = ""
for ficpath, ficline, warning in generateur_w:
oldline = get_line_no(ficpath, ficline)
if ficline > 0:
previous_oldline = get_line_no(ficpath, ficline-1)
else:
previous_oldline = None
print("===\nNew warning:")
print("\tFile = "+ficpath)
print("\tlast_ficpath_with_modified_nb_lines = "+last_ficpath_with_modified_nb_lines)
print("\tNo ligne =" , ficline)
if VERBOSE_FLAG == "True":
print("\tWarning ='"+warning+"'")
print("\tOld text of current line = '"+oldline+"'")
if previous_oldline:
print("\tOld text of previous line = '"+previous_oldline+"'")
if ficpath == last_ficpath_with_modified_nb_lines:
print("File ", ficpath, "already modified. Waiting next cpplint run to process it.")
continue
hook = get_hook(warning, ficpath)
print("hook = ", hook)
if hook is None:
print("No hook found")
continue
if VERBOSE_FLAG == "True":
print("\t=> Processing with hook", hook)
if hook in HOOKS_DELETING_OR_ADDING_LINES:
last_ficpath_with_modified_nb_lines = ficpath
if hook in HOOKS_PARSING_THE_WHOLE_FILE:
hook(ficpath, ficline, warning)
print("Done")
continue
# Cas particulier pour le hook make_const_reference : il faut faire un traitement sur le fichier .cpp associé au fichier .h concerné par le hook
if hook in [make_const_reference]:
if ficpath.find('.h') > -1:
newline, previous_newline, huchk = hook(ficpath, oldline, previous_oldline, warning)
else:
if H_FILE_MAKE_CONST_REFERENCE_MODIFIED:
continue
else:
newline, previous_newline, huchk = hook(ficpath, oldline, previous_oldline, warning)
else:
newline, previous_newline, huchk = hook(oldline, previous_oldline, warning)
if VERBOSE_FLAG == "True":
print("\tNew text = '"+newline+"'")
if huchk:
if previous_newline:
print("Replace line : \n'%s'\n with line \n'%s'\n O/N ? :"%(previous_oldline, previous_newline))
reponse = input()
if reponse in ['O', 'o']:
replace_line_no(ficpath, ficline-1, previous_oldline, previous_newline)
print("Replacement done.")
else :
print("Replacement aborted.")
print("Replace line : \n'%s'\n with line \n'%s'\n O/N ? :"%(oldline, newline))
reponse = input()
if reponse in ['O', 'o']:
replace_line_no(ficpath, ficline, oldline, newline)
print("Replacement done.")
else :
print("Replacement aborted.")
else :
if previous_newline:
replace_line_no(ficpath, ficline-1, previous_oldline, previous_newline)
replace_line_no(ficpath, ficline, oldline, newline)
print("Done")
logfile.close()
if __name__ == '__main__':
H_FILE_MAKE_CONST_REFERENCE_MODIFIED = False
parser = argparse.ArgumentParser()
parser.add_argument("--cpplint_output_file", type=str, help="Fichier de rapport cpplint à lire en entrée")
args = parser.parse_args()
if not args.cpplint_output_file:
parser.print_help()
else:
main_routine(args.cpplint_output_file)