reports/Builder__LintReport.st
author Claus Gittinger <cg@exept.de>
Thu, 28 Mar 2019 13:54:38 +0100
changeset 542 aa25a71be62a
parent 267 9f55d8893118
permissions -rw-r--r--
#DOCUMENTATION by cg
class: stx_goodies_builder_quickSelfTest
class definition

class: stx_goodies_builder_quickSelfTest class
added:18 methods
jan@71
     1
"{ Package: 'stx:goodies/builder/reports' }"
jan@71
     2
jan@71
     3
"{ NameSpace: Builder }"
jan@71
     4
jan@71
     5
Report subclass:#LintReport
jan@71
     6
	instanceVariableNames:'environment rules'
jan@71
     7
	classVariableNames:''
jan@71
     8
	poolDictionaries:''
jan@71
     9
	category:'Builder-Reports'
jan@71
    10
!
jan@71
    11
jan@71
    12
jan@71
    13
!LintReport methodsFor:'accessing - defaults'!
jan@71
    14
jan@71
    15
defaultFileSuffix
jan@71
    16
jan@71
    17
    ^ 'Lint'
jan@71
    18
jan@71
    19
    "Modified: / 08-10-2011 / 10:49:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@71
    20
!
jan@71
    21
jan@71
    22
defaultFormat
jan@71
    23
    "raise an error: must be redefined in concrete subclass(es)"
jan@71
    24
jan@71
    25
    ^ LintReportFormat::PMD new
jan@71
    26
jan@71
    27
    "Modified: / 25-11-2011 / 22:06:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@79
    28
!
jan@79
    29
jan@79
    30
defaultName
jan@79
    31
jan@79
    32
    environment isNil ifTrue:[^super defaultName].
jan@79
    33
    ^environment label
jan@79
    34
jan@79
    35
    "Modified: / 25-11-2011 / 22:06:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@79
    36
    "Created: / 13-01-2012 / 12:43:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@71
    37
! !
jan@71
    38
jan@117
    39
!LintReport methodsFor:'command line options'!
jan@117
    40
jan@117
    41
cmdlineOptionRuleset
jan@117
    42
jan@117
    43
    ^CmdLineOption new
jan@117
    44
        short: $s;
jan@117
    45
        long: 'ruleset';
jan@233
    46
        description: 'defines set of rules to check against.';
jan@117
    47
        action:[:option |
jan@117
    48
            self setupRulesFrom: option.
jan@117
    49
        ];
jan@117
    50
        yourself
jan@117
    51
jan@117
    52
    "Created: / 28-02-2013 / 23:13:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@233
    53
    "Modified: / 27-05-2014 / 16:54:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@117
    54
! !
jan@117
    55
jan@71
    56
!LintReport methodsFor:'generating'!
jan@71
    57
jan@254
    58
generateClass:class inPackage:package 
jan@267
    59
    | sourceInfo |
jan@71
    60
jan@254
    61
    sourceInfo := ReportSourceInfo forClass:class inPackage:package.
jan@267
    62
    format writeFile:(sourceInfo pathNameAbsolute: true)
jan@254
    63
        with:[
jan@254
    64
            self generateClass:class source:sourceInfo inPackage: package.
jan@254
    65
            self generateClass:class class source:sourceInfo inPackage: package.
jan@71
    66
        ].
jan@71
    67
jan@254
    68
    "Created: / 15-12-2014 / 10:46:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@267
    69
    "Modified: / 16-12-2014 / 10:38:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@71
    70
!
jan@71
    71
jan@118
    72
generateClass: aClass selector: aSelector source: sourceInfo
jan@118
    73
        | matching |
jan@71
    74
        matching := rules select: [ :each | 
jan@71
    75
                (self isSelectorEnvironment: each result)
jan@71
    76
                        and: [ each result includesSelector: aSelector in: aClass ] ].
jan@118
    77
        self generateViolations: matching class: aClass selector: aSelector source: sourceInfo
jan@71
    78
jan@71
    79
    "Created: / 07-10-2011 / 11:04:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@118
    80
    "Modified: / 01-03-2013 / 18:10:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@71
    81
!
jan@71
    82
jan@254
    83
generateClass: aClass selector: aSelector source: sourceInfo inPackage: package
jan@254
    84
        | matching |
