Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions src/Camel-Case-Matching-Tests/CoGlobalEntryTest.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
Class {
#name : 'CoGlobalEntryTest',
#superclass : 'TestCase',
#category : 'Camel-Case-Matching-Tests',
#package : 'Camel-Case-Matching-Tests'
}

{ #category : 'testing' }
CoGlobalEntryTest >> testCamelCasePartsOf [
self assert: (CoGlobalEntry new camelCasePartsOf: 'CoGlobalVariableFetcher')
equals: #('Co' 'Global' 'Variable' 'Fetcher')
]

{ #category : 'testing' }
CoGlobalEntryTest >> testMatchTokenAgainstPartsPartIndexWhenEmptyToken [

]

{ #category : 'testing' }
CoGlobalEntryTest >> testMatchTokenAgainstPartsPartIndexWhenEmptyTokenWithParts [
self assert:(CoGlobalEntry new matchToken: '' againstParts: #('foo' 'bar') partIndex: 1) equals: true
]

{ #category : 'testing' }
CoGlobalEntryTest >> testMatchTokenAgainstPartsPartIndexWhenExactMatch [
self assert:(CoGlobalEntry new matchToken: 'FooBarBaz' againstParts: #('Foo' 'Bar' 'Baz') partIndex: 1) equals: true
]

{ #category : 'testing' }
CoGlobalEntryTest >> testMatchTokenAgainstPartsPartIndexWhenNoMatch [
self assert:(CoGlobalEntry new matchToken: 'FooBarBaz' againstParts: #('Co' 'A' 'S' 'T' 'Fetcher') partIndex: 1) equals: false
]

{ #category : 'testing' }
CoGlobalEntryTest >> testMatchTokenAgainstPartsPartIndexWhenTokenConsumesBeforePartsEnd [
self assert:(CoGlobalEntry new matchToken: 'CoAST' againstParts: #('Co' 'A' 'S' 'T' 'Fetcher') partIndex: 1) equals: true
]

{ #category : 'testing' }
CoGlobalEntryTest >> testMatchTokenAgainstPartsPartIndexWhenTokenTooLong [
self assert:(CoGlobalEntry new matchToken: 'FooBarBaz' againstParts: #('Foo' 'Bar') partIndex: 1) equals: false
]

{ #category : 'testing' }
CoGlobalEntryTest >> testMatchesCamelCaseCompletionTokenCaseSensitiveWhenEmptyToken [
self assert: (CoGlobalEntry new matchesCamelCaseCompletionToken: '' caseSensitive: true) equals: true
]

{ #category : 'testing' }
CoGlobalEntryTest >> testMatchesCamelCaseCompletionTokenCaseSensitiveWhenExactPrefixMatch [
| entry |
entry := CoGlobalEntry new.
entry contents: 'CoGlobalVariableFetcher'.

self assert: (
entry matchesCamelCaseCompletionToken: 'CoGlo'
caseSensitive: true
) equals: true
]

{ #category : 'testing' }
CoGlobalEntryTest >> testMatchesCamelCaseCompletionTokenCaseSensitiveWhenExactPrefixMatchCaseInsensitive [
| entry |
entry := CoGlobalEntry new.
entry contents: 'CoGlobalVariableFetcher'.

self assert: (
entry matchesCamelCaseCompletionToken: 'CoGlo'
caseSensitive: false
) equals: true
]

{ #category : 'testing' }
CoGlobalEntryTest >> testMatchesCamelCaseCompletionTokenCaseSensitiveWhenMatchFailsDueToWrongOrder [
| entry |
entry := CoGlobalEntry new.
entry contents: 'CoGlobalVariableFetcher'.

self assert: (
entry matchesCamelCaseCompletionToken: 'CoFetVar'
caseSensitive: false
) equals: false
]

{ #category : 'testing' }
CoGlobalEntryTest >> testMatchesCamelCaseCompletionTokenCaseSensitiveWhenNoPartsReturnsFalse [
| entry |
entry := CoGlobalEntry new.
entry contents: ''.

self assert: (
entry matchesCamelCaseCompletionToken: 'CoFetVar'
caseSensitive: false
) equals: false
]

{ #category : 'testing' }
CoGlobalEntryTest >> testcamelCasePartsOfWhenAcronymInMiddle [
self assert: (CoGlobalEntry new camelCasePartsOf: 'CoHeuristicASTResultSetBuilder') equals: #('Co' 'Heuristic' 'A' 'S' 'T' 'Result' 'Set' 'Builder')
]

{ #category : 'testing' }
CoGlobalEntryTest >> testcamelCasePartsOfWhenAllUppercase [
self assert: (CoGlobalEntry new camelCasePartsOf: 'AST') equals: #('A' 'S' 'T')
]

{ #category : 'testing' }
CoGlobalEntryTest >> testcamelCasePartsOfWhenCamelCase [
self assert: (CoGlobalEntry new camelCasePartsOf: 'CoVariableFetcher') equals: #('Co' 'Variable' 'Fetcher')
]

{ #category : 'testing' }
CoGlobalEntryTest >> testcamelCasePartsOfWhenEmptyString [
self assert: (CoGlobalEntry new camelCasePartsOf: '') equals: #()
]

{ #category : 'testing' }
CoGlobalEntryTest >> testcamelCasePartsOfWhenLowerCaseWord [
self assert: (CoGlobalEntry new camelCasePartsOf: 'foo') equals: #('foo')
]
27 changes: 27 additions & 0 deletions src/Camel-Case-Matching-Tests/CoGlobalVariableFetcherTest.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Class {
#name : 'CoGlobalVariableFetcherTest',
#superclass : 'TestCase',
#category : 'Camel-Case-Matching-Tests',
#package : 'Camel-Case-Matching-Tests'
}

{ #category : 'testing' }
CoGlobalVariableFetcherTest >> testNewEntryForSetsContents [
|fetcher|
fetcher := CoGlobalVariableFetcher new.
self assert: ((fetcher newEntryFor: 'OrderedCollection') contents) equals: 'OrderedCollection'
]

{ #category : 'testing' }
CoGlobalVariableFetcherTest >> testNewEntryForSetsFetcherName [
|fetcher|
fetcher := CoGlobalVariableFetcher new.
self assert: ((fetcher newEntryFor: 'OrderedCollection') fetcherName ) equals: 'CoGlobalVariableFetcher'
]

{ #category : 'testing' }
CoGlobalVariableFetcherTest >> testNewEntryForSetsNode [
|fetcher|
fetcher := CoGlobalVariableFetcher new.
self assert: ((fetcher newEntryFor: 'OrderedCollection') node) equals: nil
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ Extension { #name : 'CoCaseInsensitiveBeginsWithFilter' }
{ #category : '*Camel-Case-Matching' }
CoCaseInsensitiveBeginsWithFilter >> accepts: aCandidate [

^ (self candidate: aCandidate matchesPrefixCaseSensitive: false)
or: [ NECPreferences camelCaseGlobalMatching
and: [ self candidate: aCandidate matchesCamelCaseCaseSensitive: false ] ]
^ (self candidate: aCandidate matchesPrefixCaseSensitive: false) or: [
self candidate: aCandidate matchesCamelCaseCaseSensitive: false ]
]
8 changes: 6 additions & 2 deletions src/Camel-Case-Matching/CoEntry.extension.st
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ Extension { #name : 'CoEntry' }

{ #category : '*Camel-Case-Matching' }
CoEntry >> beginsWith: aString [

"Returns true if the receiver begins with the given string using case-sensitive prefix matching."
^ self matchesPrefixToken: aString caseSensitive: true
]

{ #category : '*Camel-Case-Matching' }
CoEntry >> matchesCamelCaseCompletionToken: aString caseSensitive: aBoolean [

"Default implementation always returns false.
Actual camelCase matching logic is implemented in subclasses."

^ false
]

{ #category : '*Camel-Case-Matching' }
CoEntry >> matchesPrefixToken: aString caseSensitive: aBoolean [
"Returns true if the receiver's contents begins with aString,
using either case-sensitive or case-insensitive comparison."

^ self contents beginsWith: aString caseSensitive: aBoolean
]
23 changes: 23 additions & 0 deletions src/Camel-Case-Matching/CoGlobalEntry.extension.st
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ Extension { #name : 'CoGlobalEntry' }

{ #category : '*Camel-Case-Matching' }
CoGlobalEntry >> camelCasePartsOf: aString [
"Splits a camelCase or PascalCase string into its component parts.
Returns an array of substrings, breaking before each uppercase letter
(except the first character)."

| parts current |
parts := OrderedCollection new.
Expand All @@ -21,6 +24,10 @@ CoGlobalEntry >> camelCasePartsOf: aString [

{ #category : '*Camel-Case-Matching' }
CoGlobalEntry >> matchToken: token againstParts: parts [
"Entry point for token matching against a collection of parts.
Starts the recursive matching process from the first part (index 1).
See matchToken:againstParts:partIndex:
"

^ self
matchToken: token
Expand All @@ -31,6 +38,15 @@ CoGlobalEntry >> matchToken: token againstParts: parts [
{ #category : '*Camel-Case-Matching' }
CoGlobalEntry >> matchToken: token againstParts: parts partIndex: startIndex [

"Returns true if the given token can be matched by concatenating
prefixes of successive parts, starting at startIndex.

The match proceeds in order through the parts collection, taking
one prefix per part and consuming the token progressively.
Uses backtracking to try all possible prefix lengths.

Returns true if the entire token is consumed, false otherwise."

token ifEmpty: [ ^ true ].
startIndex > parts size ifTrue: [ ^ false ].

Expand All @@ -54,6 +70,13 @@ CoGlobalEntry >> matchToken: token againstParts: parts partIndex: startIndex [
{ #category : '*Camel-Case-Matching' }
CoGlobalEntry >> matchesCamelCaseCompletionToken: aString caseSensitive: aBoolean [

"Checks whether aString matches the receiver's contents

The contents are split into camelCase parts, and the input string
is compared as a prefix across these parts in order.

Returns true if the token can be matched, false otherwise."

| token parts normalizedParts normalizedToken |
aString ifEmpty: [ ^ true ].

Expand Down
7 changes: 7 additions & 0 deletions src/Camel-Case-Matching/CoGlobalVariableFetcher.extension.st
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ Extension { #name : 'CoGlobalVariableFetcher' }

{ #category : '*Camel-Case-Matching' }
CoGlobalVariableFetcher >> entriesDo: aBlock [
"Iterates over full environment entries and filtered global names,
converting each into a CoGlobalEntry and passing it to the block."

self entriesDoWithFullEnvironmentScan: aBlock .

Expand All @@ -13,6 +15,9 @@ CoGlobalVariableFetcher >> entriesDo: aBlock [

{ #category : '*Camel-Case-Matching' }
CoGlobalVariableFetcher >> entriesDoWithFullEnvironmentScan: aBlock [
"Iterates over all global system names and yields a CoGlobalEntry for each one to the given block.

Performs a full environment scan (no filtering) and wraps each global name into an entry before passing it to the block."

self systemNavigation
allGlobalNamesStartingWith: ''
Expand All @@ -23,6 +28,8 @@ CoGlobalVariableFetcher >> entriesDoWithFullEnvironmentScan: aBlock [
{ #category : '*Camel-Case-Matching' }
CoGlobalVariableFetcher >> newEntryFor: aGlobalName [

"Creates a CoGlobalEntry for a global name, setting its AST node and fetcher name."

^ (CoGlobalEntry contents: aGlobalName node: astNode)
fetcherName: self class name;
yourself
Expand Down
Loading