diff --git a/packages/DomainCode-Core/DCQuery.class.st b/packages/DomainCode-Core/DCQuery.class.st index 4d64b87..d1490bf 100644 --- a/packages/DomainCode-Core/DCQuery.class.st +++ b/packages/DomainCode-Core/DCQuery.class.st @@ -60,6 +60,12 @@ DCQuery class >> removeProperty: anObject from: aDomainObject [ ifPresent: [:properties | properties remove: aDomainObject] ] +{ #category : #'as yet unclassified' } +DCQuery class >> script: aCollection allDeep: anotherCollection [ + + ^ Array streamContents: [:s | anotherCollection allChildrenDo: [:obj | (self script: aCollection with: obj) ifNotNil: [:res | s nextPut: res]]] +] + { #category : #'as yet unclassified' } DCQuery class >> script: aCollection first: anotherCollection [ @@ -67,6 +73,13 @@ DCQuery class >> script: aCollection first: anotherCollection [ ^ nil ] +{ #category : #'as yet unclassified' } +DCQuery class >> script: aCollection firstDeep: anotherCollection [ + + anotherCollection allChildrenDo: [:obj | (self script: aCollection with: obj) ifNotNil: [:res | ^ res]]. + ^ nil +] + { #category : #'as yet unclassified' } DCQuery class >> script: aCollection with: anObject [ diff --git a/packages/DomainCode-Core/Morph.extension.st b/packages/DomainCode-Core/Morph.extension.st index 6d72c41..eeb4227 100644 --- a/packages/DomainCode-Core/Morph.extension.st +++ b/packages/DomainCode-Core/Morph.extension.st @@ -14,7 +14,7 @@ Morph >> allChildrenBreadthFirstDo: aBlock [ { #category : #'*DomainCode-Core' } Morph >> allChildrenDo: aBlock [ - self children do: [:c | c allChildrenDo: aBlock]. + self childrenDo: [:c | c allChildrenDo: aBlock]. aBlock value: self ] @@ -37,12 +37,33 @@ Morph >> allDomainBlocksWithDepthDo: aBlock leafDo: anotherBlock depth: aNumber anotherBlock value: self value: aNumber ] +{ #category : #'*DomainCode-Core' } +Morph >> childCount [ + + | i | + i := 0. + self childrenDo: [:c | i := i + 1]. + ^ i +] + { #category : #'*DomainCode-Core' } Morph >> children [ ^ submorphs ] +{ #category : #'*DomainCode-Core' } +Morph >> childrenDo: aBlock [ + + submorphs do: aBlock +] + +{ #category : #'*DomainCode-Core' } +Morph >> childrenSelect: aBlock [ + + ^ Array streamContents: [:s | self childrenDo: [:c | (aBlock value: c) ifTrue: [s nextPut: c]]] +] + { #category : #'*DomainCode-Core' } Morph >> firstDeepChildNode [ @@ -55,7 +76,8 @@ Morph >> firstDeepChildNode [ { #category : #'*DomainCode-Core' } Morph >> hasChildren [ - ^ self children notEmpty + self childrenDo: [:c | ^ true]. + ^ false ] { #category : #'*DomainCode-Core' } diff --git a/packages/DomainCode-Diff/DCChawatheScriptGenerator.class.st b/packages/DomainCode-Diff/DCChawatheScriptGenerator.class.st index 8b838af..16b6f54 100644 --- a/packages/DomainCode-Diff/DCChawatheScriptGenerator.class.st +++ b/packages/DomainCode-Diff/DCChawatheScriptGenerator.class.st @@ -8,11 +8,11 @@ Class { DCChawatheScriptGenerator >> alignChildrenSrc: w dest: x srcInOrder: srcInOrder destInOrder: destInOrder in: aMapping [ | s1 s2 lcs | - w children do: [:c | srcInOrder remove: c ifAbsent: []]. - x children do: [:c | destInOrder remove: c ifAbsent: []]. + w childrenDo: [:c | srcInOrder remove: c ifAbsent: []]. + x childrenDo: [:c | destInOrder remove: c ifAbsent: []]. - s1 := w children select: [:c | (aMapping isSrcMapped: c) and: [x children includes: (aMapping destForSrc: c)]]. - s2 := x children select: [:c | (aMapping isDestMapped: c) and: [w children includes: (aMapping srcForDest: c)]]. + s1 := w childrenSelect: [:c | (aMapping isSrcMapped: c) and: [x children includes: (aMapping destForSrc: c)]]. + s2 := x childrenSelect: [:c | (aMapping isDestMapped: c) and: [w children includes: (aMapping srcForDest: c)]]. lcs := self lcsWith: s1 and: s2 in: aMapping. lcs do: [:mapping | diff --git a/packages/DomainCode-Diff/DCMappingComparator.class.st b/packages/DomainCode-Diff/DCMappingComparator.class.st index eba206e..d9d6f2e 100644 --- a/packages/DomainCode-Diff/DCMappingComparator.class.st +++ b/packages/DomainCode-Diff/DCMappingComparator.class.st @@ -9,7 +9,8 @@ Class { 'destAncestors', 'rootSrc', 'rootDest', - 'absolutePositions' + 'absolutePositions', + 'indicesInParents' ], #category : #'DomainCode-Diff' } @@ -102,17 +103,17 @@ DCMappingComparator >> longestCommonSubsequenceWith: aCollection and: anotherCol 1 to: aCollection size do: [:i | 1 to: anotherCollection size do: [:j | (aCollection at: i) type = (anotherCollection at: j) type - ifTrue: [lengths at: i + 1 at: j + 1 put: (lengths at: i at: j)] - ifFalse: [lengths at: i + 1 at: j + 1 put: ((lengths at: i + 1 at: j) max: (lengths at: i at: j + 1))]]]. + ifTrue: [lengths atFast: i + 1 at: j + 1 put: (lengths atFast: i at: j)] + ifFalse: [lengths atFast: i + 1 at: j + 1 put: ((lengths atFast: i + 1 at: j) max: (lengths at: i at: j + 1))]]]. indices := OrderedCollection new. x := aCollection size + 1. y := anotherCollection size + 1. [x > 1 and: [y > 1]] whileTrue: [ - (lengths at: x at: y) = (lengths at: x - 1 at: y) + (lengths atFast: x at: y) = (lengths atFast: x - 1 at: y) ifTrue: [x := x - 1] ifFalse: [ - (lengths at: x at: y) = (lengths at: x at: y - 1) + (lengths atFast: x at: y) = (lengths atFast: x at: y - 1) ifTrue: [y := y - 1] ifFalse: [ indices add: {x - 1. y - 1}. @@ -193,9 +194,12 @@ DCMappingComparator >> similarityPositionInParentsCompare: aMapping with: anothe indices add: current siblingIndex. current := current parent]. indices]. + + indicesInParents ifNil: [indicesInParents := Dictionary new]. + distance := [:mapping | | indicesVec1 indicesVec2 sum | - indicesVec1 := indicesInOwnerSubmorphs value: mapping first. - indicesVec2 := indicesInOwnerSubmorphs value: mapping second. + indicesVec1 := indicesInParents at: mapping first ifAbsentPut: [indicesInOwnerSubmorphs value: mapping first]. + indicesVec2 := indicesInParents at: mapping second ifAbsentPut: [indicesInOwnerSubmorphs value: mapping second]. sum := 0.0. 1 to: (indicesVec1 size min: indicesVec2 size) diff --git a/packages/DomainCode-Diff/DCMatcher.class.st b/packages/DomainCode-Diff/DCMatcher.class.st index ce760c5..b6ff13d 100644 --- a/packages/DomainCode-Diff/DCMatcher.class.st +++ b/packages/DomainCode-Diff/DCMatcher.class.st @@ -102,6 +102,8 @@ DCMatcher >> matchFrom: src to: dest [ { #category : #'as yet unclassified' } DCMatcher >> performEditsIn: aDest to: aSrc [ + aSrc allChildrenDo: [:m | m clearDiffCache]. + DCChawatheScriptGenerator new generateFrom: aSrc to: aDest diff --git a/packages/DomainCode-Parser/DCBlock.class.st b/packages/DomainCode-Parser/DCBlock.class.st index 2accb0b..d30d7cb 100644 --- a/packages/DomainCode-Parser/DCBlock.class.st +++ b/packages/DomainCode-Parser/DCBlock.class.st @@ -351,7 +351,7 @@ DCBlock class >> smalltalkDeclaration [ ^ { [:x | x language = SBTSSmalltalk]. - [:x | #(#identifier #'block_argument') includes: x type]. + [:x | x is: #(#identifier #'block_argument')]. [:id | {#args. id. id orAllParents: #(#method #block)}]. [:id :scopes | | decl | decl := ((DCQuery @@ -371,8 +371,11 @@ DCBlock class >> smalltalkDeclaration [ detect: [:arg | (arg contents withoutLeading: #($:)) = (id contents withoutLeading: #($:))] ifNone: [nil]]}. { - [:method | "method args" - method queryAll: '[(keyword_selector (identifier) @) (binary_selector (identifier) @)]']. + [:method | + "method args" + method queryFirst: { + [:x | x is: {#'binary_selector'. #'keyword_selector'}]. + [:x | x children select: [:c | c is: #identifier]]}]. [:args | args detect: [:arg | arg contents = id contents] ifNone: [nil]]}} with: scope]} first: scopes) ifNil: [ @@ -581,8 +584,9 @@ DCBlock class >> smalltalkMessageSendAutoCompletion [ [:x | "only autocomplete for the first message part (just after receiver)" x childIndex = 2]. [:x | (DCQuery script: self smalltalkMessageSendSelector with: x) ifNotNil: [:res | res, {x}]]. + [:selector :message :part | selector size > 2]. [:selector :message :part | - part addSuggestions: ((self sortedSuggestions: Symbol allSymbols for: selector addAll: false max: 10) collect: [:sel | + part addSuggestions: ((self sortedSymbolSuggestionsFor: selector max: 10) collect: [:sel | DCSuggestionItem new selector: sel label: 'send' source: ((sel allSatisfy: #isSpecial) ifTrue: [sel, ' __sb'] ifFalse: [ (sel includes: $:) @@ -604,8 +608,7 @@ DCBlock class >> smalltalkMessageSendSelector [ ^ { self smalltalkMessageSend. - [:message | {#args. message queryAll: '[(keyword) (binary_operator) (unary_identifier)] @part'. message}]. - [:hits :message | {#args. hits select: [:part | part owner = message]. message}]. + [:message | {#args. message children select: [:c | c is: #(#keyword #'binary_operator' #'unary_identifier')]. message}]. [:hits :message | {#args. hits collect: #contents. message}]. [:parts :message | {#args. parts joinSeparatedBy: ''. message}]} ] @@ -685,7 +688,7 @@ DCBlock class >> smalltalkSelector [ #args. DCQuery script: { - [:s | s queryAll: '[(keyword) (binary_operator) (unary_identifier)] @part']. + [:s | s children select: [:c | c is: #(#keyword #'binaary_operator' #'unary_identifier')]]. [:hits | (hits collect: #contents) joinSeparatedBy: '']} with: sel. sel}]}} @@ -1023,7 +1026,7 @@ DCBlock >> applyEdit: edit source: newSource cursorAt: newIndex undoDo: aBlock [ self sandblockEditor do: (SBDoItCommand new do: apply; undo: [ - oldTree tryApplyChange: [:source | + oldTree infoForEditDo: [:source | aBlock value: source value: [:new :undoEdit :undo | oldTree applyEdit: undoEdit source: new cursorAt: undoEdit newEndByte undoDo: nil]]])] @@ -1106,21 +1109,31 @@ DCBlock >> childNodes [ { #category : #'as yet unclassified' } DCBlock >> children [ - ^ Array streamContents: [:s | super children do: [:c | c isReplacement ifTrue: [c resolveSource ifNotNil: [:child | s nextPut: child]] ifFalse: [s nextPut: c]]] + ^ Array streamContents: [:s | self childrenDo: [:c | s nextPut: c]] ] { #category : #'as yet unclassified' } -DCBlock >> clearCache [ +DCBlock >> childrenDo: aBlock [ - super clearCache. - self removeProperty: #treeHash + ^ self submorphs do: [:c | + c isReplacement + ifTrue: [c resolveSource ifNotNil: [:child | aBlock value: child]] + ifFalse: [aBlock value: c]] +] + +{ #category : #hierarchy } +DCBlock >> clearDiffCache [ + + self removeProperty: #treeHash. + self removeProperty: #treeSize. + self removeProperty: #treeHeight ] { #category : #'as yet unclassified' } DCBlock >> clearInput [ - self tryApplyChange: [:source :textMorph | self class replace: self activeTextMorph range in: source with: '' do: self applyBlock] + self infoForEditDo: [:source :textMorph | self class replace: (self activeTextMorph ifNil: [self]) range in: source with: '' do: self applyBlock] ] { #category : #'as yet unclassified' } @@ -1161,7 +1174,7 @@ DCBlock >> currentTextMorph [ DCBlock >> deleteAfterCursor [ - self tryApplyChange: [:source :textMorph :cursorIndex | self class deleteFrom: source at: cursorIndex + 1 do: self applyBlock]. + self infoForEditDo: [:source :textMorph :cursorIndex | self class deleteFrom: source at: cursorIndex + 1 do: self applyBlock]. self batchedChangeStep ] @@ -1169,7 +1182,7 @@ DCBlock >> deleteAfterCursor [ DCBlock >> deleteBeforeCursor [ - self tryApplyChange: [:source :textMorph :cursorIndex | self class deleteFrom: source at: cursorIndex do: self applyBlock]. + self infoForEditDo: [:source :textMorph :cursorIndex | self class deleteFrom: source at: cursorIndex do: self applyBlock]. self batchedChangeStep ] @@ -1179,7 +1192,7 @@ DCBlock >> deleteBlock [ self isArtefact ifTrue: [^ super deleteBlock]. - self tryApplyChange: [:source :textMorph :cursorIndex | | delRange | + self infoForEditDo: [:source :textMorph :cursorIndex | | delRange | delRange := textMorph range. self trailingTerminator ifNotNil: [:t | delRange := SBTSRange merging: {delRange. t range}. @@ -1365,11 +1378,17 @@ DCBlock >> handleInsertEvent: anEvent in: textMorph [ { #category : #hierarchy } DCBlock >> hasAnyParent: aBlock [ + | p | self isRootBlock ifTrue: [^ false]. - self parent = aBlock ifTrue: [^ true]. + p := self parent. + p ifNil: [ + self assert: self type = 'ERROR'. + ^ false]. - ^ self parent hasAnyParent: aBlock + p = aBlock ifTrue: [^ true]. + + ^ p hasAnyParent: aBlock ] { #category : #hierarchy } @@ -1404,6 +1423,21 @@ DCBlock >> indentFor: aBlock current: aNumber [ ifFalse: [aNumber] ] +{ #category : #'as yet unclassified' } +DCBlock >> infoForEditDo: aClosure [ + + | oldCursorOffset oldSource | + oldCursorOffset := self activeTextMorph ifNotNil: #cursor. + oldSource := self rootBlock privateSource. + + aClosure valueWithEnoughArguments: { + oldSource. + self activeTextMorph ifNil: [self]. + self activeTextMorph + ifNotNil: [self activeTextMorph range start index + (oldCursorOffset - 1)] + ifNil: [self range]} +] + { #category : #'as yet unclassified' } DCBlock >> initialize [ @@ -1462,7 +1496,7 @@ DCBlock >> inputClosestTextMorphTo: cursorPosition [ { #category : #'as yet unclassified' } DCBlock >> insert: aString [ - self tryApplyChange: [:source :textMorph :cursorIndex | self class insert: aString in: source at: cursorIndex + 1 do: self applyBlock]. + self infoForEditDo: [:source :textMorph :cursorIndex | self class insert: aString in: source at: cursorIndex + 1 do: self applyBlock]. self batchedChangeStep ] @@ -1494,7 +1528,7 @@ DCBlock >> insertStatementAboveOrBelow: anAboveBoolean [ point := anAboveBoolean ifTrue: [target range start] ifFalse: [target range end]. index := point index. - self tryApplyChange: [:source | + self infoForEditDo: [:source | self class insert: String cr, indent in: source @@ -1579,6 +1613,16 @@ DCBlock >> intoWorld: aWorld [ updateQueriesFor: #always] ] +{ #category : #hierarchy } +DCBlock >> is: aCollectionOrSymbol [ + + | matches | + matches := aCollectionOrSymbol isSymbol + ifTrue: [{aCollectionOrSymbol}] + ifFalse: [aCollectionOrSymbol]. + ^ matches includes: self type +] + { #category : #'as yet unclassified' } DCBlock >> isArtefact [ @@ -1648,7 +1692,7 @@ DCBlock >> isTSMorph [ { #category : #'as yet unclassified' } DCBlock >> keyStroke: anEvent [ - self tryApplyChange: [:source :textMorph :cursorIndex | | input | + self infoForEditDo: [:source :textMorph :cursorIndex | | input | input := anEvent keyCharacter asString. (input first isPrintable and: [anEvent commandKeyPressed not]) ifTrue: [ (self adaptInput: input in: source at: cursorIndex textMorph: textMorph event: anEvent) ifNotEmpty: [:text | @@ -1716,16 +1760,6 @@ DCBlock >> minBoundsWith: info [ ^ info bounds ] -{ #category : #'as yet unclassified' } -DCBlock >> noteNewOwner: aMorph [ - - super noteNewOwner: aMorph. - - "check if we have just been moved out of a replacement" - (self replacedParent notNil and: [aMorph notNil and: [aMorph class = DCBlock]]) ifTrue: ["self replacedParent: nil" - ] -] - { #category : #hierarchy } DCBlock >> orAllParents: aCollectionOrSymbol [ @@ -1809,7 +1843,7 @@ DCBlock >> parentNode [ DCBlock >> pasteReplace [ - self tryApplyChange: [:source :textMorph :cursorIndex | | str | + self infoForEditDo: [:source :textMorph :cursorIndex | | str | str := Clipboard clipboardText string. cursorIndex class = SBTSRange @@ -1860,7 +1894,7 @@ DCBlock >> prefersNoBorder [ { #category : #'as yet unclassified' } DCBlock >> prettyPrint [ - self tryApplyChange: [:source | | new | + self infoForEditDo: [:source | | new | new := [ PPFormatter formatString: source @@ -1868,11 +1902,12 @@ DCBlock >> prettyPrint [ noPattern: false] on: SyntaxErrorNotification do: [source]. - self - applyEdit: nil - source: new - cursorAt: 1 - undoDo: [:undoSource :block | block value: source value: nil value: nil]] + source = new ifFalse: [ + self + applyEdit: nil + source: new + cursorAt: 1 + undoDo: [:undoSource :block | block value: source value: nil value: nil]]] ] { #category : #'as yet unclassified' } @@ -1943,6 +1978,8 @@ DCBlock >> privateTSTreeOrNilDo: aBlock [ { #category : #'as yet unclassified' } DCBlock >> queryAll: aString [ + aString isString ifFalse: [^ DCQuery script: aString allDeep: self]. + self assert: (aString includes: $@) description: 'query needs a capture (@) to be useful'. ^ Array streamContents: [:stream | @@ -1969,6 +2006,8 @@ DCBlock >> queryChildrenFirst: aString [ { #category : #'as yet unclassified' } DCBlock >> queryFirst: aString [ + aString isString ifFalse: [^ DCQuery script: aString firstDeep: self]. + self assert: (aString includes: $@) description: 'query needs a capture (@) to be useful'. self allChildrenDo: [:block | @@ -2049,7 +2088,7 @@ DCBlock >> replace: oldTree with: newTree [ { #category : #'as yet unclassified' } DCBlock >> replaceWith: aString [ - self tryApplyChange: [:source :textMorph :cursorIndex | self class replace: textMorph range in: source with: aString do: self applyBlock] + self infoForEditDo: [:source :textMorph :cursorIndex | self class replace: textMorph range in: source with: aString do: self applyBlock] ] { #category : #accessing } @@ -2088,6 +2127,13 @@ DCBlock >> run: aCollection [ ^ DCQuery script: aCollection with: self ] +{ #category : #'as yet unclassified' } +DCBlock >> sandblockEditor [ + + " allow embedded nodes to access the editor " + ^ (self owner ifNil: [self parent]) ifNotNil: [:o | o sandblockEditor] +] + { #category : #'as yet unclassified' } DCBlock >> saveTryFixing: aFixBoolean quick: aQuickBoolean [ @@ -2109,11 +2155,17 @@ DCBlock >> shallowCopyBlock [ { #category : #hierarchy } DCBlock >> siblingIndex [ + | i p | self replacedParent ifNotNil: [^ self replacedParent siblingIndex]. - self parent ifNil: [^ 0]. + p := self parent. + p ifNil: [^ 0]. - ^ self parent children indexOf: self + i := 1. + p childrenDo: [:c | + c = self ifTrue: [^ i]. + i := i + 1]. + ^ 0 ] { #category : #'as yet unclassified' } @@ -2182,7 +2234,7 @@ DCBlock >> suggestions [ { #category : #'as yet unclassified' } DCBlock >> swap: aNumber [ - self tryApplyChange: [:source :textMorph :cursorIndex | | pivot outerPivot | + self infoForEditDo: [:source :textMorph :cursorIndex | | pivot outerPivot | pivot := (self sandblockEditor mode = #input ifTrue: [textMorph] ifFalse: [self]) orOwnerSuchThat: [:morph | morph owner submorphCount > 1]. @@ -2236,14 +2288,14 @@ DCBlock >> trailingTerminator [ { #category : #'as yet unclassified' } DCBlock >> treeHash [ - true ifTrue: [^ self treeHashCount: {0}]. + false ifTrue: [^ self treeHashCount: {0}]. ^ self valueOfProperty: #treeHash ifAbsentPut: [self treeHashCount: {0}] ] { #category : #'as yet unclassified' } DCBlock >> treeHashChildren: anotherNumber [ - ^ ((((self type hash bitXor: 'ENTER' hash) bitXor: anotherNumber) bitXor: self siblingIndex hash) bitXor: self children size) bitXor: 'LEAVE' hash + ^ ((((self type hash bitXor: 'ENTER' hash) bitXor: anotherNumber) bitXor: self siblingIndex hash) bitXor: self childCount) bitXor: 'LEAVE' hash ] { #category : #'as yet unclassified' } @@ -2251,37 +2303,39 @@ DCBlock >> treeHashChildren: anotherNumber countPtr: aCollection [ aCollection at: 1 put: aCollection first + 1. - ^ ((((self type hash + 'ENTER' hash) + anotherNumber) bitXor: (2 * aCollection first + 1) hash) bitXor: self children size) bitXor: 'LEAVE' hash + ^ ((self type hash + 'ENTER' hash + anotherNumber bitXor: (2 * aCollection first + 1) hash) bitXor: self childCount) bitXor: 'LEAVE' hash ] { #category : #'as yet unclassified' } DCBlock >> treeHashCount: aPtr [ + | hash | self hasChildren ifFalse: [^ self treeHashChildren: 0 countPtr: aPtr]. + hash := 0. + + self childrenDo: [:morph | hash := (hash + (morph treeHashCount: aPtr)) hashMultiply]. + ^ self - treeHashChildren: (self children inject: 0 into: [:hash :morph | hash bitXor: (morph treeHashCount: aPtr)]) + treeHashChildren: hash countPtr: aPtr ] +{ #category : #'as yet unclassified' } +DCBlock >> treeHeight [ + + ^ self valueOfProperty: #treeHeight ifAbsentPut: [super treeHeight] +] + { #category : #'as yet unclassified' } DCBlock >> treeLabel [ ^ '' ] -{ #category : #'as yet unclassified' } -DCBlock >> tryApplyChange: aClosure [ +{ #category : #hierarchy } +DCBlock >> treeSize [ - | oldCursorOffset oldSource | - oldCursorOffset := self activeTextMorph ifNotNil: #cursor. - oldSource := self rootBlock privateSource. - - aClosure valueWithEnoughArguments: { - oldSource. - self activeTextMorph ifNil: [self]. - self activeTextMorph - ifNotNil: [self activeTextMorph range start index + (oldCursorOffset - 1)] - ifNil: [self range]} + ^ self valueOfProperty: #treeSize ifAbsentPut: [super treeSize] ] { #category : #'as yet unclassified' } @@ -2314,7 +2368,7 @@ DCBlock >> updateAllHighlights [ { #category : #'as yet unclassified' } DCBlock >> useSuggestion: anItem [ - self tryApplyChange: [:source :textMorph :cursorIndex | self class replace: textMorph range in: source with: anItem source do: self applyBlock] + self infoForEditDo: [:source :textMorph :cursorIndex | self class replace: textMorph range in: source with: anItem source do: self applyBlock] ] { #category : #'as yet unclassified' } @@ -2374,7 +2428,7 @@ DCBlock >> wrapInSquareBrackets [ { #category : #'as yet unclassified' } DCBlock >> wrapWithBefore: aString after: anotherString [ - self tryApplyChange: [:source :textMorph :cursorIndex | + self infoForEditDo: [:source :textMorph :cursorIndex | self class replace: textMorph range in: source diff --git a/packages/DomainCode-Parser/DCEmptyStatement.class.st b/packages/DomainCode-Parser/DCEmptyStatement.class.st index 18ba95c..c68b10d 100644 --- a/packages/DomainCode-Parser/DCEmptyStatement.class.st +++ b/packages/DomainCode-Parser/DCEmptyStatement.class.st @@ -51,7 +51,7 @@ DCEmptyStatement >> insertSeparatorAfter: aBoolean [ DCEmptyStatement >> pasteReplace [ - self tryApplyChange: [:source :textMorph :cursorIndex | | str | + self infoForEditDo: [:source :textMorph :cursorIndex | | str | str := Clipboard clipboardText string. str := self insertSeparatorAfter ifTrue: [str, self language statementTerminator] diff --git a/packages/DomainCode-Parser/DCJumpPlaceholder.class.st b/packages/DomainCode-Parser/DCJumpPlaceholder.class.st index 3253d6d..556f234 100644 --- a/packages/DomainCode-Parser/DCJumpPlaceholder.class.st +++ b/packages/DomainCode-Parser/DCJumpPlaceholder.class.st @@ -4,18 +4,6 @@ Class { #category : #'DomainCode-Parser' } -{ #category : #'as yet unclassified' } -DCJumpPlaceholder >> adaptInput: input in: source at: cursorIndex textMorph: textMorph event: anEvent [ - - (super adaptInput: input in: source at: cursorIndex textMorph: textMorph event: anEvent) ifNotEmpty: [:newInput | - self - replace: self range - in: source - with: newInput - do: [:new :edit | self applyEdit: edit source: new cursorAt: cursorIndex + 1]]. - ^ '' -] - { #category : #'as yet unclassified' } DCJumpPlaceholder >> initialize [ @@ -25,16 +13,24 @@ DCJumpPlaceholder >> initialize [ ] { #category : #'as yet unclassified' } -DCJumpPlaceholder >> isJumpPoint [ - - ^ true +DCJumpPlaceholder >> keyStroke: anEvent [ + + (anEvent keyCharacter isPrintable and: [anEvent commandKeyPressed not]) ifTrue: [ + self source infoForEditDo: [:source :textMorph :cursorIndex | + self source replaceWith: (self source + adaptInput: anEvent keyCharacter asString + in: source + at: cursorIndex + textMorph: textMorph + event: anEvent)]]. + self batchedChangeStep ] { #category : #'as yet unclassified' } DCJumpPlaceholder >> pasteReplace [ - self tryApplyChange: [:source :textMorph :cursorIndex | | str | + self infoForEditDo: [:source :textMorph :cursorIndex | | str | str := Clipboard clipboardText string. self diff --git a/packages/DomainCode-Parser/DCQueryState.class.st b/packages/DomainCode-Parser/DCQueryState.class.st index 6e6e253..587a8bf 100644 --- a/packages/DomainCode-Parser/DCQueryState.class.st +++ b/packages/DomainCode-Parser/DCQueryState.class.st @@ -114,9 +114,14 @@ DCQueryState >> querySourceOverride: aBlock [ { #category : #'as yet unclassified' } DCQueryState >> queueUpdateQueriesFor: aSymbol [ - (updateQueued at: aSymbol ifAbsent: [false]) ifTrue: [^ self]. + (self triggers anySatisfy: [:t | updateQueued at: aSymbol ifAbsent: [false]]) ifTrue: [^ self]. + updateQueued at: aSymbol put: true. - rootBlock world addAlarm: #updateQueriesFor: withArguments: {aSymbol} for: self at: Time millisecondClockValue + rootBlock world + addAlarm: #updatePendingQueries + withArguments: {} + for: self + at: Time millisecondClockValue ] { #category : #'as yet unclassified' } @@ -190,6 +195,15 @@ DCQueryState >> updateDecoratorsDuring: aBlock [ currentDecorators at: currentTrigger put: newDecorators ] +{ #category : #'as yet unclassified' } +DCQueryState >> updatePendingQueries [ + + updateQueued keysAndValuesDo: [:trigger :queued | queued ifTrue: [self updateQueriesFor: trigger]]. + + " FIXME disallows processing to trigger another update -- intentional? " + self triggers do: [:t | updateQueued at: t put: false] +] + { #category : #'as yet unclassified' } DCQueryState >> updateQueriesFor: aSymbol [ diff --git a/packages/DomainCode-Parser/DCReplacement.class.st b/packages/DomainCode-Parser/DCReplacement.class.st index d0febc9..b40bdc5 100644 --- a/packages/DomainCode-Parser/DCReplacement.class.st +++ b/packages/DomainCode-Parser/DCReplacement.class.st @@ -75,6 +75,13 @@ DCReplacement >> contents [ ^ self source ifNotNil: #contents ifNil: [''] ] +{ #category : #'as yet unclassified' } +DCReplacement >> currentTextMorph [ + + self submorphsDo: [:m | m isTextMorph ifTrue: [^ m]]. + ^ nil +] + { #category : #'as yet unclassified' } DCReplacement >> embed: aClosure [ diff --git a/packages/DomainCode-Parser/DCReplacementTest.class.st b/packages/DomainCode-Parser/DCReplacementTest.class.st index cd640bd..12f3733 100644 --- a/packages/DomainCode-Parser/DCReplacementTest.class.st +++ b/packages/DomainCode-Parser/DCReplacementTest.class.st @@ -176,6 +176,6 @@ DCReplacementTest >> testUninstallWithEmbeddedRoot [ replacement := block childSandblocks first childSandblocks first. self assert: DCBlock equals: replacement class. - self assert: #identifier equals: block children first children first type. + self assert: #ideantifier equals: block children first children first type. self assert: 'a2' equals: block children first children first contents] ] diff --git a/packages/DomainCode-Parser/DCSmalltalkMethod.class.st b/packages/DomainCode-Parser/DCSmalltalkMethod.class.st index d9b09c4..3b01423 100644 --- a/packages/DomainCode-Parser/DCSmalltalkMethod.class.st +++ b/packages/DomainCode-Parser/DCSmalltalkMethod.class.st @@ -26,11 +26,11 @@ DCSmalltalkMethod class >> newWith: aString in: aClass [ ] { #category : #'as yet unclassified' } -DCSmalltalkMethod >> blockForPC: aNumber isActiveFrame: aBoolean [ +DCSmalltalkMethod >> blockForPC: aNumber isActiveFrame: aBoolean in: aCompiledCode [ | pc | - pc := aBoolean ifTrue: [aNumber] ifFalse: [self compiledMethod pcPreviousTo: aNumber]. - (self method getSourceStringAndMark parseAsMethodFor: self methodClass) rawSourceRanges keysAndValuesDo: [:node :range | node pc = pc ifTrue: [^ self method smallestBlockEncompassig: (SBTSRange start: range start - 1 size: range size)]]. + pc := aBoolean ifTrue: [aNumber] ifFalse: [aCompiledCode pcPreviousTo: aNumber]. + (self method sourceString parseAsMethodFor: self methodClass) rawSourceRanges keysAndValuesDo: [:node :range | (node pc = pc or: [node pc = (aCompiledCode -> pc)]) ifTrue: [^ self method smallestBlockEncompassig: (SBTSRange start: range start - 1 size: range size)]]. ^ nil ] @@ -141,8 +141,12 @@ DCSmalltalkMethod >> layoutCommands [ DCSmalltalkMethod >> messageSendForError: anError argsDo: aBlock [ | context message | - context := anError signalerContext findContextSuchThat: [:c | c method = self compiledMethod]. - message := self blockForPC: context pc isActiveFrame: context = anError signalerContext. + context := anError signalerContext findContextSuchThat: [:c | " don't look for a block but for the home method of a block " + c method method = self compiledMethod]. + message := self + blockForPC: context pc + isActiveFrame: context = anError signalerContext + in: context method. aBlock value: message value: ((anError signalerContext findContextSuchThat: [:c | c sender = context]) arguments collectWithIndex: [:arg :index | (message childNodes at: 2 + (index - 1 * 2) + 1) -> arg]) @@ -230,7 +234,7 @@ DCSmalltalkMethod >> saveTryFixing: aFixBoolean quick: aQuickBoolean [ DCSmalltalkMethod >> selector [ | selector | - selector := (self method queryAll: '[(unary_selector) (binary_selector) (keyword_selector)] @') ifEmpty: [^ ''] ifNotEmpty: #first. + selector := (self method queryFirst: {[:x | x is: #(#'unary_selector' #'binary_selector' #'keyword_selector')]}) ifNil: [^ '']. ^ (((selector childSandblocks viewFrom: 1 by: 2) collect: [:p | p contents]) joinSeparatedBy: '') asSymbol ] diff --git a/packages/DomainCode-Parser/DCSuggestionItem.class.st b/packages/DomainCode-Parser/DCSuggestionItem.class.st index b1f3dfb..3703388 100644 --- a/packages/DomainCode-Parser/DCSuggestionItem.class.st +++ b/packages/DomainCode-Parser/DCSuggestionItem.class.st @@ -24,5 +24,6 @@ DCSuggestionItem >> source [ DCSuggestionItem >> useSuggestionOn: aBlock in: anEditor [ aBlock useSuggestion: self. - self completionAction ifNotNil: [self completionAction cull: anEditor] + self completionAction ifNotNil: [self completionAction cull: anEditor]. + aBlock batchedChangeStep ] diff --git a/packages/DomainCode-Parser/DCText.class.st b/packages/DomainCode-Parser/DCText.class.st index 4cd7eaf..08a80a6 100644 --- a/packages/DomainCode-Parser/DCText.class.st +++ b/packages/DomainCode-Parser/DCText.class.st @@ -21,6 +21,14 @@ DCText >> allParentsUpTo: aBlock [ ^ {self parent}, (self parent allParentsUpTo: aBlock) ] +{ #category : #'as yet unclassified' } +DCText >> childrenDo: aBlock [ +] + +{ #category : #'as yet unclassified' } +DCText >> clearDiffCache [ +] + { #category : #'as yet unclassified' } DCText >> compatibleWithType: aSymbol [ @@ -104,6 +112,12 @@ DCText >> initialize [ range := SBTSRange null ] +{ #category : #'as yet unclassified' } +DCText >> is: aCollectionOrSymbol [ + + ^ false +] + { #category : #'as yet unclassified' } DCText >> isExpression [ @@ -225,7 +239,12 @@ DCText >> shownColor [ { #category : #hierarchy } DCText >> siblingIndex [ - ^ self parent children indexOf: self + | i | + i := 1. + self parent childrenDo: [:c | + c = self ifTrue: [^ i]. + i := i + 1]. + ^ 0 ] { #category : #'as yet unclassified' } diff --git a/packages/Sandblocks-TreeSitter/Morph.extension.st b/packages/Sandblocks-TreeSitter/Morph.extension.st index 4eff046..07db4c8 100644 --- a/packages/Sandblocks-TreeSitter/Morph.extension.st +++ b/packages/Sandblocks-TreeSitter/Morph.extension.st @@ -16,7 +16,7 @@ Morph >> containingInlineBlock [ { #category : #'*Sandblocks-TreeSitter' } Morph >> descendantsPreOrder [ - ^ Array streamContents: [:s | self children do: [:p | p allChildrenPreorderDo: [:m | s nextPut: m]]] + ^ Array streamContents: [:s | self childrenDo: [:p | p allChildrenPreorderDo: [:m | s nextPut: m]]] ] { #category : #'*Sandblocks-TreeSitter' }