jan@254
    85
        matching := rules select: [ :each | 
jan@254
    86
                (self isSelectorEnvironment: each result)
jan@254
    87
                        and: [ each result includesSelector: aSelector in: aClass ] ].
jan@254
    88
        self generateViolations: matching class: aClass selector: aSelector source: sourceInfo
jan@71
    89
jan@254
    90
    "Created: / 15-12-2014 / 11:04:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@254
    91
!
jan@71
    92
jan@254
    93
generateClass: aClass source: sourceInfo inPackage: package 
jan@254
    94
jan@254
    95
    | matching |
jan@254
    96
    (environment definesClass: aClass) ifTrue: [
jan@254
    97
        matching := rules select: [ :rule | (self isClassEnvironment: rule result) and: [ rule result includesClass: aClass ] ].
jan@254
    98
        self generateViolations: matching class: aClass source: sourceInfo
jan@254
    99
    ].
jan@254
   100
    (environment selectorsForClass: aClass) asSortedCollection do: [ :selector | 
jan@254
   101
        self generateClass: aClass selector: selector source: sourceInfo inPackage: package
jan@254
   102
    ]
jan@254
   103
jan@254
   104
    "Created: / 15-12-2014 / 11:05:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@254
   105
!
jan@254
   106
jan@254
   107
generateClassesInPackage:package 
jan@254
   108
    (ProjectDefinition searchForClassesWithProject:package) do:[:cls | 
jan@254
   109
        self generateClass:cls inPackage:package
jan@254
   110
    ].
jan@254
   111
jan@254
   112
    "Created: / 15-12-2014 / 10:52:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@254
   113
!
jan@254
   114
jan@254
   115
generateExtensionsInPackage:package 
jan@267
   116
    | sourceInfo |
jan@254
   117
jan@254
   118
    sourceInfo := ReportSourceInfo forExtensionsInPackage:package.
jan@267
   119
    format writeFile:(sourceInfo pathNameAbsolute: true)
jan@254
   120
        with:[
jan@254
   121
            (ProjectDefinition searchForExtensionsWithProject:package) do:[:method | 
jan@254
   122
                self 
jan@254
   123
                    generateClass:method mclass
jan@254
   124
                    selector:method selector
jan@254
   125
                    source:sourceInfo
jan@254
   126
                    inPackage: package.
jan@254
   127
            ].
jan@254
   128
        ].
jan@254
   129
jan@254
   130
    "Created: / 15-12-2014 / 10:50:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@267
   131
    "Modified: / 16-12-2014 / 10:38:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@254
   132
!
jan@254
   133
jan@254
   134
generatePackage: package
jan@254
   135
    self generateClassesInPackage:package.  
jan@254
   136
    self generateExtensionsInPackage:package.
jan@254
   137
jan@254
   138
    "Created: / 15-12-2014 / 10:42:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@71
   139
!
jan@71
   140
jan@118
   141
generateViolations: aCollection class: aClass selector: aSelector source: sourceInfo
jan@118
   142
    | method offset  |
jan@71
   143
jan@254
   144
    (AbstractSourceCodeManager isVersionMethodSelector: aSelector) ifTrue:[ ^ self ].
jan@254
   145
    (AbstractSourceCodeManager isExtensionsVersionMethodSelector: aSelector) ifTrue:[ ^ self ].
jan@254
   146
jan@254
   147
jan@118
   148
    method := aClass compiledMethodAt: aSelector.
jan@118
   149
    offset := sourceInfo offsetOfMethod: method.
jan@71
   150
    aCollection do: [ :rule |
jan@254
   151
        | tree |
jan@254
   152
jan@254
   153
        tree := RBParser parseMethod: method source.
jan@254
   154
        rule result selectionIntervalsForSource: method source tree: tree in: method mclass do:[:intervalOrNil | 
jan@254
   155
            | interval start stop |
jan@254
   156
jan@254
   157
            interval := interval isNil ifTrue: [ 1 to: method source size ].
jan@254
   158
            start := sourceInfo lineAndColumnOfOffset: offset + interval first - 1.
jan@254
   159
            stop  := sourceInfo lineAndColumnOfOffset: offset + interval last - 1.
jan@254
   160
jan@254
   161
            format writeViolation: rule
jan@254
   162
                       class: aClass selector: aSelector
jan@254
   163
                   startLine: start x column: start y
jan@254
   164
                    stopLine: stop x  column: stop  y.
jan@254
   165
        ]
jan@254
   166
    ]
