diff --git a/src/EnlumineurFormatter-Tests/EFArrayExpressionTest.class.st b/src/EnlumineurFormatter-Tests/EFArrayExpressionTest.class.st index 3b1ce334359..f4c82c21c94 100644 --- a/src/EnlumineurFormatter-Tests/EFArrayExpressionTest.class.st +++ b/src/EnlumineurFormatter-Tests/EFArrayExpressionTest.class.st @@ -172,7 +172,7 @@ EFArrayExpressionTest >> spaceInsideArrayConfiguration [ manually so that the spacesBefore string is correctly computed." ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testEmptyArray [ | source | configurationSelector := #basicConfiguration. @@ -180,7 +180,7 @@ EFArrayExpressionTest >> testEmptyArray [ self assert: source equals: '{}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testFiveSpaceAroundBrackets [ | source | configurationSelector := #fiveSpacesInsideArrayConfiguration. @@ -188,7 +188,7 @@ EFArrayExpressionTest >> testFiveSpaceAroundBrackets [ self assert: source equals: '{ 1. 2. 3 }' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testFormatElement [ | source | configurationSelector := #basicConfiguration. @@ -199,7 +199,7 @@ EFArrayExpressionTest >> testFormatElement [ (b := 2)}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testNewLineAfterBracesWhenMultiline [ | source | configurationSelector := #multiLineConfiguration. @@ -225,7 +225,7 @@ EFArrayExpressionTest >> testNewLineAfterBracesWhenMultiline [ (self + (1 @ -1))}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testNoExtraSpaceAroundPeriod [ | source | configurationSelector := #basicConfiguration. @@ -233,7 +233,7 @@ EFArrayExpressionTest >> testNoExtraSpaceAroundPeriod [ self assert: source equals: '{1. 2. 3}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testNoSpaceAroundBrackets [ | source | configurationSelector := #basicConfiguration. @@ -241,7 +241,7 @@ EFArrayExpressionTest >> testNoSpaceAroundBrackets [ self assert: source equals: '{1. 2. 3}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testOneSpaceAroundBrackets [ | source | configurationSelector := #oneSpaceInsideArrayConfiguration. @@ -249,7 +249,7 @@ EFArrayExpressionTest >> testOneSpaceAroundBrackets [ self assert: source equals: '{ 1. 2. 3 }' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testPeriodAtEndOfMethod [ | source | configurationSelector := #periodAtEndOfMethod. @@ -257,7 +257,7 @@ EFArrayExpressionTest >> testPeriodAtEndOfMethod [ self assert: source equals: '{1 factorial}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testPeriodAtEndOfMethodWithMultipleElementArrayShouldNotHavePeriodAtEnd [ | source | configurationSelector := #periodAtEndOfMethod. @@ -267,7 +267,7 @@ EFArrayExpressionTest >> testPeriodAtEndOfMethodWithMultipleElementArrayShouldNo (a := 2)}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testPeriodAtEndOfMethodWithMultipleElementArrayShouldNotHavePointAtTheEnd [ | source | configurationSelector := #periodAtEndOfMethod. @@ -278,7 +278,7 @@ EFArrayExpressionTest >> testPeriodAtEndOfMethodWithMultipleElementArrayShouldNo (3 + 2)}' "we should not have a point at the end." ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testSpaceAroundPeriod [ | source | configurationSelector := #basicConfiguration. @@ -286,7 +286,7 @@ EFArrayExpressionTest >> testSpaceAroundPeriod [ self assert: source equals: '{1. 2. 3}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testSpaceBeforePeriod [ | source | configurationSelector := #basicConfiguration. @@ -294,7 +294,7 @@ EFArrayExpressionTest >> testSpaceBeforePeriod [ self assert: source equals: '{1. 2. 3}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testSpaceInside [ | source | configurationSelector := #spaceInsideArrayConfiguration. @@ -302,7 +302,7 @@ EFArrayExpressionTest >> testSpaceInside [ self assert: source equals: '{ 1. 2. 3 }' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testThreeSpacesBeforePeriod [ | source | configurationSelector := #threeSpacesBeforeDotInArrayConfiguration. @@ -310,7 +310,7 @@ EFArrayExpressionTest >> testThreeSpacesBeforePeriod [ self assert: source equals: '{1 . 2 . 3}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testToLongNewLine [ | source | configurationSelector := #maxLineLengthConfiguration. @@ -323,7 +323,7 @@ EFArrayExpressionTest >> testToLongNewLine [ 1}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testToLongNewLine2 [ | source | configurationSelector := #maxLineLengthConfiguration. @@ -335,7 +335,7 @@ EFArrayExpressionTest >> testToLongNewLine2 [ 5. 6. 7. 1}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testToLongNewLine2WithSpaceBefore [ | source | configurationSelector := #maxLineLengthConfigurationWithSpaceBefore. @@ -347,7 +347,7 @@ EFArrayExpressionTest >> testToLongNewLine2WithSpaceBefore [ 5 . 6 . 7 . 1}' ] -{ #category : #test } +{ #category : #tests } EFArrayExpressionTest >> testToLongNewLineWithSpaceBefore [ | source | configurationSelector := #maxLineLengthConfigurationWithSpaceBefore. diff --git a/src/EnlumineurFormatter-Tests/EFBenchTest.class.st b/src/EnlumineurFormatter-Tests/EFBenchTest.class.st new file mode 100644 index 00000000000..47fe7f64be5 --- /dev/null +++ b/src/EnlumineurFormatter-Tests/EFBenchTest.class.st @@ -0,0 +1,84 @@ +Class { + #name : #EFBenchTest, + #superclass : #TestCase, + #category : #'EnlumineurFormatter-Tests' +} + +{ #category : #tests } +EFBenchTest >> basicMethod [ + [[[[[ [ + [ :y :z | + [ :x | 1 to: 10 do: [:i | Transcript show:i ; cr ;cr] ]]] + ]]]]] +] + +{ #category : #tests } +EFBenchTest >> basicMethod2 [ + + + 1 to: 10 do: [:i | Transcript show:i ; cr ;cr] + +] + +{ #category : #tests } +EFBenchTest >> basicMethod3 [ + "a method with many similar expressions." + | x y | + x to: y do: [:i | Transcript show:i ; cr ;cr]. + x to: y do: [:i | Transcript show:i ; cr ;cr]. + x to: y do: [:i | Transcript show:i ; cr: x ; cr: x ]. + +] + +{ #category : #resources } +EFBenchTest >> longNestedMethod [ + + self foo: [ :b1 | + b1 value: [ :b2 | + b2 value: [ :b3 | + b2 value: [ :b4 | + b3 value: [ :b5 | + b4 value: [ :b6 | + b5 value: [ :b7 | + b6 value: [ :b8| + b7 value: [ :b9 | + b8 value: [ :b10 | + b9 value: 2] ] ] ]] ] ] ] ] ] +] + +{ #category : #resources } +EFBenchTest >> longNestedMethodShort [ + | b0 | + self value: [:b1 | b0 value: [:b2 | b1 value: [:b3 | b2 value: [:b4 | b3 value: [:b5 | b4 value: [:b6 | b5 value: [:b7 | b7 value: 2 ] ] ] ] ] ] ] +] + +{ #category : #tests } +EFBenchTest >> testBasicBlueInk [ + + BIConfigurableFormatter format: (EFBenchTest >> #basicMethod) ast +] + +{ #category : #tests } +EFBenchTest >> testBasicEF [ + self skip. + [ EFFormatter format: (EFBenchTest >> #basicMethod) ast ] bench +] + +{ #category : #tests } +EFBenchTest >> testBasicEF2 [ + + EFFormatter format: (EFBenchTest >> #basicMethod2) ast +] + +{ #category : #tests } +EFBenchTest >> testEF [ + " + [ EFFormatter format: (EFBenchTest >> #longNestedMethodShort) ast ] bench '0.159 per second' + + [ RBSimpleFormatter format: (EFBenchTest >> #longNestedMethodShort) ast ] bench + >>>'15597.361 per second' + + [ BIConfigurableFormatter format: (EFBenchTest >> #longNestedMethodShort) ast ] bench '7341.000 per second' + + " +] diff --git a/src/EnlumineurFormatter-Tests/EFBlockExpressionTest.class.st b/src/EnlumineurFormatter-Tests/EFBlockExpressionTest.class.st index 2e9614c42b7..28edccbb139 100644 --- a/src/EnlumineurFormatter-Tests/EFBlockExpressionTest.class.st +++ b/src/EnlumineurFormatter-Tests/EFBlockExpressionTest.class.st @@ -9,16 +9,16 @@ EFBlockExpressionTest >> basicConfiguration [ ^ self contextClass basicNew numberOfSpacesInsideBlock: 1; - periodAtEndOfBlock:false; + periodAtEndOfBlock: false; periodAtEndOfMethod: false; - lineUpBlockBrackets:false; + lineUpBlockBrackets: false; indentStyle: #tabulation; - keepBlockInMessage:true; - retainBlankLinesBetweenStatements:false; + keepBlockInMessage: true; + retainBlankLinesBetweenStatements: false; minimumNewLinesBetweenStatements:1; multiLineMessages: Array new; oneLineMessages: Array new; - numberOfArgumentsForMultiLine:5; + numberOfArgumentsForMultiLine: 5; indentsForKeywords:1; newLineBeforeFirstKeyword:false; formatCommentCloseToStatements:true; @@ -413,12 +413,12 @@ EFBlockExpressionTest >> tabIndentIsnotAffectedConfiguration [ indentExtraSpaces:0 ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testArgumentIsFormated [ self validate: ':i|i' isFormattedAs: ' :i | i ' ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testArgumentsAreFormated [ self @@ -426,7 +426,7 @@ EFBlockExpressionTest >> testArgumentsAreFormated [ isFormattedAs:' :i :j | i '. ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testArgumentsComments [ self @@ -435,7 +435,7 @@ EFBlockExpressionTest >> testArgumentsComments [ ' :i "aComment" :j "anotherComment" | i ' ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testDoNotKeepBlockInMessageConfiguration [ self validate: ':i | i to: 10 do: [:j | Transcript show:i. Transcript show: j]' @@ -447,7 +447,7 @@ i to: 10 do: with: #doNotKeepBlockInMessageConfiguration. ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testDontFormatCommentWithStatement [ self validate: '1 factorial. "aComment" 2 factorial' @@ -458,7 +458,7 @@ EFBlockExpressionTest >> testDontFormatCommentWithStatement [ with: #dontFormatCommentWithStatementConfiguration ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testEndPeriodInside [ self @@ -467,7 +467,7 @@ EFBlockExpressionTest >> testEndPeriodInside [ with: #periodAtEndConfiguration ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testFormatBody [ self validate: ' [1]. [ a:=1] ' @@ -477,7 +477,7 @@ EFBlockExpressionTest >> testFormatBody [ [ a := 1 ] ' ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testFormatCommentWithStatement [ self validate: '1 factorial. "aComment" 2 factorial' @@ -488,7 +488,7 @@ EFBlockExpressionTest >> testFormatCommentWithStatement [ with: #formatCommentWithStatementConfiguration ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testFourSpaceIndent [ self validate: ':i | i to: 10 do: [:j | Transcript show:i; show: j]' @@ -501,7 +501,31 @@ i to: 10 do: [ :j | with: #fourSpaceIndentConfiguration ] -{ #category : #test } +{ #category : #tests } +EFBlockExpressionTest >> testLongMultipleArguments [ + self skip. + self + validate: ' :superlong :longlong :long | Transcript show: longlong ; show: long' + isFormattedAs: +' :superlong :longlong :long | +Transcript + show: longlong; + show: long ' + with: #numberOfSpaceChangedAfterIndentCharacterConfiguration +] + +{ #category : #tests } +EFBlockExpressionTest >> testLongSingleArgument [ + self skip. + self + validate: ' [:superlonglonglong | Transcript show:i; show: j]' + isFormattedAs: +'[ :superlonglonglong | + Transcript show:i; show: j]' + with: #numberOfSpaceChangedAfterIndentCharacterConfiguration +] + +{ #category : #tests } EFBlockExpressionTest >> testMultiline [ self @@ -512,7 +536,7 @@ EFBlockExpressionTest >> testMultiline [ 6 factorial ' ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testNewLineAfterFirstBracketWhenMultilineWithArguments [ self @@ -523,7 +547,7 @@ i + 3. i factorial ' ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testNewLineAfterFirstBracketWhenMultilineWithTemporaries [ self @@ -536,7 +560,7 @@ EFBlockExpressionTest >> testNewLineAfterFirstBracketWhenMultilineWithTemporarie with: #blockWithTemporariesConfiguration ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testNewLineBeforeEndBrackets [ self @@ -548,13 +572,13 @@ EFBlockExpressionTest >> testNewLineBeforeEndBrackets [ ' with: #newLineBeforeEndBracketConfiguration. ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testNoEndPeriodInside [ self validate: '2.' isFormattedAs: ' 2 ' ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testNoExtraSpaceAroundBlock [ | expr source | @@ -564,13 +588,13 @@ EFBlockExpressionTest >> testNoExtraSpaceAroundBlock [ self assert: source equals: self openBracket, ' 2 ', self closeBracket ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testNoExtraSpaceInside [ self validate: ' 2 ' isFormattedAs: ' 2 ' ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testNoNewLineBeforeEndBrackets [ self @@ -581,18 +605,18 @@ EFBlockExpressionTest >> testNoNewLineBeforeEndBrackets [ 4 ' with: #noNewLineBeforeEndBracketConfiguration. ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testNotTooLongBlockBody [ self validate: 'short' isFormattedAs: ' short ' with: #tooLongStatementConfiguration ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testNumberOfSpaces [ self validate: '2' isFormattedAs: ' 2 ' with: #configurationWithThreeSpaces ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testOneSpaceIndent [ self validate: ':i | i to: 10 do: [:j | Transcript show:i; show: j]' @@ -604,13 +628,13 @@ i to: 10 do: [ :j | with: #oneSpaceIndentConfiguration. ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testSpace [ self validate: '2' isFormattedAs: ' 2 ' ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testTabIndent [ self validate: ':i | i to: 10 do: [:j | Transcript show:i; show: j]' isFormattedAs: ' :i | @@ -621,7 +645,7 @@ i to: 10 do: [ :j | with: #tabIndentConfiguration ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testTabIndentIsNotAffectedByNumberOfSpace [ self validate: ':i | i to: 10 do: [:j | Transcript show:i; show: j]' @@ -633,21 +657,21 @@ i to: 10 do: [ :j | with: #tabIndentIsnotAffectedConfiguration ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testTooLongBlockBody [ self validate: 'tooLongStatement' isFormattedAs: ' tooLongStatement ' with: #tooLongStatementConfiguration ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testTooLongBlockBodyWithArgument [ self validate: ':i | tooLongStatement' isFormattedAs: ' :i | tooLongStatement ' with: #tooLongStatementConfiguration ] -{ #category : #test } +{ #category : #tests } EFBlockExpressionTest >> testnumberOfSpaceChangedAfterIndentCharacter [ self validate: ':i | i to: 10 do: [:j | Transcript show:i; show: j]' diff --git a/src/EnlumineurFormatter-Tests/EFContextTest.class.st b/src/EnlumineurFormatter-Tests/EFContextTest.class.st index b7d02df02ff..9dbef71d6fa 100644 --- a/src/EnlumineurFormatter-Tests/EFContextTest.class.st +++ b/src/EnlumineurFormatter-Tests/EFContextTest.class.st @@ -11,3 +11,21 @@ EFContextTest >> testNumberOfSpaces [ context := EFContext new. self assert: context indentExtraSpaces equals: '' ] + +{ #category : #tests } +EFContextTest >> testOneLineMessage [ + + | context | + context := EFContext new. + self assert: (context oneLineMessages includes: #to:). + self assert: (context oneLineMessages includes: #to:do:). + +] + +{ #category : #tests } +EFContextTest >> testOneLineMessageClassSide [ + + self assert: (EFFormatter oneLineMessages includes: #to:). + self assert: (EFFormatter oneLineMessages includes: #to:do:). + +] diff --git a/src/EnlumineurFormatter-Tests/EFInternalTest.class.st b/src/EnlumineurFormatter-Tests/EFInternalTest.class.st new file mode 100644 index 00000000000..1c5118b7ee6 --- /dev/null +++ b/src/EnlumineurFormatter-Tests/EFInternalTest.class.st @@ -0,0 +1,79 @@ +Class { + #name : #EFInternalTest, + #superclass : #TestCase, + #category : #'EnlumineurFormatter-Tests' +} + +{ #category : #tests } +EFInternalTest >> testCurrentLineLength [ + + | formatter | + formatter := EFFormatter new. + formatter writeString: 'abdef'. + self assert: formatter currentLineLength equals: 'abdef' size. + formatter newLines: 2. + self assert: formatter currentLineLength equals: 0. +] + +{ #category : #tests } +EFInternalTest >> testCurrentLineLengthWithStringContainingCR [ + + | formatter | + formatter := EFFormatter new. + formatter writeString: 'abdef', Character cr asString, 'ef'. + self assert: formatter currentLineLength equals: 'ef' size. + +] + +{ #category : #tests } +EFInternalTest >> testLineStartIsCorrectAfterIndent [ + + | formatter | + formatter := EFFormatter new. + formatter numberOfSpacesInIndent: 5. + formatter indent: 4. + self assert: formatter indentString equals: ' '. + formatter newLines: 3. + self assert: formatter lineStart equals: 3 + "indeed the lineStart in the beginning of the last line." + +] + +{ #category : #tests } +EFInternalTest >> testLineStartIsCorrectAfterNewLines [ + + | formatter | + formatter := EFFormatter new. + formatter newLines: 3. + self assert: formatter lineStart equals: 3 + +] + +{ #category : #tests } +EFInternalTest >> testLineStartIsInitializedToZero [ + + | formatter | + formatter := EFFormatter new. + self assert: formatter lineStart equals: 0. + +] + +{ #category : #tests } +EFInternalTest >> testLineStartIsOkAfterWriteString [ + + | formatter | + formatter := EFFormatter new. + self assert: formatter lineStart equals: 0. + formatter writeString: 'abdef'. + self assert: formatter lineStart equals: 0. +] + +{ #category : #tests } +EFInternalTest >> testLineStartStringContainingCR [ + + | formatter | + formatter := EFFormatter new. + formatter writeString: 'abdef', Character cr asString, 'ef'. + self assert: formatter lineStart equals: 'abdef' size + 1. + +] diff --git a/src/EnlumineurFormatter-Tests/EFMethodExpressionTest.class.st b/src/EnlumineurFormatter-Tests/EFMethodExpressionTest.class.st index 5f9aa3bd2cc..159062f1630 100644 --- a/src/EnlumineurFormatter-Tests/EFMethodExpressionTest.class.st +++ b/src/EnlumineurFormatter-Tests/EFMethodExpressionTest.class.st @@ -260,7 +260,7 @@ EFMethodExpressionTest >> spaceIndentConfiguration [ indentExtraSpaces:0 ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testBasic [ | expr source | expr := RBParser parseMethod: 'aMethod "aComment" body'. @@ -273,7 +273,7 @@ EFMethodExpressionTest >> testBasic [ body' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testBasic2 [ | expr source | expr := RBParser parseMethod: 'aMethod "aComment1" "aComment2" body'. @@ -288,7 +288,7 @@ EFMethodExpressionTest >> testBasic2 [ body' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testBasicSpaceIndent [ | expr source | expr := RBParser parseMethod: 'aMethod "aComment" body'. @@ -301,7 +301,7 @@ EFMethodExpressionTest >> testBasicSpaceIndent [ body' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testBigMethod [ | expr source | expr := RBParser parseMethod: @@ -330,7 +330,7 @@ EFMethodExpressionTest >> testBigMethod [ ]' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testCommentBasicFormat [ | expr source | expr := RBParser parseMethod: 'aMethode " aComment "'. @@ -342,7 +342,7 @@ EFMethodExpressionTest >> testCommentBasicFormat [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testCommentNotBasicFormat [ | expr source | expr := RBParser parseMethod: 'aMethode " aComment "'. @@ -354,7 +354,7 @@ EFMethodExpressionTest >> testCommentNotBasicFormat [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testFormatBody [ | expr source | expr := RBParser parseMethod: 'aMethode a:=1'. @@ -365,7 +365,7 @@ EFMethodExpressionTest >> testFormatBody [ a := 1' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testIndentCascade [ | expr source | expr := RBParser parseMethod: 'aMethode Transcript cr; show: ''foo''; cr. Transcript cr;cr'. @@ -382,7 +382,27 @@ EFMethodExpressionTest >> testIndentCascade [ cr' ] -{ #category : #test } +{ #category : #tests } +EFMethodExpressionTest >> testMethodWithMessageArgument [ + | expr source | + expr := RBParser parseMethod: +'aMethod + + 1 to: 10 do: [:i | Transcript show:i ; cr ;cr] + '. + configurationSelector := #bigMethodeConfiguration. + source := self formatter format: expr. + self assert: source equals: +'aMethod + 1 to: 10 do: [:i | + Transcript + show: i; + cr; + cr + ]' +] + +{ #category : #tests } EFMethodExpressionTest >> testNewLinesAfterComment [ | expr source | expr := RBParser parseMethod: 'aMethode "aComment"'. @@ -395,7 +415,7 @@ EFMethodExpressionTest >> testNewLinesAfterComment [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testNewLinesAfterComment2 [ | expr source | expr := RBParser parseMethod: 'aMethode "aComment" "anotherComment"'. @@ -410,7 +430,7 @@ EFMethodExpressionTest >> testNewLinesAfterComment2 [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testNewLinesAfterGluedComment [ | expr source | expr := RBParser parseMethod: 'aMethode"aComment""anotherComment"'. @@ -423,7 +443,7 @@ EFMethodExpressionTest >> testNewLinesAfterGluedComment [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testNewLinesBetweenTopComments [ | expr source | expr := RBParser parseMethod: 'aMethode "aComment" "anotherComment"'. @@ -436,7 +456,7 @@ EFMethodExpressionTest >> testNewLinesBetweenTopComments [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testNoNewLinesAfterComment [ | expr source | expr := RBParser parseMethod: 'aMethode "aComment"'. @@ -449,7 +469,7 @@ EFMethodExpressionTest >> testNoNewLinesAfterComment [ ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testNoNewLinesAfterGluedComment [ | expr source | expr := RBParser parseMethod: 'aMethode "aComment""anotherComment"'. @@ -462,7 +482,7 @@ EFMethodExpressionTest >> testNoNewLinesAfterGluedComment [ ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testNoNewLinesAfterSignature [ | expr source | expr := RBParser parseMethod: 'aMethode'. @@ -473,7 +493,7 @@ EFMethodExpressionTest >> testNoNewLinesAfterSignature [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testNoNewLinesBetweenTopComments [ | expr source | expr := RBParser parseMethod: 'aMethode "aComment" "anotherComment"'. @@ -485,7 +505,7 @@ EFMethodExpressionTest >> testNoNewLinesBetweenTopComments [ ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testOneNewLinesAfterSignature [ | expr source | expr := RBParser parseMethod: 'aMethode'. @@ -496,7 +516,7 @@ EFMethodExpressionTest >> testOneNewLinesAfterSignature [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testPragma [ | expr source | expr := RBParser parseMethod: 'aMethode '. @@ -508,7 +528,7 @@ EFMethodExpressionTest >> testPragma [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testSignatureNotOnMultipleLines [ | expr source | expr := RBParser parseMethod: 'aMethode:arg1 foo:arg2'. @@ -519,7 +539,7 @@ EFMethodExpressionTest >> testSignatureNotOnMultipleLines [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testSignatureOnMultipleLines [ | expr source | expr := RBParser parseMethod: 'aMethode: arg1 foo:arg2'. @@ -531,7 +551,7 @@ EFMethodExpressionTest >> testSignatureOnMultipleLines [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testSignatureWithArgument [ | expr source | expr := RBParser parseMethod: 'aMethode:arg'. @@ -542,7 +562,7 @@ EFMethodExpressionTest >> testSignatureWithArgument [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testSignatureWithoutArgument [ | expr source | expr := RBParser parseMethod: 'aMethode'. @@ -553,7 +573,7 @@ EFMethodExpressionTest >> testSignatureWithoutArgument [ ' ] -{ #category : #test } +{ #category : #tests } EFMethodExpressionTest >> testTwoNewLinesAfterSignature [ | expr source | expr := RBParser parseMethod: 'aMethode'. diff --git a/src/EnlumineurFormatter-Tests/EFTest.class.st b/src/EnlumineurFormatter-Tests/EFTest.class.st index 331ed4db010..20987d97cc6 100644 --- a/src/EnlumineurFormatter-Tests/EFTest.class.st +++ b/src/EnlumineurFormatter-Tests/EFTest.class.st @@ -69,24 +69,3 @@ EFTest >> parseExpression: anExpression [ EFTest >> parserClass [ ^ RBParser ] - -{ #category : #test } -EFTest >> testLookAheadCodeIsResetWhenChangingConfiguration [ - "This is a test to show that the formatter got a problem with a cache. When we execute two formatting passes one after the other and changed the context. Some nodes are not formatted with the new context but with the old. This is due to a cache used by the formatter." - - | prettyPrinterInstance context1 context2 astNode res1 res2 | - context1 := EFContext new. - context2 := EFContext new lineUpBlockBrackets: true. - prettyPrinterInstance := EFFormatter new installNewContext: context1. - astNode := RBParser parseExpression: - '1 to: 4 do: [ :i | - Transcript - show: i; - cr; - cr]'. - - res1 := prettyPrinterInstance format: astNode. - res2 := (prettyPrinterInstance installNewContext: context2) format: astNode. - - self deny: res1 equals: res2 -] diff --git a/src/EnlumineurFormatter-Tests/RBMethodNodeTest.extension.st b/src/EnlumineurFormatter-Tests/RBMethodNodeTest.extension.st new file mode 100644 index 00000000000..553af89a7bd --- /dev/null +++ b/src/EnlumineurFormatter-Tests/RBMethodNodeTest.extension.st @@ -0,0 +1,86 @@ +Extension { #name : #RBMethodNodeTest } + +{ #category : #'*EnlumineurFormatter-Tests' } +RBMethodNodeTest >> testBlockHasArguments [ + + | tree | + tree := self parseMethod: 'foo + [ :arg | + abd + cde + ]'. + + self assert: tree body statements first hasArguments + + +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBMethodNodeTest >> testBlockHasTemporaries [ + + | tree | + tree := self parseMethod: 'foo + [ + | tmp | + abd + cde + ]'. + + self deny: tree hasTemporaries. + self assert: tree body statements first hasTemporaries + + +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBMethodNodeTest >> testBlockHeadIsNotEmpty [ + + | tree | + tree := self parseMethod: 'foo + [ :arg | + abd + cde + ]'. + + self assert: tree body statements first headIsNotEmpty + + +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBMethodNodeTest >> testBlockHeadIsNotEmpty2 [ + + | tree | + tree := self parseMethod: 'foo + [ "blbl" + abd + cde + ]'. + + self assert: tree body statements first headIsNotEmpty + + +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBMethodNodeTest >> testBlockHeadIsNotEmpty3 [ + + | tree | + tree := self parseMethod: 'foo + [ + abd + cde + ]'. + + self deny: tree body statements first headIsNotEmpty + + +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBMethodNodeTest >> testMethodsHasTemporaries [ + + | tree | + tree := self parseMethod: 'foo: abd bar: cde + | tmp | +^ abd + cde'. + + self assert: tree hasTemporaries + + +] diff --git a/src/EnlumineurFormatter-Tests/RBProgramNodeTest.extension.st b/src/EnlumineurFormatter-Tests/RBProgramNodeTest.extension.st new file mode 100644 index 00000000000..97b4fc6a05e --- /dev/null +++ b/src/EnlumineurFormatter-Tests/RBProgramNodeTest.extension.st @@ -0,0 +1,114 @@ +Extension { #name : #RBProgramNodeTest } + +{ #category : #'*EnlumineurFormatter-Tests' } +RBProgramNodeTest >> testAllStatementsAssignment [ + | tree | + tree := self parserClass parseMethod: + 'methodName + + x := 33'. + + self assert: tree allStatements size equals: 1. +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBProgramNodeTest >> testAllStatementsBlockWithReturn [ + | tree | + tree := self parserClass parseMethod: + 'methodName + ^ [ ^ self ] '. + self assert: tree allStatements size equals: 2 + +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBProgramNodeTest >> testAllStatementsBlockWithTemps [ + | tree | + tree := self parserClass parseMethod: + 'methodName + ^ [ | tmp | tmp := 88 ] '. + self assert: tree allStatements size equals: 3. + +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBProgramNodeTest >> testAllStatementsDynamicArray [ + | tree | + tree := self parserClass parseMethod: + 'methodName + + { 1 . self send1 . self send2} '. + + self assert: tree allStatements size equals: 4. +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBProgramNodeTest >> testAllStatementsReturns [ + | tree stats | + tree := self parserClass parseMethod: + 'methodName + ^ self '. + stats := tree allStatements. + self assert: stats size equals: 1 +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBProgramNodeTest >> testAllStatementsReturnsMultiple [ + | tree stats | + tree := self parserClass parseMethod: + 'methodName + 1 ifTrue: [ ^ self ]. + ^ self '. + stats := tree allStatements. + self assert: stats size equals: 3 + +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBProgramNodeTest >> testAllStatementsSimpleBlock [ + | tree stats | + tree := self parserClass parseMethod: + 'methodName + ^ [ 8 + 4 ] '. + stats := tree allStatements. + self assert: stats size equals: 2 +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBProgramNodeTest >> testAllStatementsTemps [ + | tree stats | + tree := self parserClass parseMethod: + 'methodName + | tmp1 tmp2 | + tmp1 + tmp2'. + stats := tree allStatements. + self assert: stats size equals: 3 +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBProgramNodeTest >> testAllStatementsTwoMessages [ + | tree stats | + tree := self parserClass parseMethod: + 'methodName + + 1 send1 send2'. + stats := tree allStatements. + self assert: stats size equals: 1. +] + +{ #category : #'*EnlumineurFormatter-Tests' } +RBProgramNodeTest >> testNumberOfSentMessages [ + | tree messages | + tree := self parserClass parseMethod: + 'methodName + | temp | + 1 send1 send2; send3. + temp := [:each | {4 send4} send5]. + temp send6. + 0 ifTrue: [ 1 ]'. + messages := tree sentMessages. + self assert: messages size equals: 7. + "we count ifTrue:" + 1 to: 6 do: + [ :i | self assert: (messages includes: ('send' , i printString) asSymbol) ] +] diff --git a/src/EnlumineurFormatter/EFContext.class.st b/src/EnlumineurFormatter/EFContext.class.st index a80b4d57f89..fecf29cb6b3 100644 --- a/src/EnlumineurFormatter/EFContext.class.st +++ b/src/EnlumineurFormatter/EFContext.class.st @@ -53,7 +53,23 @@ Class { { #category : #initialization } EFContext >> configureMultiLineMessages [ - multiLineMessages := #(#ifTrue:ifFalse: #ifFalse:ifTrue: #ifTrue: #ifFalse: #on:do: #ensure: #ifCurtailed:) + multiLineMessages := self defaultMultiLineMessages +] + +{ #category : #initialization } +EFContext >> configureOneLineMessages [ + oneLineMessages := self defaultOneLineMessages +] + +{ #category : #initialization } +EFContext >> defaultMultiLineMessages [ + + ^ #(#ifTrue:ifFalse: #ifFalse:ifTrue: #ifTrue: #ifFalse: #on:do: #ensure: #ifCurtailed:) +] + +{ #category : #initialization } +EFContext >> defaultOneLineMessages [ + ^#(#to: #to:do: #to:by: #to:by:do:) ] { #category : #accessing } @@ -112,37 +128,37 @@ EFContext >> indentsForKeywords: anInteger [ { #category : #initialization } EFContext >> initialize [ - super initialize. - self useBasicCommentFormat: true. - self formatCommentCloseToStatements: true. - indentsForKeywords := 1. - keepBlockInMessage := true. - lineUpBlockBrackets := false. - maxLineLength := 70. - methodSignatureOnMultipleLines := false. - minimumNewLinesBetweenStatements := 1. - self configureMultiLineMessages. - newLineAfterCascade := true. - newLineBeforeFirstCascade := true. - newLineBeforeFirstKeyword := true. - numberOfNewLinesAfterMethodComment := 2. - newLinesAfterMethodSignature := 1. - newLinesAfterTemporaries := 1. - numberOfArgumentsForMultiLine := 4. - oneLineMessages := #(#to: #to:do: #to:by: #to:by:do:). - self periodAtEndOfBlock: false. - self periodAtEndOfMethod: false. - self retainBlankLinesBetweenStatements: false. - self retainBlankLinesBeforeComments: true. - self selectorAndArgumentCombinedMaxSize: 40. - self numberOfSpacesInsideBlock: 1. - self numberOfSpacesInsideParentheses: 0. - self numberOfSpacesAfterCaretSymbolInReturn: 1. - self indentStyle: #tabulation. - self numberOfSpacesInIndent: 3. - self numberOfSpacesBeforeDotInDynamicArray: 0. - self indentExtraSpaces: 0. - self numberOfSpacesInsideArray: 1 + super initialize. + self useBasicCommentFormat: true. + self formatCommentCloseToStatements: true. + indentsForKeywords := 1. + keepBlockInMessage := true. + lineUpBlockBrackets := false. + maxLineLength := 70. + methodSignatureOnMultipleLines := false. + minimumNewLinesBetweenStatements := 1. + self configureMultiLineMessages. + newLineAfterCascade := true. + newLineBeforeFirstCascade := true. + newLineBeforeFirstKeyword := true. + numberOfNewLinesAfterMethodComment := 2. + newLinesAfterMethodSignature := 1. + newLinesAfterTemporaries := 1. + numberOfArgumentsForMultiLine := 4. + self configureOneLineMessages. + self periodAtEndOfBlock: false. + self periodAtEndOfMethod: false. + self retainBlankLinesBetweenStatements: false. + self retainBlankLinesBeforeComments: true. + self selectorAndArgumentCombinedMaxSize: 40. + self numberOfSpacesInsideBlock: 1. + self numberOfSpacesInsideParentheses: 0. + self numberOfSpacesAfterCaretSymbolInReturn: 1. + self indentStyle: #tabulation. + self numberOfSpacesInIndent: 3. + self numberOfSpacesBeforeDotInDynamicArray: 0. + self indentExtraSpaces: 0. + self numberOfSpacesInsideArray: 1 ] { #category : #accessing } @@ -415,7 +431,7 @@ EFContext >> selectorAndArgumentCombinedMaxSize: anInteger [ ] { #category : #accessing } -EFContext >> spacesAfterCaretSymbolInReturn [ +EFContext >> spacesAfterCaretSymbolInReturnString [ ^ spacesAfterCaretSymbolInReturn ] @@ -430,12 +446,12 @@ EFContext >> spacesInsideArray [ ] { #category : #accessing } -EFContext >> spacesInsideBlocks [ +EFContext >> spacesInsideBlocksString [ ^ spacesInsideBlocks ] { #category : #accessing } -EFContext >> spacesInsideParentheses [ +EFContext >> spacesInsideParenthesesString [ ^ spacesInsideParentheses ] diff --git a/src/EnlumineurFormatter/EFFormatter.class.st b/src/EnlumineurFormatter/EFFormatter.class.st index 3711aa5d2d7..012cbfbb7c4 100644 --- a/src/EnlumineurFormatter/EFFormatter.class.st +++ b/src/EnlumineurFormatter/EFFormatter.class.st @@ -1,22 +1,31 @@ " Enlumineur is a replacement of BlueInk pretty printer. -It was developed by Hugo Lasnier during 6 months internship within RMOD and supervised by S. Ducasse and G. Polito during 2019.. +It was developed by Hugo Lasnier during 6 months internship within RMOD and supervised by S. Ducasse and G. Polito during 2019. +The code was revisited and cleaned but there are probably more glitches left. -Enlumineur enhancements are: +Enlumineur enhancements compared to BlueInk are: - systematic test coverage with more than 270 tests -- full revisiting of settings with description and example +- full revisiting of settings with description and examples - no way to break the code by entering a non space character to indent code - support for {.....} long list - cleaning coupled settings - support for to:do: block like statement (multiline arguments) -- removal of ""traditional parentheses"" what ever it meant. -- new line and more indentation after the opening bracket -- A dedicated UI was in preparation but should be validated before introduced in Pharo. -- See package Enlumineur-UI (https://github.com/Ducasse/enlumineur) +- removal of ""traditional parentheses"" whatever it meant. +- new line and more indentations after the opening bracket +- A dedicated UI was in preparation but should be redone before introduced in Pharo. + See package Enlumineur-UI (https://github.com/Ducasse/enlumineur) -Now Enlumineur should be improved to be able to reformat the full code of Pharo. +Enlumineur should be improved to be able to reformat the full code of Pharo. The tests are a first step to make sure that we understand what is impacted by a change. + +Implementation remarks + - willBeMultiline: too costly because it formats the code to see if it fits. + We should have other heuristics. + - formatBlock: should be improved and speed up. + formatBlock2: is a first alternative but it broke some tests that should be evaluated. + - Some Node extensions should be pushed to the packages their belong to. + " Class { #name : #EFFormatter, @@ -24,13 +33,11 @@ Class { #instVars : [ 'codeStream', 'indent', - 'lookaheadCode', 'originalSource', 'lineStart', 'context', 'isInCascadeNode', - 'isInMethodNode', - 'temporaryLookAheadCode' + 'lookAheadCode' ], #classVars : [ 'DefaultPrettyPrintContext', @@ -340,7 +347,7 @@ EFFormatter class >> numberOfSpacesInsideParentheses: anInteger [ { #category : #accessing } EFFormatter class >> oneLineMessages [ - ^ DefaultPrettyPrintContext oneLineMessages printString + ^ DefaultPrettyPrintContext oneLineMessages ] { #category : #accessing } @@ -882,18 +889,18 @@ EFFormatter class >> settingsUseBasicCommentFormat: aBuilder [ ] { #category : #accessing } -EFFormatter class >> spacesAfterCaretSymbolInReturn [ - ^ DefaultPrettyPrintContext spacesAfterCaretSymbolInReturn +EFFormatter class >> spacesAfterCaretSymbolInReturnString [ + ^ DefaultPrettyPrintContext spacesAfterCaretSymbolInReturnString ] { #category : #accessing } -EFFormatter class >> spacesInsideBlocks [ - ^ DefaultPrettyPrintContext spacesInsideBlocks +EFFormatter class >> spacesInsideBlocksString [ + ^ DefaultPrettyPrintContext spacesInsideBlocksString ] { #category : #accessing } -EFFormatter class >> spacesInsideParentheses [ - ^ DefaultPrettyPrintContext spacesInsideParentheses +EFFormatter class >> spacesInsideParenthesesString [ + ^ DefaultPrettyPrintContext spacesInsideParenthesesString ] { #category : #accessing } @@ -927,6 +934,14 @@ EFFormatter >> addSpaceIfNeededForLastArgument: aPragmaNode [ ifTrue: [ self space ] ] +{ #category : #private } +EFFormatter >> areArgumentsTooLong: anArray [ + + | size | + size := anArray sum: [ :each | each name size ]. + ^ self isLineTooLongWithNewCharacters: size +] + { #category : #private } EFFormatter >> basicFormatCommentFor: aComment [ codeStream nextPutAll: (originalSource copyFrom: aComment start to: aComment stop). @@ -946,7 +961,7 @@ EFFormatter >> bracketWith: bracketString around: aBlock indentExtraSpaces: anIn bracketString isEmpty ifTrue: [ ^ aBlock value ]. codeStream nextPut: bracketString first. - ^ [self indentExtraSpaces: anInteger around: aBlock] + ^ [ self indentExtraSpaces: anInteger around: aBlock ] ensure: [ codeStream nextPut: bracketString last ] ] @@ -974,16 +989,17 @@ EFFormatter >> currentLineLength [ { #category : #'private-formatting' } EFFormatter >> firstSeparatorShouldNotPassLine: aMessageNode [ -"predicat that tell if the keyWord should be forced te be on the sameLine" + "predicate that tells if the keyword should be forced to be on the same line." ^ aMessageNode isKeyword - and: [ aMessageNode arguments size <= 1 - or: [ self newLineBeforeFirstKeyword not ] ] + and: [ aMessageNode arguments size <= 1 + or: [ self newLineBeforeFirstKeyword not ] ] ] { #category : #'public interface' } EFFormatter >> format: aParseTree [ - codeStream := self initializeCodeStream. + + self initializeCodeStream. originalSource := aParseTree source. self visitNode: aParseTree. ^ codeStream contents @@ -1031,50 +1047,92 @@ EFFormatter >> formatArrayBody: aSequenceNode [ ifTrue: [ self addNewLinesBeforeStatementStartingAt: (statements at: i + 1) start ] ] ] +{ #category : #'private-formatting' } +EFFormatter >> formatBlock2: aBlockNode [ + + "This is a change to speed up and avoid the use of willBeMultiline: + Now it breaks many tests and we should investigate why + For example + + we obtain + hkjhjkh + ifTrue: [ self foo + ] + + and not + hkjhjkh + ifTrue: [ self foo ] + " + + | doesFirstStatementFit | + codeStream nextPutAll: self spacesInsideBlocksString. + self formatBlockArgumentsFor: aBlockNode. + self formatBlockCommentFor: aBlockNode. + + doesFirstStatementFit := self isLineTooLongWithNode: aBlockNode body statements first. + + ((self shouldPassNewLineAfterHeadOfBlock: aBlockNode) + and: [ (aBlockNode body statements size > 1) or: [ doesFirstStatementFit ] ]) + ifTrue: [ self newLine ]. + + self visitSequenceNode: aBlockNode body. + + (self lineUpBlockBrackets and: [ (aBlockNode body statements size > 1) + or: [ doesFirstStatementFit ] ]) + ifTrue: [ self newLine ] + ifFalse: [ codeStream nextPutAll: self spacesInsideBlocksString ] + +] + { #category : #'private-formatting' } EFFormatter >> formatBlock: aBlockNode [ + " see formatBlock2: for a possible alternate and faster definition." + | isMultiline | - isMultiline := self - willBeMultiline: aBlockNode body - saveIn: lookaheadCode. - codeStream nextPutAll: self spacesInsideBlocks. + isMultiline := self willBeMultiline: aBlockNode body. + + codeStream nextPutAll: self spacesInsideBlocksString. + self formatBlockArgumentsFor: aBlockNode. self formatBlockCommentFor: aBlockNode. ((isMultiline or: [ self isLineTooLongWithNode: aBlockNode body ]) - and: [ self shouldPassNewLineAfterHeadOfBlock: aBlockNode ]) - ifTrue: [ self newLine ]. + and: [ self shouldPassNewLineAfterHeadOfBlock: aBlockNode ]) + ifTrue: [ self newLine ]. + self visitSequenceNode: aBlockNode body. - (self lineUpBlockBrackets and: [ isMultiline ]) - ifTrue: [ self newLine ] - ifFalse: [ codeStream nextPutAll: self spacesInsideBlocks ] + + (self lineUpBlockBrackets and: [ isMultiline ]) + ifTrue: [ self newLine ] + ifFalse: [ codeStream nextPutAll: self spacesInsideBlocksString ] + ] { #category : #'private-formatting' } EFFormatter >> formatBlockArgumentsFor: aBlockNode [ - aBlockNode arguments isEmpty + + | onAnotherLine args | + args := aBlockNode arguments. + args isEmpty ifTrue: [ ^ self ]. - aBlockNode arguments + onAnotherLine := self areArgumentsTooLong: args. + args do: [ :each | - (self isLineTooLongWithNode: each )ifTrue: [self newLine ]. + onAnotherLine ifTrue: [self newLine ]. codeStream nextPut: $:. - self visitNode: each. + self visitVariableNode: each. self formatCommentCloseToStatements ifTrue: [ self spaceAndFormatComments: each ]. self space ]. codeStream nextPutAll: '| '. + ] { #category : #'private-formatting' } EFFormatter >> formatBlockCommentFor: aBlockNode [ - originalSource isNil - ifTrue: [ ^ self ]. - aBlockNode comments - do: [ :each | - - self basicFormatCommentFor: each. - (self isNonEmptySingleLineBlock: aBlockNode) - ifTrue: [ self space ]] + originalSource ifNil: [ ^ self ]. + aBlockNode comments do: [:each | self basicFormatCommentFor: each. + (self isNonEmptySingleLineBlock: aBlockNode) ifTrue: [ self space ] ] ] { #category : #accessing } @@ -1089,29 +1147,16 @@ EFFormatter >> formatCommentCloseToStatements: aBoolean [ { #category : #'private-formatting' } EFFormatter >> formatCommentsFor: aNode [ - originalSource isNil - ifTrue: [ ^ self ]. - aNode comments - do: - [ :each | - self basicFormatCommentFor: each. - ] + originalSource ifNil: [ ^ self ]. + aNode comments do: [:each | self basicFormatCommentFor: each ] ] { #category : #private } -EFFormatter >> formatMessageNodeInAMessageStreamFor: aMessageNode [ - | messageStream | - messageStream := WriteStream on: (String new: 100). - self - with: aMessageNode selectorParts - and: aMessageNode arguments - do: [ :selector :arg | - messageStream - nextPutAll: selector; - space; - nextPutAll: (self formattedSourceFor: arg withDictionary: temporaryLookAheadCode) ] - separatedBy: [ messageStream space ]. - ^ messageStream +EFFormatter >> formatMessageNode: aMessageNode [ + ^String streamContents: [:messageStream | self with: aMessageNode selectorParts and: aMessageNode arguments do: [:selector :arg | messageStream + nextPutAll: selector; + space; + nextPutAll: (self formattedSourceFor: arg) ] separatedBy: [ messageStream space ] ] ] { #category : #'private-formatting' } @@ -1127,17 +1172,13 @@ EFFormatter >> formatMethodBodyFor: aMethodNode [ { #category : #'private-formatting' } EFFormatter >> formatMethodCommentFor: aMethodNode [ - originalSource isNil - ifTrue: [ ^ self ]. - aMethodNode comments - do: - [ :each | - - self useBasicCommentFormat - ifTrue: [ self basicFormatCommentFor: each ] - ifFalse: [ - self resizeCommentFor: each startingAt: 0]. - self newLines: self numberOfNewLinesAfterMethodComment ] + originalSource ifNil: [ ^ self ]. + aMethodNode comments + do: [:each | + self useBasicCommentFormat + ifTrue: [ self basicFormatCommentFor: each ] + ifFalse: [ self resizeCommentFor: each startingAt: 0 ]. + self newLines: self numberOfNewLinesAfterMethodComment ] ] { #category : #'private-formatting' } @@ -1152,20 +1193,21 @@ EFFormatter >> formatMethodPatternFor: aMethodNode [ { #category : #'private-formatting' } EFFormatter >> formatPragmasFor: aMethodNode [ - aMethodNode pragmas do: [ :each | self visitNode: each; newLine ] + + aMethodNode pragmas do: [ :each | self visitPragmaNode: each; newLine ] ] { #category : #'private-formatting' } EFFormatter >> formatSelectorAndArguments: aMessageNode [ "We are formatting a message and here we are about to format the message selector and its arguments." - | isMultilineMessage hasMutlineArguments multilineArgumentBeforeAnotherArgument | + | isMultilineMessage hasMultiLineArguments multilineArgumentBeforeAnotherArgument | multilineArgumentBeforeAnotherArgument := self messageHasMultilineArgumentBeforeAnotherArgument: aMessageNode. isMultilineMessage := (self isMultiLineMessage: aMessageNode) or:[multilineArgumentBeforeAnotherArgument]. - hasMutlineArguments := self hasAMultiLineMessageArgument: aMessageNode arguments. + hasMultiLineArguments := self hasAMultiLineMessageArgument: aMessageNode arguments. self indent: - (((isMultilineMessage or:[hasMutlineArguments]) and:[aMessageNode isKeyword]) + (((isMultilineMessage or:[hasMultiLineArguments]) and:[aMessageNode isKeyword]) ifTrue: [ self indentsForKeywords ] ifFalse: [ 0 ]) around: [ self @@ -1184,31 +1226,16 @@ EFFormatter >> formatSelectorAndArguments: aMessageNode [ { #category : #'private-formatting' } EFFormatter >> formatSelectorAndArguments: aMessageNode firstSeparator: firstBlock restSeparator: restBlock [ - | separatorBlock i| - i := 0. - separatorBlock := firstBlock. - aMessageNode isUnary - ifTrue: [ - self indentAround: [self handleLineForSelector: aMessageNode selector withSeparatorBlock: - separatorBlock. - codeStream nextPutAll: aMessageNode selector ]] - ifFalse: [ - aMessageNode selectorParts with: aMessageNode arguments do: [ :selector :argument | - i := i + 1. - self - handleLineForSelector: selector - withSeparatorBlock: separatorBlock. - separatorBlock := restBlock. - self - indent: - ((((self willBeMultiline: argument saveIn: temporaryLookAheadCode) and: [ i < aMessageNode selectorParts size or: [ self newLineBefore ] ]) - or:[ self isInCascadeNode ]) - ifTrue: [ 1 ] ifFalse: [ 0 ]) - around: [ codeStream nextPutAll: selector. - self handleLineForArgument: argument ]. - ((self willBeMultiline: argument saveIn: lookaheadCode) and:[i < aMessageNode selectorParts size]) ifTrue: [ separatorBlock := self newLine ] - ] - ] + | separatorBlock i | + i := 0. + separatorBlock := firstBlock. + aMessageNode isUnary ifTrue: [ self indentAround: [ self handleLineForSelector: aMessageNode selector withSeparatorBlock: separatorBlock. + codeStream nextPutAll: aMessageNode selector ] ] ifFalse: [ aMessageNode selectorParts with: aMessageNode arguments do: [:selector :argument | i := i + 1. + self handleLineForSelector: selector withSeparatorBlock: separatorBlock. + separatorBlock := restBlock. + self indent: ((((self willBeMultiline: argument) and: [ i < aMessageNode selectorParts size or: [ self newLineBefore ] ]) or: [ self isInCascadeNode ]) ifTrue: [ 1 ] ifFalse: [ 0 ]) around: [ codeStream nextPutAll: selector. + self handleLineForArgument: argument ]. + ((self willBeMultiline: argument) and: [ i < aMessageNode selectorParts size ]) ifTrue: [ separatorBlock := self newLine ] ] ] ] { #category : #'private-formatting' } @@ -1233,7 +1260,7 @@ EFFormatter >> formatSequenceNodeStatementsFor: aSequenceNode [ ifTrue: [ self addNewLinesBeforeStatementStartingAt: (statements at: i + 1) start ] ] ] -{ #category : #visiting } +{ #category : #'private-formatting' } EFFormatter >> formatSingleArrayElement: aRBNode [ "Imagine that you have {1 factorial}, you do not want an ending period. This method is only invoked on the last array element." @@ -1242,8 +1269,7 @@ EFFormatter >> formatSingleArrayElement: aRBNode [ { #category : #'private-formatting' } EFFormatter >> formatStatementCommentsFor: aStatementNode [ - originalSource isNil - ifTrue: [ ^ self ]. + originalSource ifNil: [ ^ self ]. self formatCommentCloseToStatements ifFalse: [ ^ self ]. aStatementNode statementComments @@ -1256,14 +1282,13 @@ EFFormatter >> formatStatementCommentsFor: aStatementNode [ ifFalse: [ self space ]. self useBasicCommentFormat ifTrue: [ self basicFormatCommentFor: each ] - ifFalse: [ - self resizeCommentFor: each startingAt: self currentLineLength ]] + ifFalse: [ self resizeCommentFor: each startingAt: self currentLineLength ]] ] { #category : #private } EFFormatter >> formatTemporariesFor: aSequenceNode [ - aSequenceNode temporaries isEmpty - ifTrue: [ ^ self ]. + aSequenceNode hasTemporaries + ifFalse: [ ^ self ]. self bracketWith: '|' around: @@ -1280,29 +1305,22 @@ EFFormatter >> formatTemporariesFor: aSequenceNode [ ] { #category : #private } -EFFormatter >> formattedSourceFor: aNode withDictionary: aDictionary [ - ^ aDictionary at: aNode ifAbsentPut: [ +EFFormatter >> formattedSourceFor: aNode [ + + ^ lookAheadCode at: aNode ifAbsentPut: [ self class new - indent: self indent; - installNewContext: context; - format: aNode ] + indent: self indent; + installNewContext: context; + lookAheadCode: lookAheadCode; + format: aNode ] ] { #category : #private } EFFormatter >> handleLineForArgument: anArgument [ - | isLineTooLong | - isLineTooLong := self isLineTooLongWithNode: anArgument. - anArgument isBlock - ifTrue: [((self willBeMultiline: anArgument saveIn: temporaryLookAheadCode) - and: [ self keepBlockInMessage not ]) - ifTrue: [ self newLine ] - ifFalse: [ self space ] ] - ifFalse: [ (self isInCascadeNode and: [ isLineTooLong ]) - ifTrue: [ self newLine ] - ifFalse: [ isLineTooLong - ifTrue: [ self newLine ] - ifFalse: [ self space ] ] ]. - self visitNode: anArgument + | isLineTooLong | + isLineTooLong := self isLineTooLongWithNode: anArgument. + anArgument isBlock ifTrue: [ ((self willBeMultiline: anArgument) and: [ self keepBlockInMessage not ]) ifTrue: [ self newLine ] ifFalse: [ self space ] ] ifFalse: [ (self isInCascadeNode and: [ isLineTooLong ]) ifTrue: [ self newLine ] ifFalse: [ isLineTooLong ifTrue: [ self newLine ] ifFalse: [ self space ] ] ]. + self visitNode: anArgument ] { #category : #private } @@ -1314,20 +1332,13 @@ EFFormatter >> handleLineForSelector: selector withSeparatorBlock: aBlock [ { #category : #private } EFFormatter >> hasAMultiLineMessageArgument: anArgumentsCollection [ - ^ anArgumentsCollection - anySatisfy: [ :each | - self isInCascadeNode - ifTrue: [ self indent: 0 around: [ self willBeMultiline: each saveIn: temporaryLookAheadCode ] ] - ifFalse: [ - self - indent: self indentsForKeywords + 1 - around: [ self willBeMultiline: each saveIn: temporaryLookAheadCode ] ] ] + ^anArgumentsCollection anySatisfy: [:each | self isInCascadeNode ifTrue: [ self indent: 0 around: [ self willBeMultiline: each ] ] ifFalse: [ self indent: self indentsForKeywords + 1 around: [ self willBeMultiline: each ] ] ] ] { #category : #private } EFFormatter >> headOfBlockNotEmpty: aBlockNode [ - ^ aBlockNode arguments isNotEmpty or: [aBlockNode comments isNotEmpty] + ^ aBlockNode arguments isNotEmpty or: [aBlockNode comments isNotEmpty] ] { #category : #accessing } @@ -1410,27 +1421,30 @@ EFFormatter >> initialize [ lineStart := 0. self indent: 0. self isInCascadeNode: false. - lookaheadCode := self initializeLookAheadCode. - temporaryLookAheadCode := self initializeLookAheadCode. - codeStream := self initializeCodeStream. - context := DefaultPrettyPrintContext + self initializeCodeStream. + context := DefaultPrettyPrintContext. + self initializeTemporaryLookAheadCode ] { #category : #initialization } EFFormatter >> initializeCodeStream [ - ^ WriteStream on: (String new: 256) + + codeStream := WriteStream on: (String new: 256) ] { #category : #initialization } -EFFormatter >> initializeLookAheadCode [ - ^ IdentityDictionary new +EFFormatter >> initializeTemporaryLookAheadCode [ + + lookAheadCode := IdentityDictionary new + "this is strange because using an identity should normally produce more entries in the cache + since each node is a different object. + However on simple methods it is still faster than using a Dictionary." ] { #category : #'public interface' } EFFormatter >> installNewContext: aContext [ - - context := aContext. - lookaheadCode := self initializeLookAheadCode + + context := aContext ] { #category : #accessing } @@ -1443,15 +1457,23 @@ EFFormatter >> isInCascadeNode: aBoolean [ isInCascadeNode := aBoolean ] +{ #category : #private } +EFFormatter >> isLineTooLongWithNewCharacters: aNumber [ + "Is the length of the current line + the length of the first fragment of code until a new line is >= the max line length" + + ^ self currentLineLength + aNumber >= self maxLineLength +] + { #category : #private } EFFormatter >> isLineTooLongWithNode: aNode [ - ^ self isLineTooLongWithString: (self formattedSourceFor: aNode withDictionary: temporaryLookAheadCode ). + ^self isLineTooLongWithString: (self formattedSourceFor: aNode) ] { #category : #private } EFFormatter >> isLineTooLongWithString: aString [ - ^ self currentLineLength - + (aString indexOf: Character cr ifAbsent: [ aString size ]) + "Is the length of the current line + the length of the first fragment of code until a new line is >= the max line length" + + ^ self currentLineLength + (aString indexOf: Character cr ifAbsent: [ aString size ]) >= self maxLineLength ] @@ -1465,12 +1487,12 @@ EFFormatter >> isMultiLineMessage: aMessageNode [ ifTrue: [ ^ true ]. aMessageNode isUnary ifTrue: [ ^ self isLineTooLongWithString: aMessageNode selector ]. - ^ self isLineTooLongWithString: (self formatMessageNodeInAMessageStreamFor: aMessageNode) contents + ^ self isLineTooLongWithString: (self formatMessageNode: aMessageNode) contents ] { #category : #private } EFFormatter >> isNonEmptySingleLineBlock: aBlockNode [ - ^ ((self willBeMultiline: aBlockNode body saveIn: temporaryLookAheadCode ) or: [ aBlockNode body statements isEmpty ]) not + ^((self willBeMultiline: aBlockNode body) or: [ aBlockNode body statements isEmpty ]) not ] { #category : #accessing } @@ -1517,6 +1539,16 @@ EFFormatter >> lineUpBlockBrackets: aBoolean [ context lineUpBlockBrackets: aBoolean ] +{ #category : #accessors } +EFFormatter >> lookAheadCode [ + ^ lookAheadCode +] + +{ #category : #accessors } +EFFormatter >> lookAheadCode: anObject [ + lookAheadCode := anObject +] + { #category : #accessing } EFFormatter >> maxLineLength [ ^ context maxLineLength @@ -1528,12 +1560,9 @@ EFFormatter >> maxLineLength: anInteger [ ] { #category : #private } -EFFormatter >> messageHasMultilineArgumentBeforeAnotherArgument: aMessageNode [ - - aMessageNode arguments doWithIndex: [ :each :i | - (self willBeMultiline: each saveIn: temporaryLookAheadCode) - ifTrue: [ ^ i < aMessageNode arguments size ]]. - ^ false +EFFormatter >> messageHasMultilineArgumentBeforeAnotherArgument: aMessageNode [ + aMessageNode arguments doWithIndex: [:each :i | (self willBeMultiline: each) ifTrue: [ ^i < aMessageNode arguments size ] ]. + ^false ] { #category : #accessing } @@ -1668,15 +1697,13 @@ EFFormatter >> newLineBeforeFirstKeyword: aBoolean [ { #category : #private } EFFormatter >> newLines: anInteger [ + "Add a number of new lines and in addition store the position of the latest new lines in the stream so that latter we can compute the current line length." + anInteger + self indentString size = 0 - ifTrue: - [ codeStream space ]. - anInteger - timesRepeat: - [ codeStream cr ]. + ifTrue: [ codeStream space ]. + anInteger timesRepeat: [ codeStream cr ]. lineStart := codeStream position. - self - indentTimesRepeat: self indent + self indentTimesRepeat: self indent ] { #category : #private } @@ -1812,17 +1839,6 @@ EFFormatter >> periodAtEndOfMethod: aBoolean [ context periodAtEndOfMethod: aBoolean ] -{ #category : #accessing } -EFFormatter >> periodsAsTerminators [ - ^ context periodsAtEndOfBlock and: [ context periodsAtEndOfMethod ] -] - -{ #category : #accessing } -EFFormatter >> periodsAsTerminators: aBoolean [ - context periodAtEndOfBlock: aBoolean. - context periodAtEndOfMethod: aBoolean -] - { #category : #accessing } EFFormatter >> periodsAtEndOfBlock [ ^ context periodsAtEndOfBlock @@ -1946,8 +1962,7 @@ EFFormatter >> selectorAndArgumentCombinedMaxSize: anInteger [ { #category : #'private-formatting' } EFFormatter >> shouldPassNewLineAfterHeadOfBlock: aBlockNode [ - ^ (self headOfBlockNotEmpty: aBlockNode) - or: [ self keepBlockInMessage ] + ^ aBlockNode headIsNotEmpty or: [ self keepBlockInMessage ] ] { #category : #private } @@ -1962,8 +1977,8 @@ EFFormatter >> spaceAndFormatComments: aNode [ ] { #category : #accessing } -EFFormatter >> spacesAfterCaretSymbolInReturn [ - ^ context spacesAfterCaretSymbolInReturn +EFFormatter >> spacesAfterCaretSymbolInReturnString [ + ^ context spacesAfterCaretSymbolInReturnString ] { #category : #accessing } @@ -1977,13 +1992,14 @@ EFFormatter >> spacesInsideArray [ ] { #category : #accessing } -EFFormatter >> spacesInsideBlocks [ - ^ context spacesInsideBlocks +EFFormatter >> spacesInsideBlocksString [ + ^ context spacesInsideBlocksString ] { #category : #accessing } -EFFormatter >> spacesInsideParentheses [ - ^ context spacesInsideParentheses +EFFormatter >> spacesInsideParenthesesString [ + "Set via numberOfSpacesInsideParentheses: " + ^ context spacesInsideParenthesesString ] { #category : #accessing } @@ -2003,10 +2019,12 @@ EFFormatter >> visitArrayNode: anArrayNode [ { #category : #visiting } EFFormatter >> visitAssignmentNode: anAssignmentNode [ - self visitNode: anAssignmentNode variable. - codeStream space; nextPutAll: anAssignmentNode assignmentOperator; space. + | var | + var := anAssignmentNode variable. + self visitVariableNode: var. + codeStream nextPutAll: ' := '. self - indentExtraSpaces: anAssignmentNode variable name size + ' := ' size + indentExtraSpaces: var name size + ' := ' size around: [ self visitNode: anAssignmentNode value ] ] @@ -2014,7 +2032,7 @@ EFFormatter >> visitAssignmentNode: anAssignmentNode [ EFFormatter >> visitBlockNode: aBlockNode [ self bracketWith: '[]' - around: [ self formatBlock: aBlockNode ]. + around: [ self formatBlock: aBlockNode ] ] @@ -2077,6 +2095,7 @@ EFFormatter >> visitLiteralNode: aLiteralNode [ { #category : #visiting } EFFormatter >> visitLiteralVariableNode: aLiteralVariableNode [ | binding | + self halt. "looks like it is not used. Ask around RBLiteralVariableNode" binding := aLiteralVariableNode binding. self writeString: binding key storeString, ' -> '. aLiteralVariableNode binding value isLiteral @@ -2099,8 +2118,6 @@ EFFormatter >> visitMethodNode: aMethodNode [ { #category : #visiting } EFFormatter >> visitNode: aNode [ | needsParenthesis | - (lookaheadCode includesKey: aNode) - ifTrue: [ ^ self writeString: (lookaheadCode at: aNode) ]. needsParenthesis := self needsParenthesisFor: aNode. self bracketWith: @@ -2109,12 +2126,12 @@ EFFormatter >> visitNode: aNode [ ifFalse: [ '' ]) around: [ needsParenthesis - ifTrue: [ codeStream nextPutAll: self spacesInsideParentheses ]. + ifTrue: [ codeStream nextPutAll: self spacesInsideParenthesesString ]. super visitNode: aNode. (self formatCommentCloseToStatements or: [ aNode isMethod or: [ aNode isSequence or: [ aNode isBlock ] ] ]) ifFalse: [ self spaceAndFormatComments: aNode. ]. needsParenthesis - ifTrue: [ codeStream nextPutAll: self spacesInsideParentheses ] ] + ifTrue: [ codeStream nextPutAll: self spacesInsideParenthesesString ] ] indentExtraSpaces: (needsParenthesis ifTrue: [ 1 + self numberOfSpacesInsideParentheses ] ifFalse:[ 0 ]) ] @@ -2123,7 +2140,7 @@ EFFormatter >> visitParseErrorNode: aNode [ self writeString: aNode value ] -{ #category : #visiting } +{ #category : #'visiting patterns' } EFFormatter >> visitPatternBlockNode: aRBPatternBlockNode [ codeStream nextPut: $`. self @@ -2131,7 +2148,7 @@ EFFormatter >> visitPatternBlockNode: aRBPatternBlockNode [ around: [self formatBlock: aRBPatternBlockNode] ] -{ #category : #visiting } +{ #category : #'visiting patterns' } EFFormatter >> visitPatternWrapperBlockNode: aRBPatternWrapperBlockNode [ self visitNode: aRBPatternWrapperBlockNode wrappedNode. codeStream nextPut: $`. @@ -2157,7 +2174,7 @@ EFFormatter >> visitPragmaNode: aPragmaNode [ EFFormatter >> visitReturnNode: aReturnNode [ codeStream nextPut: $^; - nextPutAll: self spacesAfterCaretSymbolInReturn. + nextPutAll: self spacesAfterCaretSymbolInReturnString. self indentExtraSpaces: 1 + self numberOfSpacesAfterCaretSymbolInReturn around: [ self visitNode: aReturnNode value ] @@ -2178,13 +2195,8 @@ EFFormatter >> visitVariableNode: aVariableNode [ ] { #category : #private } -EFFormatter >> willBeMultiline: aNode [ - ^(self formattedSourceFor: aNode withDictionary: lookaheadCode) includes: Character cr -] - -{ #category : #private } -EFFormatter >> willBeMultiline: aNode saveIn: aDictionary [ - ^(self formattedSourceFor: aNode withDictionary: aDictionary) includes: Character cr +EFFormatter >> willBeMultiline: aNode [ + ^(self formattedSourceFor: aNode) includes: Character cr ] { #category : #utilities } @@ -2199,9 +2211,10 @@ EFFormatter >> with: firstCollection and: secondCollection do: aBlock separatedB { #category : #private } EFFormatter >> writeString: aString [ + "Write the argument in the code stream and in addition maintent the line start position so that we can later compute the current line length." | index | index := aString lastIndexOf: Character cr ifAbsent: [ 0 ]. - codeStream nextPutAll: aString . + codeStream nextPutAll: aString. index > 0 ifTrue: [ lineStart := codeStream position - (aString size - index) ] ] diff --git a/src/EnlumineurFormatter/RBArrayNode.extension.st b/src/EnlumineurFormatter/RBArrayNode.extension.st new file mode 100644 index 00000000000..4cf64ace1a4 --- /dev/null +++ b/src/EnlumineurFormatter/RBArrayNode.extension.st @@ -0,0 +1,9 @@ +Extension { #name : #RBArrayNode } + +{ #category : #'*EnlumineurFormatter' } +RBArrayNode >> allStatements [ + ^ statements asOrderedCollection copy + addAll: super allStatements; + yourself + +] diff --git a/src/EnlumineurFormatter/RBBlockNode.extension.st b/src/EnlumineurFormatter/RBBlockNode.extension.st new file mode 100644 index 00000000000..ead26ae896c --- /dev/null +++ b/src/EnlumineurFormatter/RBBlockNode.extension.st @@ -0,0 +1,29 @@ +Extension { #name : #RBBlockNode } + +{ #category : #'*EnlumineurFormatter' } +RBBlockNode >> allStatements [ + "including temp variable definition." + ^ self temporaries asOrderedCollection copy + addAll: super allStatements; + yourself + +] + +{ #category : #'*EnlumineurFormatter' } +RBBlockNode >> hasArguments [ + + ^ arguments isNotEmpty +] + +{ #category : #'*EnlumineurFormatter' } +RBBlockNode >> hasTemporaries [ + + ^ self temporaries isNotEmpty +] + +{ #category : #'*EnlumineurFormatter' } +RBBlockNode >> headIsNotEmpty [ + "Return true whether the receiver has some arguments or comments" + + ^ arguments isNotEmpty or: [ self comments isNotEmpty ] +] diff --git a/src/EnlumineurFormatter/RBMethodNode.extension.st b/src/EnlumineurFormatter/RBMethodNode.extension.st new file mode 100644 index 00000000000..543a87d5d25 --- /dev/null +++ b/src/EnlumineurFormatter/RBMethodNode.extension.st @@ -0,0 +1,15 @@ +Extension { #name : #RBMethodNode } + +{ #category : #'*EnlumineurFormatter' } +RBMethodNode >> allStatements [ + "return the statements including variable definition." + ^ self temporaries asOrderedCollection copy + addAll: super allStatements; + yourself + +] + +{ #category : #'*EnlumineurFormatter' } +RBMethodNode >> hasTemporaries [ + ^ self temporaries isNotEmpty +] diff --git a/src/EnlumineurFormatter/RBProgramNode.extension.st b/src/EnlumineurFormatter/RBProgramNode.extension.st new file mode 100644 index 00000000000..8c8447352d3 --- /dev/null +++ b/src/EnlumineurFormatter/RBProgramNode.extension.st @@ -0,0 +1,14 @@ +Extension { #name : #RBProgramNode } + +{ #category : #'*EnlumineurFormatter' } +RBProgramNode >> allStatements [ + | children | + children := self children. + children isEmpty ifTrue: [^#()]. + ^children inject: OrderedCollection new + into: + [:vars :each | + vars + addAll: each allStatements; + yourself] +] diff --git a/src/EnlumineurFormatter/RBSequenceNode.extension.st b/src/EnlumineurFormatter/RBSequenceNode.extension.st new file mode 100644 index 00000000000..62dc201f104 --- /dev/null +++ b/src/EnlumineurFormatter/RBSequenceNode.extension.st @@ -0,0 +1,15 @@ +Extension { #name : #RBSequenceNode } + +{ #category : #'*EnlumineurFormatter' } +RBSequenceNode >> allStatements [ + ^ statements asOrderedCollection copy + addAll: super allStatements; + yourself + +] + +{ #category : #'*EnlumineurFormatter' } +RBSequenceNode >> hasTemporaries [ + + ^ temporaries isNotEmpty +]