--- a/SmallSense__SmalltalkCompletionEngine.st Mon May 19 16:57:14 2014 +0100
+++ b/SmallSense__SmalltalkCompletionEngine.st Thu May 22 16:15:30 2014 +0100
@@ -3,7 +3,7 @@
"{ NameSpace: SmallSense }"
CompletionEngine subclass:#SmalltalkCompletionEngine
- instanceVariableNames:'inferencer'
+ instanceVariableNames:'collector'
classVariableNames:'Debug'
poolDictionaries:''
category:'SmallSense-Smalltalk'
@@ -43,33 +43,58 @@
!SmalltalkCompletionEngine class methodsFor:'utilities'!
-resultSetFor: mode source: source class: class line: line column: col
+resultSetFor: mode source: source class: class line: line column: col
| inferencer tree |
mode == #method ifTrue:[
inferencer := SmalltalkInferencer forClass: class methodSource: source asString.
inferencer parserClass: SmalltalkParser.
+ inferencer process.
] ifFalse:[
self breakPoint: #jv.
^nil.
inferencer := Parser for: (source asString readStream).
"JV@2011-06-13: HACK, use polymorphism"
tree := inferencer
- parseExpressionWithSelf:nil
- notifying:nil
- ignoreErrors:false
- ignoreWarnings:false
+ parseExpressionWithSelf:nil
+ notifying:nil
+ ignoreErrors:false
+ ignoreWarnings:false
inNameSpace:nil.
inferencer tree: tree.
].
^ self new
completeAtLine:line
column:col
- inferencer:inferencer
+ collector:inferencer
"Modified: / 07-04-2011 / 22:55:58 / Jakub <zelenja7@fel.cvut.cz>"
"Created: / 26-11-2011 / 17:53:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 13-05-2014 / 12:29:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 02-09-2013 / 14:43:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified (format): / 02-10-2013 / 13:09:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!SmalltalkCompletionEngine methodsFor:'completion-helpers'!
+
+javaClassesDo: aBlock
+ | class loader loaders |
+
+ class := collector klass.
+ loaders := Set new.
+ loader := (class notNil and:[class isJavaClass]) ifTrue:[class classLoader] ifFalse:[JavaVM systemClassLoader].
+ [ loader notNil ] whileTrue:[
+ loaders add: loader.
+ loader := loader instVarNamed: #parent.
+ ].
+ loaders add: nil.
+
+ JavaVM registry classesDo:[:cls|
+ (loaders includes: cls classLoader) ifTrue:[
+ aBlock value: cls.
+ ].
+ ].
+
+ "Created: / 04-10-2013 / 13:10:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!SmalltalkCompletionEngine methodsFor:'completion-individual'!
@@ -77,7 +102,7 @@
addClassVariables
| class |
- class := inferencer klass theNonMetaclass.
+ class := collector klass theNonMetaclass.
class classVarNames do:[:nm|
result add:(VariablePO classVariable: nm in: class).
].
@@ -89,7 +114,7 @@
addGlobalsStartingWith: prefix
| class ns cls environment |
- class := inferencer klass.
+ class := collector klass.
ns := class nameSpace.
environment := context environment.
"nameSpace may return private class, sigh"
@@ -99,10 +124,10 @@
cls := ns classNamed: nm.
(cls notNil and:[cls name = nm]) ifTrue:[
(JavaPackage isNil or:[cls isJavaPackage not]) ifTrue:[
- result add:(ClassPO new subject: cls; showPrefix: cls isJavaClass).
+ result add:(((PO forClass: cls)) showPrefix: cls isJavaClass).
]
] ifFalse:[
- (self isGlobalKeyForClassVariable: nm) ifFalse:[
+ (self isGlobalKeyForClassVariable: nm) ifFalse:[
result add:(VariablePO globalVariable: nm)
].
].
@@ -115,9 +140,9 @@
(JavaPackage isNil or:[cls isJavaPackage not ]) ifTrue:[
cls notNil ifTrue:[
cls isBehavior ifTrue:[
- result add:(ClassPO new subject: cls; showPrefix: cls isJavaClass).
+ result add:(((PO forClass: cls)) showPrefix: cls isJavaClass).
] ifFalse:[
- (self isGlobalKeyForClassVariable: nm) ifFalse:[
+ (self isGlobalKeyForClassVariable: nm) ifFalse:[
result add:(VariablePO globalVariable: nm).
].
]
@@ -128,13 +153,135 @@
]
"Created: / 26-11-2011 / 17:29:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 13-05-2014 / 12:09:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 20-05-2014 / 09:58:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+addJavaClassesInPackage: prefix
+ prefix isEmptyOrNil ifTrue:[
+ self javaClassesDo: [:cls |
+ result add: (ClassPO new klass: cls; showPrefix: true; yourself)
+ ].
+ ] ifFalse:[
+ self javaClassesDo: [:cls |
+ (cls binaryName startsWith: prefix) ifTrue:[
+ result add: (ClassPO new klass: cls; showPrefix: true; yourself)
+ ].
+ ].
+
+ ].
+
+ "Created: / 04-10-2013 / 13:09:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 20-10-2013 / 02:42:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+addMethodsForType: type
+ ^ self addMethodsForType: type stripOff: nil
+
+ "Created: / 26-11-2011 / 17:03:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 09-05-2014 / 12:51:36 / 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 selector2classesMap |
+
+ selector2classesMap := Dictionary new.
+ 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 selector2classMap |
+
+ class := each.
+ selector2classMap := Dictionary new.
+
+ "/ Now, special care for Java classes, sigh...
+ (class isMetaclass and:[class theNonMetaclass isJavaClass]) ifTrue:[
+ seen add: class.
+ class theNonMetaclass selectorsAndMethodsDo: [:selector :met |
+ met isStatic ifTrue:[
+ result add: (PO forClass: met mclass selector: selector)
+ ].
+ ].
+ ] ifFalse:[
+ [ class notNil and:[(seen includes: class) not]] whileTrue: [
+ class selectorsAndMethodsDo: [:selector :met |
+ met isSynthetic ifFalse:[
+ (stripprefix isNil or:[ selector size > stripprefix size and:[selector startsWith: stripprefix]]) ifTrue:[
+ selector2classMap at: selector put: class.
+ ].
+ ]
+ ].
+ class := class superclass.
+ ]
+ ].
+ selector2classMap keysAndValuesDo:[:selector :class |
+ | classes |
+
+ classes := selector2classesMap at: selector ifAbsentPut: [ Set new ].
+ classes add: class.
+ ]
+ ].
+
+ selector2classesMap keysAndValuesDo: [:selector :classes|
+ result add:(MethodPO forClasses: classes selector: selector prefix: stripprefix)
+ ]
+
+ "Created: / 08-04-2014 / 21:23:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 20-05-2014 / 10:47:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
addPools
| class |
- class := inferencer klass theNonMetaclass.
+ class := collector klass theNonMetaclass.
class theNonMetaclass sharedPools do:[:pool|
pool theNonMetaclass classVarNames do:[:nm|
result add:(VariablePO classVariable: nm in: pool).
@@ -149,15 +296,16 @@
| class |
- class := inferencer klass theNonMetaclass.
+ class := collector klass theNonMetaclass.
class privateClassesDo:[:pclass|
| nm |
nm := pclass fullName copyFrom: class fullName size + 3.
- result add:(ClassPO new subject: pclass; name: nm).
+ result add:((PO forClass: pclass) name: nm).
]
"Created: / 06-08-2013 / 12:28:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 20-05-2014 / 10:00:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
addVariablesFor: node
@@ -165,11 +313,11 @@
| n klass |
"Add Instance variables"
- klass := inferencer klass.
+ klass := collector klass.
[ klass notNil ] whileTrue:[
| usedInstVars |
- usedInstVars := inferencer parser usedInstVars.
+ usedInstVars := collector parser usedInstVars.
klass instVarNames do:[:nm |
| po |
@@ -184,7 +332,7 @@
"/ When on class side (i.e., in class method), do not complete
"/ instance variables of Class / ClassDescription / Behaviour
"/ as STC won't compile such code.
- klass := (klass isMetaclass and:[klass superclass == Class])
+ klass := (klass isMetaclass and:[klass superclass == Class])
ifTrue:[nil]
ifFalse:[klass superclass].
].
@@ -193,16 +341,16 @@
result add: (VariablePO new name: nm).
].
"Add arguments"
- inferencer parser methodArgs ? #() do:[:nm|
+ collector parser methodArgs ? #() do:[:nm|
result add: (VariablePO argument: nm).
].
"Add temporaries"
- inferencer parser methodVars ? #() do:[:nm|
+ collector parser methodVars ? #() do:[:nm|
result add: (VariablePO variable: nm).
].
"Add literals"
#(#true #false #nil ) do:[:nm|
- result add: (SnippetPO new subject: nm).
+ result add: (SnippetPO new value: nm).
].
@@ -216,7 +364,7 @@
]
"Created: / 31-07-2013 / 00:32:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 22-01-2014 / 19:42:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 20-05-2014 / 10:09:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!SmalltalkCompletionEngine methodsFor:'completion-private'!
@@ -229,7 +377,7 @@
codeView := context codeView.
class := codeView isCodeView2
- ifTrue: [ codeView klass ]
+ ifTrue: [ codeView klass ]
ifFalse: [ codeView editedClass ].
class isNil ifTrue:[
class := UndefinedObject.
@@ -240,13 +388,13 @@
"Modified: / 21-01-2014 / 23:20:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
-complete: mode source: source class: class line: lineNrArg column: colNrArg
- | inf lineNr colNr |
+complete: mode source: source class: class line: lineNrArg column: colNrArg
+ | inferencer lineNr colNr |
mode == #method ifTrue:[
lineNr := lineNrArg.
colNr := colNrArg.
- inf := SmalltalkInferencer forClass: class methodSource: source asString.
+ inferencer := SmalltalkInferencer forClass: class methodSource: source asString.
] ifFalse:[
| line |
@@ -254,17 +402,18 @@
colNr := colNrArg.
line := codeView list at: lineNrArg ifAbsent:[ nil ].
line isEmptyOrNil ifTrue:[ ^ nil ].
- inf := SmalltalkInferencer forExpression: line.
+ inferencer := SmalltalkInferencer forExpression: line.
].
- inf parserClass: SmalltalkParser.
+ inferencer parserClass: SmalltalkParser.
+ inferencer process.
^ self
completeAtLine:lineNr
column:colNr
- inferencer:inf
+ collector:inferencer
"Created: / 02-10-2013 / 13:23:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 13-05-2014 / 12:29:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 07-10-2013 / 13:43:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
completeAfter:node
@@ -283,20 +432,17 @@
"Modified: / 24-09-2013 / 02:15:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
-completeAtLine:line column:col inferencer:inferencerArg
+completeAtLine:line column:col collector:coll
"find most possible codeCompletion object"
| nodeToPosition |
- inferencer := inferencerArg.
- inferencer process.
- (inferencer tree isNil or:[inferencer tree == #Error]) ifTrue:[
- ^ nil
+ collector := coll.
+ (collector tree isNil or:[collector tree == #Error]) ifTrue:[
+ ^ nil
].
- inferencer environment: context environment.
-
- nodeToPosition := SmalltalkParseNodeFinder new
- findNodeIn: inferencer source tree: inferencer tree comments: inferencer parser commentPositions
+ nodeToPosition := SmalltalkParseNodeFinder new
+ findNodeIn: collector source tree: collector tree comments: collector parser commentPositions
line: line column: col.
context node: nodeToPosition key position: nodeToPosition value.
@@ -315,7 +461,10 @@
].
^result.
- "Created: / 13-05-2014 / 12:29:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Created: / 04-03-2011 / 13:01:14 / Jakub <zelenja7@fel.cvut.cz>"
+ "Modified: / 08-04-2011 / 10:52:59 / Jakub <zelenja7@fel.cvut.cz>"
+ "Created: / 26-11-2011 / 17:05:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 29-01-2014 / 10:36:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
completeBefore:node
@@ -327,9 +476,9 @@
"Created: / 26-11-2011 / 17:07:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
-completeIn:node
+completeIn:node
"return collection which can be afterNode"
-
+
node isVariableNode ifTrue:[
self completeInVariableNode:node.
^ self.
@@ -346,7 +495,7 @@
"Modified: / 08-04-2014 / 20:52:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
-completeInMessageNode:node
+completeInMessageNode:node
| parent |
@@ -359,7 +508,7 @@
"Modified (format): / 08-04-2014 / 21:16:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
-completeInVariableNode:node
+completeInVariableNode:node
node name first isUppercase ifTrue:[
self addGlobalsStartingWith:node name.
self addClassVariables.
@@ -376,12 +525,12 @@
| i |
i := 0.
- [
+ [
i := aString indexOf: $: startingAt: i + 1.
- i ~~ 0
- ] whileTrue:[
- aString size > i ifTrue:[
- (aString at: i + 1) ~~ $: ifTrue:[
+ i ~~ 0
+ ] whileTrue:[
+ aString size > i ifTrue:[
+ (aString at: i + 1) ~~ $: ifTrue:[
^ true
].
].