--- a/reports/Builder__LintReport.st Fri Mar 01 10:42:50 2013 +0100
+++ b/reports/Builder__LintReport.st Fri Mar 01 19:12:32 2013 +0100
@@ -9,6 +9,20 @@
category:'Builder-Reports'
!
+Object subclass:#SourceInfo
+ instanceVariableNames:'klass filename offsets lineEnds'
+ classVariableNames:''
+ poolDictionaries:''
+ privateIn:LintReport
+!
+
+Stream subclass:#LineCountingStream
+ instanceVariableNames:'position lineEnds'
+ classVariableNames:''
+ poolDictionaries:''
+ privateIn:LintReport::SourceInfo
+!
+
!LintReport class methodsFor:'class initialization'!
@@ -64,72 +78,66 @@
!LintReport methodsFor:'generating'!
generateClass: aClass
- | sourceStream sourceName |
- sourceStream := WriteStream on: String new.
+ | sourceInfo sourceName |
+ sourceInfo := SourceInfo for: aClass.
sourceName := self encodeFilename: (self sourceFilenameFor: aClass).
format writeFile: sourceName with: [
- self generateClass: aClass source: sourceStream.
- self generateClass: aClass class source: sourceStream.
+ self generateClass: aClass source: sourceInfo.
+ self generateClass: aClass class source: sourceInfo.
].
- format writeSource: sourceStream contents to: sourceName
+ format writeSource: sourceInfo contents to: sourceName
"Created: / 06-10-2011 / 23:54:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 01-03-2013 / 17:59:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
-generateClass: aClass selector: aSelector source: sourceStream
- | offset source matching |
- offset := self
- lineAndColumn: sourceStream contents
- at: sourceStream position.
- sourceStream
- nextPutAll: (source := self convert: (aClass sourceCodeAt: aSelector));
- nextPut: Character lf; nextPut: Character lf.
+generateClass: aClass selector: aSelector source: sourceInfo
+ | matching |
matching := rules select: [ :each |
(self isSelectorEnvironment: each result)
and: [ each result includesSelector: aSelector in: aClass ] ].
- self generateViolations: matching class: aClass selector: aSelector source: source offset: offset
+ self generateViolations: matching class: aClass selector: aSelector source: sourceInfo
"Created: / 07-10-2011 / 11:04:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 01-03-2013 / 18:10:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
-generateClass: aClass source: sourceStream
+generateClass: aClass source: sourceInfo
- | offset source matching |
- offset := self
- lineAndColumn: sourceStream contents
- at: sourceStream position.
- sourceStream
- nextPutAll: (source := self convert: aClass definition);
- nextPut: Character lf; nextPut: Character lf.
+ | matching |
(environment definesClass: aClass) ifTrue: [
matching := rules select: [ :rule |
(self isClassEnvironment: rule result)
and: [ rule result includesClass: aClass ] ].
- self generateViolations: matching class: aClass selector: nil source: source offset: offset ].
+ self generateViolations: matching class: aClass selector: nil source: sourceInfo].
(environment selectorsForClass: aClass) asSortedCollection
- do: [ :selector | self generateClass: aClass selector: selector source: sourceStream]
+ do: [ :selector | self generateClass: aClass selector: selector source: sourceInfo]
"Created: / 07-10-2011 / 10:29:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 01-03-2013 / 18:11:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
-generateViolations: aCollection class: aClass selector: aSelector source: aString offset: aPoint
+generateViolations: aCollection class: aClass selector: aSelector source: sourceInfo
+ | method offset |
+ method := aClass compiledMethodAt: aSelector.
+ offset := sourceInfo offsetOfMethod: method.
aCollection do: [ :rule |
| interval start stop |
- interval := (rule result selectionIntervalFor: aString) ifNil: [ 1 to: aString size ].
- start := self lineAndColumn: aString at: interval first.
- stop := self lineAndColumn: aString at: interval last.
+ interval := (rule result selectionIntervalFor: method source) isNil ifTrue: [ 1 to: method source size ].
+ start := sourceInfo lineAndColumnOfOffset: offset + interval first - 1.
+ stop := sourceInfo lineAndColumnOfOffset: offset + interval last - 1.
format writeViolation: rule
class: aClass selector: aSelector
- startLine: aPoint x + start x column: aPoint y + start y - 1
- stopLine: aPoint x + stop x column: aPoint y + stop y - 1.
+ startLine: start x column: start y
+ stopLine: stop x column: stop y.
]
- "Created: / 25-11-2011 / 22:23:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Created: / 01-03-2013 / 18:05:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!LintReport methodsFor:'initialization'!
@@ -182,10 +190,11 @@
sourceFilenameFor: aClass
- | fn |
+ | fn cls |
- fn := aClass package asString replaceAll:$: with:$_;replaceAll:$/ with:$_.
- fn := fn , '_' , (aClass asString copyReplaceAll:$: with: $_), '.' , aClass programmingLanguage sourceFileSuffix.
+ cls := aClass theNonMetaclass.
+ fn := cls package asString replaceAll:$: with:$_;replaceAll:$/ with:$_.
+ fn := fn , '_' , (cls asString copyReplaceAll:$: with: $_), '.' , cls programmingLanguage sourceFileSuffix.
^self encodeFilename: fn.
@@ -198,6 +207,7 @@
"
"Created: / 07-10-2011 / 09:06:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 01-03-2013 / 18:00:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!LintReport methodsFor:'running'!
@@ -255,6 +265,170 @@
^ #(SelectorEnvironment ParseTreeEnvironment VariableEnvironment) includes: anEnvironment class name
! !
+!LintReport::SourceInfo class methodsFor:'instance creation'!
+
+for: aClass
+ ^self new setClass: aClass
+
+ "Created: / 01-03-2013 / 17:50:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!LintReport::SourceInfo methodsFor:'initialization'!
+
+setClass: aClass
+ klass := aClass theNonMetaclass.
+ self setup.
+
+ "Created: / 01-03-2013 / 17:49:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+setup
+ "To be called after class is set"
+
+ | stream |
+
+ stream := LineCountingStream new.
+ offsets := Dictionary new.
+
+ [
+ self fileOutOn: stream.
+ ] on: AbstractSourceFileWriter methodSourceRewriteQuery do:[:rewriteQuery |
+ | m |
+
+ m := rewriteQuery method.
+ offsets at: m put: stream position + 1.
+ rewriteQuery proceed.
+ ].
+ lineEnds := stream lineEnds
+
+ "
+ SourceInfo for: Builder::ReportRunner
+ "
+
+ "Created: / 01-03-2013 / 17:30:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!LintReport::SourceInfo methodsFor:'utilities'!
+
+fileOutOn:aStream
+ klass fileOutOn: aStream withTimeStamp:false
+
+ "Created: / 01-03-2013 / 17:51:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!LintReport::SourceInfo::LineCountingStream class methodsFor:'instance creation'!
+
+new
+ "return an initialized instance"
+
+ ^ self basicNew initialize.
+! !
+
+!LintReport::SourceInfo::LineCountingStream methodsFor:'accessing'!
+
+contents
+ "return the entire contents of the stream.
+ For a readStream, that is the rest (i.e. upToEnd),
+ for a writeStream, that is the collected data. As we do not know here,
+ what we are, this is the responsibility of a subclass..."
+
+ ^ self shouldNotImplement
+
+ "Modified: / 01-03-2013 / 17:36:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+lineEnds
+ ^ lineEnds
+!
+
+position
+ ^ position
+! !
+
+!LintReport::SourceInfo::LineCountingStream methodsFor:'initialization'!
+
+initialize
+ "Invoked when a new instance is created."
+
+ "/ please change as required (and remove this comment)
+ position := 0.
+ lineEnds := OrderedCollection new.
+
+ "/ super initialize. -- commented since inherited method does nothing
+
+ "Modified: / 01-03-2013 / 17:39:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!LintReport::SourceInfo::LineCountingStream methodsFor:'queries'!
+
+isReadable
+ "return true, if reading is supported by the recevier.
+ This has to be redefined in concrete subclasses."
+
+ ^ false
+
+ "Modified: / 01-03-2013 / 17:36:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+isWritable
+ "return true, if writing is supported by the recevier.
+ This has to be redefined in concrete subclasses."
+
+ ^ true
+
+ "Modified: / 01-03-2013 / 17:37:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+size
+ "return the number of elements in the streamed collection."
+
+ ^ self shouldImplement
+! !
+
+!LintReport::SourceInfo::LineCountingStream methodsFor:'reading'!
+
+next
+ "return the next element of the stream
+ - we do not know here how to do it, it must be redefined in subclass"
+
+ ^ self shouldNotImplement
+
+ "Modified: / 01-03-2013 / 17:37:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!LintReport::SourceInfo::LineCountingStream methodsFor:'testing'!
+
+atEnd
+ "return true if the end of the stream has been reached;
+ - we do not know here how to do it, it must be redefined in subclass"
+
+ ^ false
+
+ "Modified: / 01-03-2013 / 17:37:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+isEmpty
+ "return true, if the contents of the stream is empty"
+
+ ^ self shouldNotImplement
+
+ "Modified: / 01-03-2013 / 17:37:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!LintReport::SourceInfo::LineCountingStream methodsFor:'writing'!
+
+nextPut:aCharacter
+ "put the argument, anObject onto the receiver
+ - we do not know here how to do it, it must be redefined in subclass"
+
+ position := position + 1.
+ aCharacter == Character cr ifTrue:[
+ lineEnds add: position
+ ].
+
+ "Modified: / 01-03-2013 / 17:39:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
!LintReport class methodsFor:'documentation'!
version