jan@254
   167
jan@254
   168
    "Created: / 01-03-2013 / 18:05:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@254
   169
    "Modified: / 15-12-2014 / 11:32:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@254
   170
!
jan@254
   171
jan@254
   172
generateViolations: aCollection class: aClass source: sourceInfo
jan@254
   173
    | method offset start stop |
jan@254
   174
jan@254
   175
    start := sourceInfo lineAndColumnOfOffset: 1.
jan@254
   176
    stop  := sourceInfo lineAndColumnOfOffset: SmallInteger maxVal.
jan@254
   177
    aCollection do: [ :rule |
jan@254
   178
        | interval  |
jan@71
   179
jan@71
   180
        format writeViolation: rule
jan@254
   181
                   class: aClass selector: nil
jan@118
   182
               startLine: start x column: start y
jan@118
   183
                stopLine: stop x  column: stop  y.
jan@71
   184
    ]
jan@71
   185
jan@254
   186
    "Created: / 15-12-2014 / 11:13:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@71
   187
! !
jan@71
   188
jan@71
   189
!LintReport methodsFor:'initialization'!
jan@71
   190
jan@71
   191
setupForClasses: classes
jan@71
   192
jan@71
   193
    environment := BrowserEnvironment new forClasses: classes.
jan@71
   194
    environment label: name
jan@71
   195
jan@71
   196
    "Created: / 04-08-2011 / 14:40:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@71
   197
!
jan@71
   198
jan@254
   199
setupForPackages: pkgs
jan@254
   200
    pkgs isEmpty ifTrue:[^self].
jan@71
   201
    environment := PackageEnvironment 
jan@71
   202
                    onEnvironment: BrowserEnvironment new
jan@254
   203
                    packageNames: pkgs.
jan@79
   204
    name isNil ifTrue:[
jan@254
   205
        pkgs size > 1 ifTrue:[
jan@254
   206
            name :=  pkgs size printString , ' packages'.
jan@79
   207
        ] ifFalse:[
jan@254
   208
            name :=  pkgs anElement
jan@79
   209
        ]
jan@79
   210
    ].
jan@71
   211
jan@71
   212
    environment label: name.
jan@71
   213
jan@71
   214
    "
jan@71
   215
        LintReport runPackage:'stx:goodies/monticello'.
jan@71
   216
        LintReport runPackage:'stx:libjava'
jan@71
   217
    "
jan@71
   218
jan@71
   219
    "Created: / 04-08-2011 / 14:40:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@254
   220
    "Modified: / 15-12-2014 / 10:52:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@71
   221
! !
jan@71
   222
jan@71
   223
!LintReport methodsFor:'private'!
jan@71
   224
jan@71
   225
lineAndColumn: aString at: anInteger
jan@71
   226
	| line last stream |
jan@71
   227
	line := 1.
jan@71
   228
	last := 0.
jan@71
   229
	stream := aString readStream.
jan@71
   230
	[ (stream nextLine isNil or: [ anInteger <= stream position ])
jan@71
   231
		ifTrue: [ ^ line @ (anInteger - last) ].
jan@71
   232
	last := stream position.
jan@71
   233
	line := line + 1 ]
jan@71
   234
		repeat
jan@71
   235
!
jan@71
   236
jan@254
   237
sourceFilenameForClass:class package: package 
jan@254
   238
    | fn  cls |
jan@71
   239
jan@254
   240
    cls := class theNonMetaclass.
jan@254
   241
    fn := package copy
jan@254
   242
            replaceAll:$: with:$_;
jan@254
   243
            replaceAll:$/ with:$_;
jan@254
   244
            yourself.
jan@254
   245
    fn := fn , '_' , (cls asString copyReplaceAll:$: with:$_) , '.' 
jan@254
   246
            , cls programmingLanguage sourceFileSuffix.
jan@254
   247
    ^ self encodeFilename:fn.
jan@71
   248
jan@71
   249
    "
jan@71
   250
        Builder::LintReportFormat::CheckStyle basicNew
jan@71
   251
            sourceFilenameFor: Class
jan@71
   252
