AbstractJavaCompletionEngineSimple refactored to use token patterns. Initial support for receiver type guessing.
authorJan Vrany <jan.vrany@fit.cvut.cz>
Thu, 15 May 2014 10:40:02 +0100
changeset 210 1922d415c704
parent 208 0b9ed08a04c0
child 212 a2caebc602a7
AbstractJavaCompletionEngineSimple refactored to use token patterns. Initial support for receiver type guessing.
SmallSense__AbstractJavaCompletionEngine.st
SmallSense__AbstractJavaCompletionSimple.st
SmallSense__ClassPO.st
SmallSense__CompletionEngine.st
SmallSense__JavaCompletionEngine.st
SmallSense__SmalltalkCompletionEngine.st
SmallSense__TokenStream.st
--- a/SmallSense__AbstractJavaCompletionEngine.st	Wed May 14 15:23:05 2014 +0100
+++ b/SmallSense__AbstractJavaCompletionEngine.st	Thu May 15 10:40:02 2014 +0100
@@ -22,24 +22,42 @@
 !AbstractJavaCompletionEngine methodsFor:'completion-individual'!
 
 addClassesStartingWith: prefix
+    ^ self addClassesStartingWith: prefix fullName: false
+
+    "Created: / 03-10-2013 / 11:16:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 15-05-2014 / 07:25:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+addClassesStartingWith: prefixArg fullName: matchFullName
+    | prefix |
+
+    prefix := prefixArg.
+    matchFullName ifTrue:[
+        prefix := prefix copyReplaceAll: $. with: $/.
+    ].
     context environment allClassesDo: [:cls |
-        cls isJavaClass and:[
+        cls isJavaClass ifTrue:[
             | name i |
 
-            name := cls lastName.
-            i := name lastIndexOf: $/.
-            ((name size >= (i + prefix size))
-                and:[(name at: i + 1) == prefix first
-                and:[(name at: i + prefix size) == prefix last
-                and:[(2 to: prefix size - 1) allSatisfy:[:o| (name at: i + o) == (prefix at: o)]]]])
-                ifTrue:[
-                    result add: (ClassPO new subject: cls).        
+            matchFullName ifTrue:[
+                (cls binaryName startsWith: prefix) ifTrue:[
+                    result add: (ClassPO new subject: cls; showPrefix: true; yourself).
                 ].
+            ] ifFalse:[
+                name := cls lastName.
+                i := name lastIndexOf: $/.
+                ((name size >= (i + prefix size))
+                    and:[(name at: i + 1) == prefix first
+                    and:[(name at: i + prefix size) == prefix last
+                    and:[(2 to: prefix size - 1) allSatisfy:[:o| (name at: i + o) == (prefix at: o)]]]])
+                    ifTrue:[
+                        result add: (ClassPO new subject: cls).
+                    ].
+            ].
         ].
     ].
 
-    "Created: / 03-10-2013 / 11:16:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 14-05-2014 / 12:50:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Created: / 15-05-2014 / 07:24:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 addImportsStartingWith: prefix
@@ -49,12 +67,12 @@
 
     "/ Class imports...
     context environment allClassesDo: [:cls |
-        cls isJavaClass ifTrue:[    
+        cls isJavaClass ifTrue:[
             | name |
 
             name := cls javaName.
             (cls isPublic and:[name startsWith: prefix]) ifTrue:[
-                result add: (JavaImportPO new subject: name; klass: cls; yourself).        
+                result add: (JavaImportPO new subject: name; klass: cls; yourself).
                 packages add: cls javaPackage.
             ].
         ]
@@ -68,7 +86,7 @@
     "Modified (format): / 14-05-2014 / 12:48:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
-addMethodsStartingWith: prefix    
+addMethodsStartingWith: prefix
     ^ self addMethodsStartingWith: prefix stripOff: nil filter: [:m | m isJavaMethod ]
 
     "Created: / 03-10-2013 / 18:01:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
--- a/SmallSense__AbstractJavaCompletionSimple.st	Wed May 14 15:23:05 2014 +0100
+++ b/SmallSense__AbstractJavaCompletionSimple.st	Thu May 15 10:40:02 2014 +0100
@@ -9,13 +9,40 @@
 	category:'SmallSense-Java-Abstract'
 !
 
-AbstractJavaCompletionSimple class instanceVariableNames:'patterns'
+AbstractJavaCompletionSimple class instanceVariableNames:'CompletionPatterns AnalysisPatterns'
 
 "
  No other class instance variables are inherited by this class.
 "
 !
 
+!AbstractJavaCompletionSimple class methodsFor:'initialization'!
+
+initializeCompletionPatterns
+    CompletionPatterns isNil ifTrue:[  CompletionPatterns := Dictionary new ].
+
+    #(
+        '[[:import:]] ( [[:Identifier:]](.[[:Identifier:]])*\.? )?'              #completeImport:
+        '[[:new:]] ( [[:Identifier:]](.[[:Identifier:]])*\.?)?'                     #completeNew:
+
+    ) pairWiseDo:[:pattern :action |
+        CompletionPatterns at: (TokenPatternParser parse: pattern) put: action
+    ].
+
+    "Created: / 14-05-2014 / 16:51:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!AbstractJavaCompletionSimple class methodsFor:'accessing'!
+
+completionPatterns
+    CompletionPatterns isNil ifTrue:[ 
+        self initializeCompletionPatterns.
+    ].
+    ^ CompletionPatterns
+
+    "Created: / 14-05-2014 / 16:55:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !AbstractJavaCompletionSimple class methodsFor:'queries'!
 
 isAbstract
@@ -26,6 +53,22 @@
     ^ self == SmallSense::AbstractJavaCompletionSimple.
 ! !
 
+!AbstractJavaCompletionSimple methodsFor:'accessing'!
+
+completionPatterns
+    ^ self class completionPatterns
+
+    "Created: / 14-05-2014 / 17:02:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!AbstractJavaCompletionSimple methodsFor:'accessing-class'!
+
+scannerClass
+    "raise an error: must be redefined in concrete subclass(es)"
+
+    ^ self subclassResponsibility
+! !
+
 !AbstractJavaCompletionSimple methodsFor:'completion-individual'!
 
 addFieldsStartingWith: prefix
@@ -57,107 +100,174 @@
 !AbstractJavaCompletionSimple methodsFor:'completion-private'!
 
 complete
-    | line col scanner token tokenTypes values startPositions stopPositions maybeReceiverToken |
+    | line col stream tokens anyMatched |
 
     line := codeView listAt: codeView cursorLine.
     col := codeView cursorCol.
     line isNil ifTrue:[ ^ nil ].
     line size < (col - 1) ifTrue:[ ^ nil ].
 
-"/    "/ we need at least three characters in order to reduce
-"/    "/ completions...
-"/    line size < 3 ifTrue:[ ^ nil ]. 
-"/    col - 3 to: col - 1 do:[:i|
-"/        | c |
-"/
-"/        c := line at: i.
-"/        (c isLetterOrDigit or:[c == $_ or:[ c == $$ ] ]) ifFalse:[ ^ nil ] 
-"/    ].
 
-    "/ Setup some context vars
-    method := codeView editedMethod.
-    class := method notNil ifTrue:[method mclass] ifFalse:[codeView editedClass ].
+    stream := TokenStream on: (self scannerClass for: (line readStream readLimit: col - 1)).
+    anyMatched := false.
+    self completionPatterns keysAndValuesDo:[ :pattern :action |
+        | matcher |
 
-    "/ ok, we got three character prefix, now scan the current line...
-    scanner := self scannerClass for: line.
-    tokenTypes := OrderedCollection new.
-    values := OrderedCollection new.
-    startPositions := OrderedCollection new.
-    stopPositions := OrderedCollection new.
-    [
-        [ (token := scanner nextToken) ~~ #EOF and:[ scanner tokenStartPosition < (col - 1) ] ] whileTrue:[
-            tokenTypes add: token.
-            values add: scanner tokenValue.
-            startPositions add: scanner tokenStartPosition.
-            stopPositions add: scanner tokenEndPosition. 
+        stream position: 0. "/ Reset the position
+        matcher := TokenPatternMatcher for: pattern.
+        matcher matchesOnStream: stream do:[:match | 
+            self perform: action with: match.
+            anyMatched := true.
         ].
-    ] on: Error do:[ 
-        ^ nil 
+    ].
+    anyMatched ifFalse:[ 
+        stream position: 0.
+        tokens := stream contents.
+        (tokens size > 2 and:[tokens last type == $. or:[tokens last type == #Identifier and:[ (tokens at: tokens size - 1) type == $. ]]]) ifTrue:[
+            self completeMethodOrField: tokens.
+        ].                
     ].
 
-    tokenTypes isEmpty ifTrue:[ ^ nil ].
-    "/ now, simple check for import declaration
-    tokenTypes first == #import and:[
-        | prefix |
-
-        prefix := String streamContents:[:s|
-            | i |
-
-            i := 2.
-            [ i <= tokenTypes size ] whileTrue:[
-                (tokenTypes at: i) == #Identifier ifTrue:[
-                    s nextPutAll: (values at: i).
-                ] ifFalse:[
-                    ^ nil "/ malformed import
-                ].
-                (i < tokenTypes size) ifTrue:[
-                    (tokenTypes at: i + 1) == $. ifTrue:[
-                        s nextPut: $.
-                    ] ifFalse:[
-                        ^ nil "/ malformed import
-                    ].
-                ].
-                i := i + 2.
-            ].
-        ].
-        self addImportsStartingWith: prefix.
-        ^ result.
-    ].
-
-    "/ We need at least three characters to complete methods/fields.
-    (tokenTypes last ~~ #Identifier or:[values last size < 3]) ifTrue:[ ^ nil ].
-
-    "/ Complete after new keyword
-    (tokenTypes size > 1 and:[(tokenTypes at: tokenTypes size - 1) == #new]) ifTrue:[
-        self addClassesStartingWith: values last.
-        ^ result.
-    ].
-
-
-    "/ now check whether the butlast token is dot...
-    maybeReceiverToken := nil.
-    (tokenTypes size > 1 and:[(tokenTypes at: tokenTypes size - 1) == $.]) ifTrue:[
-        "/ if so, it's likely a message send, then complete methods...
-        tokenTypes size > 2 ifTrue:[
-            maybeReceiverToken := values at: values size - 2.
-        ].
-    ] ifFalse:[
-        "/ if not, then complete local variables, fields and methods defined in the class itself.
-        maybeReceiverToken := 'this'.
-    ].
-    maybeReceiverToken = 'this' ifTrue:[
-        values last first isUppercase ifTrue:[      
-            self addClassesStartingWith: values last.
-        ] ifFalse:[
-            self addFieldsStartingWith: values last.
-            self addLocalsStartingWith: values last.
-        ].
-    ].
-    self addMethodsForReceiver: maybeReceiverToken startingWith: values last.
 
     ^ result
 
     "Created: / 02-10-2013 / 13:55:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 13-05-2014 / 17:46:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified (format): / 15-05-2014 / 07:52:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+completeImport: match
+    | prefix |
+
+    prefix := nil.
+    match size > 1 ifTrue:[ 
+        prefix := String streamContents:[:s | 2 to: match size do:[:i | s nextPutAll: (match at: i) value asString] ].
+    ].
+    self addImportsStartingWith: prefix
+
+    "Created: / 15-05-2014 / 06:57:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+completeMethodOrField: tokens
+    | type dotIndex |
+
+    dotIndex := tokens last type == #Identifier ifTrue:[ tokens size - 1 ] ifFalse:[ tokens size ].  
+    self assert: (tokens at: dotIndex) type == $..
+    type := self guessReceiverTypeFrom: tokens before: dotIndex.
+    type isUnknownType ifFalse:[
+        self addMethodsForType: type.  
+        "/self addFieldsForType: type.
+    ] ifTrue:[ 
+        tokens last type == #Identifier ifTrue:[
+            | prefix |
+
+            prefix := tokens last value.
+            (prefix size >= 3 and:[ prefix ~= 'get' and:[prefix ~= 'set' ]]) ifTrue:[
+                self addMethodsStartingWith: prefix.
+            ].
+        ].
+    ].
+
+    "Created: / 15-05-2014 / 07:44:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 15-05-2014 / 09:44:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+completeNew: match
+    | prefix |
+
+    prefix := nil.
+    match size > 2 ifTrue:[ 
+        prefix := String streamContents:[:s | 2 to: match size do:[:i | s nextPutAll: (match at: i) value asString] ].
+        self addClassesStartingWith: prefix fullName: true.
+    ] ifFalse:[ 
+        prefix := (match at: 2) value.
+        self addClassesStartingWith: prefix
+    ].
+
+    "Created: / 15-05-2014 / 07:16:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!AbstractJavaCompletionSimple methodsFor:'guesswork'!
+
+guessReceiverTypeFrom: tokens before: end
+    | i type |
+
+    i := end - 1.  
+
+    (tokens at: i) type == $) ifTrue:[ 
+        "/ OK, end of message send, scan for method name...
+        | nparens nargs name |
+
+        nparens := 1.
+
+        i := i - 1.
+        nargs := 0.
+        (tokens at: i) type == $( ifTrue:[ 
+            i := i - 1.
+        ] ifFalse:[
+            nargs := 1.
+            [ i > 0 and:[ nparens ~~ 0 ] ] whileTrue:[ 
+                (tokens at: i) type == $) ifTrue:[ 
+                    nparens := nparens + 1 
+                ] ifFalse:[ 
+                    (tokens at: i) type == $( ifTrue:[ 
+                        nparens := nparens - 1 
+                    ] ifFalse:[ 
+                        (((tokens at: i) type == $,) and:[nparens == 1]) ifTrue:[    
+                            nargs := nargs + 1.
+                        ]
+                    ].
+                ].
+                i := i - 1.
+            ].
+        ].
+        nparens ~~ 0 ifTrue:[ 
+            "/ Malformed input
+            ^ Type unknown
+        ].
+        (tokens at: i) type == #Identifier ifFalse:[ 
+            "/ Malformed input
+            ^ Type unknown
+        ].
+        name := (tokens at: i) value.
+        i > 0 ifTrue:[ 
+            (tokens at: i - 1) type == $. ifTrue:[ 
+                type := self guessReceiverTypeFrom: tokens before: i - 1.
+            ] ifFalse:[ 
+                type := Type withClass: class.
+            ].
+            ^ self guessTypeOfMethod: type of: type numArgs: nargs.
+        ].
+    ].
+
+    ^ Type withClass: (context environment classNamed:#'JAVA::java::lang::Object')
+
+    "Created: / 15-05-2014 / 08:09:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 15-05-2014 / 09:42:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+guessTypeOfMethod: name of: type numArgs: nargs
+    | methods |
+
+    methods := Set new.
+    type classesDo:[:initialClass | 
+        | class |
+
+        class := initialClass.
+        [ class notNil and:[ class ~~ JavaObject  ] ] whileTrue:[
+            class selectorsAndMethodsDo:[:selector :method |
+                method isJavaMethod ifTrue:[ 
+                    (selector size > name size 
+                        and:[ method numJavaArgs = nargs
+                        and:[ (selector at: name size + 1) == $(
+                        and:[ (selector startsWith: name) ]]])
+                        ifTrue:[ methods add: method ].
+                    ].
+            ].
+        ].
+    ].
+
+    self halt.
+
+    "Created: / 15-05-2014 / 09:39:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
--- a/SmallSense__ClassPO.st	Wed May 14 15:23:05 2014 +0100
+++ b/SmallSense__ClassPO.st	Thu May 15 10:40:02 2014 +0100
@@ -39,7 +39,7 @@
     showPrefix ifTrue:[
         nm := subject name.
         (context notNil and:[subject isJavaClass]) ifTrue:[
-            context language isJava ifTrue:[
+            context language isJavaLike ifTrue:[
                 nm := subject javaName
             ] ifFalse:[
                 context language isSmalltalk ifTrue:[
@@ -53,7 +53,7 @@
     ^nm
 
     "Created: / 26-08-2013 / 10:26:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 17-12-2013 / 22:16:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 15-05-2014 / 07:28:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 showPrefix
@@ -67,20 +67,26 @@
 stringAlreadyWritten
     "Answers a string already written in the textview"    
 
-    (subject isJavaClass and:[context language isSmalltalk]) ifTrue:[
-        | rec |
+    subject isJavaClass ifTrue:[
+        context language isSmalltalk ifTrue:[
+            | rec |
 
-        rec := context node .
-        [ rec isUnaryMessage ] whileTrue:[
-            rec := rec receiver.
-        ].
-        (rec isVariableNode and:['JAVA' startsWith: rec name]) ifTrue:[
-            ^ context codeView contents asString copyFrom: rec startPosition to: context node endPosition
-        ].
+            rec := context node .
+            [ rec isUnaryMessage ] whileTrue:[
+                rec := rec receiver.
+            ].
+            (rec isVariableNode and:['JAVA' startsWith: rec name]) ifTrue:[
+                ^ context codeView contents asString copyFrom: rec startPosition to: context node endPosition
+            ].
+        ] ifFalse:[ 
+        context language isJavaLike ifTrue:[
+             ^ context wordBeforeCursorConsisitingOfCharactersMatching:[:c | c isAlphaNumeric or:['$_.' includes: c] ]
+        ]].
     ].
     ^ super stringAlreadyWritten
 
     "Created: / 20-10-2013 / 02:46:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 15-05-2014 / 07:31:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 stringToCompleteForLanguage: language
--- a/SmallSense__CompletionEngine.st	Wed May 14 15:23:05 2014 +0100
+++ b/SmallSense__CompletionEngine.st	Thu May 15 10:40:02 2014 +0100
@@ -92,6 +92,159 @@
 
 !CompletionEngine methodsFor:'completion-individual'!
 
+addMethodsForType: type 
+    | classes seen |
+
+    classes := type classes.
+    "/ Hack for Boolean: ifTrue:iFalse: etc are not defined
+    "/ in Boolean ?!!?
+    (classes size == 1 and:[classes anElement == Boolean ]) ifTrue:[
+        classes := Array with: True with: False.
+    ].
+    classes size == 1 ifTrue:[
+        classes anElement == JavaPackage class ifTrue:[  
+            "/ Special hack for JAVA: for pattern `JAVA java lang reflect`
+            "/ complete all Java classes in that package
+            | node |
+
+            node := result context node.
+            node isUnaryMessage ifTrue:[
+                | package |
+                "/ Compute package prefix...
+
+                package := node selector.
+                node := node receiver.
+                [ node isUnaryMessage ] whileTrue:[
+                    package := node selector , '/' , package.
+                    node := node receiver.
+                ].
+                self addJavaClassesInPackage: package.
+                ^ self.
+            ]
+        ]
+    ].
+
+    seen := Set new.
+    classes do: [:each | 
+        | class |
+
+        class := each.
+        [ class notNil and:[(seen includes: class) not]] whileTrue: [
+            seen add: class.
+            "/ Now, special care for Java classes, sigh...
+            (class isMetaclass and:[class theNonMetaclass isJavaClass]) ifTrue:[
+                class theNonMetaclass selectorsAndMethodsDo: [:selector :met | 
+                    met isStatic ifTrue:[
+                        result add: (MethodPO 
+                                    name: selector
+                                    class: met mclass).
+                    ].
+                ].
+            ] ifFalse:[
+                class selectorsAndMethodsDo: [:selector :met | 
+                    met isSynthetic ifFalse:[
+                        result add: (MethodPO 
+                                    name: selector
+                                    class: met mclass).
+                    ]
+                ].
+            ].
+            class := class superclass.
+        ]
+    ].
+
+    "Created: / 26-11-2011 / 17:03:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 22-01-2014 / 19:48:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+addMethodsForType: type prefix: prefix stripOff: stripprefix
+
+    type isUnknownType ifFalse:[
+        self addMethodsForType:type stripOff: stripprefix.
+        
+        "/ If the type is union of more than 6 types, then
+        "/ assume that the inferencer is likely wrong.
+        "/ then, if the prefix is at least 3 chars,
+        "/ also add methods with that prefix.
+        
+        ((type classes size > 6) and:[ prefix size > 2 ]) ifTrue:[
+            self addMethodsStartingWith:prefix stripOff: stripprefix
+        ].
+    ] ifTrue:[
+        self addMethodsStartingWith:prefix stripOff: stripprefix  
+    ].
+
+    "Created: / 08-04-2014 / 21:04:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 09-04-2014 / 09:31:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+addMethodsForType: type stripOff: stripprefix     
+    | classes seen |
+
+    classes := type classes.
+    "/ Hack for Boolean: ifTrue:iFalse: etc are not defined
+    "/ in Boolean ?!!?
+    (classes size == 1 and:[classes anElement == Boolean ]) ifTrue:[
+        classes := Array with: True with: False.
+    ].
+    classes size == 1 ifTrue:[
+        classes anElement == JavaPackage class ifTrue:[  
+            "/ Special hack for JAVA: for pattern `JAVA java lang reflect`
+            "/ complete all Java classes in that package
+            | node |
+
+            node := result context node.
+            node isUnaryMessage ifTrue:[
+                | package |
+                "/ Compute package prefix...
+
+                package := node selector.
+                node := node receiver.
+                [ node isUnaryMessage ] whileTrue:[
+                    package := node selector , '/' , package.
+                    node := node receiver.
+                ].
+                self addJavaClassesInPackage: package.
+                ^ self.
+            ]
+        ]
+    ].
+
+    seen := Set new.
+    classes do: [:each | 
+        | class |
+
+        class := each.
+        [ class notNil and:[(seen includes: class) not]] whileTrue: [
+            seen add: class.
+            "/ Now, special care for Java classes, sigh...
+            (class isMetaclass and:[class theNonMetaclass isJavaClass]) ifTrue:[
+                class theNonMetaclass selectorsAndMethodsDo: [:selector :met | 
+                    met isStatic ifTrue:[
+                        result add: (MethodPO 
+                                    name: selector
+                                    class: met mclass).
+                    ].
+                ].
+            ] ifFalse:[
+                class selectorsAndMethodsDo: [:selector :met | 
+                    met isSynthetic ifFalse:[
+                        (stripprefix isNil or:[ selector size > stripprefix size and:[selector startsWith: stripprefix]]) ifTrue:[
+                            result add: (MethodPO 
+                                        name: selector
+                                        class: met mclass
+                                        stripOff: stripprefix).
+                        ].
+                    ]
+                ].
+            ].
+            class := class superclass.
+        ]
+    ].
+
+    "Created: / 08-04-2014 / 21:23:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
 addMethodsStartingWith: prefix
     ^ self addMethodsStartingWith: prefix stripOff: nil filter: nil
 
--- a/SmallSense__JavaCompletionEngine.st	Wed May 14 15:23:05 2014 +0100
+++ b/SmallSense__JavaCompletionEngine.st	Thu May 15 10:40:02 2014 +0100
@@ -24,25 +24,6 @@
 
 !JavaCompletionEngine methodsFor:'completion-individual'!
 
-addClassesStartingWith: prefix
-    self javaClassesDo:[:cls|
-        | name i |
-
-        name := cls lastName.
-        i := name lastIndexOf: $/.
-        ((name size >= (i + prefix size))
-            and:[(name at: i + 1) == prefix first
-            and:[(name at: i + prefix size) == prefix last
-            and:[(2 to: prefix size - 1) allSatisfy:[:o| (name at: i + o) == (prefix at: o)]]]])
-            ifTrue:[
-                result add: (ClassPO new subject: cls).        
-            ].
-    ].
-
-    "Created: / 03-10-2013 / 11:16:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 20-10-2013 / 01:27:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
 addFieldsStartingWith: prefix
     | klass |
 
--- a/SmallSense__SmalltalkCompletionEngine.st	Wed May 14 15:23:05 2014 +0100
+++ b/SmallSense__SmalltalkCompletionEngine.st	Thu May 15 10:40:02 2014 +0100
@@ -151,159 +151,6 @@
     "Modified: / 14-05-2014 / 12:48:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
-addMethodsForType: type 
-    | classes seen |
-
-    classes := type classes.
-    "/ Hack for Boolean: ifTrue:iFalse: etc are not defined
-    "/ in Boolean ?!!?
-    (classes size == 1 and:[classes anElement == Boolean ]) ifTrue:[
-        classes := Array with: True with: False.
-    ].
-    classes size == 1 ifTrue:[
-        classes anElement == JavaPackage class ifTrue:[  
-            "/ Special hack for JAVA: for pattern `JAVA java lang reflect`
-            "/ complete all Java classes in that package
-            | node |
-
-            node := result context node.
-            node isUnaryMessage ifTrue:[
-                | package |
-                "/ Compute package prefix...
-
-                package := node selector.
-                node := node receiver.
-                [ node isUnaryMessage ] whileTrue:[
-                    package := node selector , '/' , package.
-                    node := node receiver.
-                ].
-                self addJavaClassesInPackage: package.
-                ^ self.
-            ]
-        ]
-    ].
-
-    seen := Set new.
-    classes do: [:each | 
-        | class |
-
-        class := each.
-        [ class notNil and:[(seen includes: class) not]] whileTrue: [
-            seen add: class.
-            "/ Now, special care for Java classes, sigh...
-            (class isMetaclass and:[class theNonMetaclass isJavaClass]) ifTrue:[
-                class theNonMetaclass selectorsAndMethodsDo: [:selector :met | 
-                    met isStatic ifTrue:[
-                        result add: (MethodPO 
-                                    name: selector
-                                    class: met mclass).
-                    ].
-                ].
-            ] ifFalse:[
-                class selectorsAndMethodsDo: [:selector :met | 
-                    met isSynthetic ifFalse:[
-                        result add: (MethodPO 
-                                    name: selector
-                                    class: met mclass).
-                    ]
-                ].
-            ].
-            class := class superclass.
-        ]
-    ].
-
-    "Created: / 26-11-2011 / 17:03:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 22-01-2014 / 19:48:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-addMethodsForType: type prefix: prefix stripOff: stripprefix
-
-    type isUnknownType ifFalse:[
-        self addMethodsForType:type stripOff: stripprefix.
-        
-        "/ If the type is union of more than 6 types, then
-        "/ assume that the inferencer is likely wrong.
-        "/ then, if the prefix is at least 3 chars,
-        "/ also add methods with that prefix.
-        
-        ((type classes size > 6) and:[ prefix size > 2 ]) ifTrue:[
-            self addMethodsStartingWith:prefix stripOff: stripprefix
-        ].
-    ] ifTrue:[
-        self addMethodsStartingWith:prefix stripOff: stripprefix  
-    ].
-
-    "Created: / 08-04-2014 / 21:04:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 09-04-2014 / 09:31:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-addMethodsForType: type stripOff: stripprefix     
-    | classes seen |
-
-    classes := type classes.
-    "/ Hack for Boolean: ifTrue:iFalse: etc are not defined
-    "/ in Boolean ?!!?
-    (classes size == 1 and:[classes anElement == Boolean ]) ifTrue:[
-        classes := Array with: True with: False.
-    ].
-    classes size == 1 ifTrue:[
-        classes anElement == JavaPackage class ifTrue:[  
-            "/ Special hack for JAVA: for pattern `JAVA java lang reflect`
-            "/ complete all Java classes in that package
-            | node |
-
-            node := result context node.
-            node isUnaryMessage ifTrue:[
-                | package |
-                "/ Compute package prefix...
-
-                package := node selector.
-                node := node receiver.
-                [ node isUnaryMessage ] whileTrue:[
-                    package := node selector , '/' , package.
-                    node := node receiver.
-                ].
-                self addJavaClassesInPackage: package.
-                ^ self.
-            ]
-        ]
-    ].
-
-    seen := Set new.
-    classes do: [:each | 
-        | class |
-
-        class := each.
-        [ class notNil and:[(seen includes: class) not]] whileTrue: [
-            seen add: class.
-            "/ Now, special care for Java classes, sigh...
-            (class isMetaclass and:[class theNonMetaclass isJavaClass]) ifTrue:[
-                class theNonMetaclass selectorsAndMethodsDo: [:selector :met | 
-                    met isStatic ifTrue:[
-                        result add: (MethodPO 
-                                    name: selector
-                                    class: met mclass).
-                    ].
-                ].
-            ] ifFalse:[
-                class selectorsAndMethodsDo: [:selector :met | 
-                    met isSynthetic ifFalse:[
-                        (stripprefix isNil or:[ selector size > stripprefix size and:[selector startsWith: stripprefix]]) ifTrue:[
-                            result add: (MethodPO 
-                                        name: selector
-                                        class: met mclass
-                                        stripOff: stripprefix).
-                        ].
-                    ]
-                ].
-            ].
-            class := class superclass.
-        ]
-    ].
-
-    "Created: / 08-04-2014 / 21:23:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
 addPools
     | class |
 
--- a/SmallSense__TokenStream.st	Wed May 14 15:23:05 2014 +0100
+++ b/SmallSense__TokenStream.st	Thu May 15 10:40:02 2014 +0100
@@ -36,6 +36,18 @@
     "Created: / 06-05-2014 / 15:25:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!TokenStream methodsFor:'* As yet uncategorized *'!
+
+contents
+    ^ Array streamContents:[ :s | 
+        [ self atEnd ] whileFalse:[ 
+            s nextPut: self next
+        ].
+    ].
+
+    "Created: / 15-05-2014 / 07:49:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !TokenStream methodsFor:'accessing'!
 
 sourceStream