jan@71
   253
        Builder::LintReportFormat::CheckStyle basicNew
jan@254
   254
            sourceFilenameFor: Builder::LintReportFormat"
jan@254
   255
jan@254
   256
    "Created: / 15-12-2014 / 10:46:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@254
   257
!
jan@254
   258
jan@254
   259
sourceFilenameForExtensionsInPackage: package 
jan@254
   260
    | fn |
jan@254
   261
jan@254
   262
    fn := package copy
jan@254
   263
            replaceAll:$: with:$_;
jan@254
   264
            replaceAll:$/ with:$_;
jan@254
   265
            yourself.
jan@254
   266
    fn := fn , '_' , 'extensions.st'.
jan@254
   267
    ^ self encodeFilename:fn.
jan@254
   268
jan@71
   269
    "
jan@254
   270
        Builder::LintReportFormat::CheckStyle basicNew
jan@254
   271
            sourceFilenameFor: Class
jan@71
   272
jan@254
   273
        Builder::LintReportFormat::CheckStyle basicNew
jan@254
   274
            sourceFilenameFor: Builder::LintReportFormat"
jan@254
   275
jan@254
   276
    "Created: / 15-12-2014 / 10:50:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@71
   277
! !
jan@71
   278
jan@71
   279
!LintReport methodsFor:'running'!
jan@71
   280
jan@71
   281
runReport
jan@82
   282
    | wasTryLocalSources |
jan@71
   283
jan@82
   284
    [
jan@82
   285
        wasTryLocalSources := Class tryLocalSourceFirst.
jan@84
   286
        Class tryLocalSourceFirst: true.
jan@82
   287
        SmalllintChecker 
jan@82
   288
            runRule: (RBCompositeLintRule rules: rules)
jan@82
   289
            onEnvironment: environment.
jan@254
   290
        environment packageNames do:[:packageName | 
jan@254
   291
            self generatePackage: packageName  
jan@254
   292
        ].
jan@82
   293
    ] ensure:[
jan@82
   294
        Class tryLocalSourceFirst: wasTryLocalSources 
jan@82
   295
    ]
jan@71
   296
jan@254
   297
    "Modified: / 15-12-2014 / 11:06:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@71
   298
!
jan@71
   299
jan@71
   300
setUp
jan@71
   301
jan@71
   302
    super setUp.
jan@117
   303
    rules isNil ifTrue:[
jan@254
   304
        rules := RBBuiltinRuleSet rulesetBuiltinDefault flatten   
jan@117
   305
    ].
jan@71
   306
jan@71
   307
    "Created: / 04-08-2011 / 14:35:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@254
   308
    "Modified: / 15-12-2014 / 11:35:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@117
   309
!
jan@117
   310
jan@117
   311
setupRulesFrom: filename
jan@117
   312
    | file |    
jan@117
   313
    file := filename asFilename.
jan@117
   314
    file readingFileDo:[:s|
jan@117
   315
        | spec |
jan@117
   316
        spec := Parser parseLiteralArray: s.
jan@117
   317
        rules := spec decodeAsLiteralArray rules.
jan@117
   318
    ]
jan@117
   319
jan@117
   320
    "Created: / 28-02-2013 / 23:17:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
jan@71
   321
! !
jan@71
   322
jan@71
   323
!LintReport methodsFor:'testing'!
jan@71
   324
jan@71
   325
isClassEnvironment: anEnvironment
jan@71
   326
	^ #(CategoryEnvironment ClassEnvironment VariableEnvironment) includes: anEnvironment class name
jan@71
   327
!
jan@71
   328
jan@71
   329
isSelectorEnvironment: anEnvironment
jan@71
   330
	^ #(SelectorEnvironment ParseTreeEnvironment VariableEnvironment) includes: anEnvironment class name
jan@71
   331
! !
jan@71
   332
jan@71
   333
!LintReport class methodsFor:'documentation'!
jan@71
   334
jan@71
   335
version
jan@71
   336
    ^ '$Header$'
jan@71
   337
!
jan@71
   338
jan@71
   339
version_CVS
jan@71
   340
    ^ '$Header$'
jan@71
   341
!
jan@71
   342
jan@71
   343
version_SVN
jan@162
   344
    ^ '$Id$'
jan@71
   345
! !
jan@71
   346