SmallSense__JavaCompletionEngine.st
author Claus Gittinger <cg@exept.de>
Wed, 16 Aug 2017 20:25:20 +0200
branchcvs_MAIN
changeset 1048 d93abbb4a1f2
parent 910 2cf84854bedc
permissions -rw-r--r--
#BUGFIX by cg initial checkin class: SmallSense::GroovyEditSupport class added: #version_CVS

"
stx:goodies/smallsense - A productivity plugin for Smalltalk/X IDE
Copyright (C) 2013-2014 Jan Vrany

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License. 

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
"
"{ Package: 'stx:goodies/smallsense' }"

"{ NameSpace: SmallSense }"

AbstractJavaCompletionEngine subclass:#JavaCompletionEngine
	instanceVariableNames:'completionNode completionScope'
	classVariableNames:''
	poolDictionaries:''
	category:'SmallSense-Java'
!

!JavaCompletionEngine class methodsFor:'documentation'!

copyright
"
stx:goodies/smallsense - A productivity plugin for Smalltalk/X IDE
Copyright (C) 2013-2014 Jan Vrany

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License. 

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
"
! !

!JavaCompletionEngine methodsFor:'completion-individual'!

addFieldsForTypeBinding:binding
    | current |

    current := binding.        
    [ current notNil ] whileTrue:[  
        current fields do:[:fbinding | 
            result add: (PO forFieldBinding: fbinding )
        ].  
        current := current superclass.
    ].

    "Created: / 13-08-2014 / 21:39:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 14-08-2014 / 09:06:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

addMethodsForReceiver: maybeReceiverToken startingWith: prefix    
    ^ self addMethodsStartingWith: prefix

    "Created: / 03-10-2013 / 17:46:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

addMethodsForTypeBinding: binding
    | current seen |

    current := binding.        
    seen := Set new.
    [ current notNil ] whileTrue:[  
        current methods do:[:mbinding |
            mbinding isConstructor ifFalse:[
                | selector |

                selector := mbinding selector , mbinding signature.
                (seen includes: selector) ifFalse:[
                    result add: (PO forMethodBinding: mbinding).
                    seen add: selector.
                ].
            ].
        ].  
        current := current superclass.
    ].

    "Created: / 13-08-2014 / 21:39:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 13-08-2014 / 22:54:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

addVariablesInScope: scope
    |scopeKind org_eclipse_jdt_internal_compiler_lookup_Scope|

    scopeKind := scope kind.
    org_eclipse_jdt_internal_compiler_lookup_Scope := JAVA org eclipse jdt internal compiler lookup Scope.

    ((scopeKind == org_eclipse_jdt_internal_compiler_lookup_Scope METHOD_SCOPE) 
    or:[ scopeKind == org_eclipse_jdt_internal_compiler_lookup_Scope BLOCK_SCOPE]) ifTrue:[ 
        1 to: scope localIndex do:[:i | 
            result add: (PO forLocalVariableBinding: (scope locals at:i) ) 
        ].
        self addVariablesInScope: (scope instVarNamed: #parent). "/ !!?!! Why 'scope parent' does not work?
    ].

    scopeKind == org_eclipse_jdt_internal_compiler_lookup_Scope CLASS_SCOPE ifTrue:[ 
        | type |

        type := scope referenceType.
        type notNil ifTrue:[ 
            self addFieldsForTypeBinding: type binding.  
        ].
    ].

    "Created: / 12-08-2014 / 10:41:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 14-08-2014 / 09:08:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaCompletionEngine methodsFor:'completion-nodes'!

completeOnFieldType: node
    node type acceptCompletionEngine: self

    "Created: / 13-08-2014 / 21:04:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

completeOnQualifiedNameReference: node
    | binding |

    binding := node binding.
    (binding notNil and:[binding problemId ~~ JAVA org eclipse jdt internal compiler lookup ProblemReasons NoError]) ifTrue:[
        binding := binding type.
        binding notNil ifTrue:[ 
            self addMethodsForTypeBinding: binding.
            self addFieldsForTypeBinding: binding.  
        ].
    ].

    "Created: / 13-08-2014 / 21:32:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 14-08-2014 / 11:13:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

completeOnSingleNameReference: node
    self addVariablesInScope: completionScope.
    self addClassesStartingWith: node token.

    "Created: / 13-08-2014 / 21:05:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

completeOnSingleTypeReference: node
    self addClassesStartingWith: node token

    "Created: / 13-08-2014 / 21:05:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaCompletionEngine methodsFor:'completion-private'!

complete
    "use the eclipse framework (running in the stx java vm)
     to do java code completion"

    |position source stx_libjava_tools org_eclipse_jdt org_eclipse_jdt_internal_compiler 
     org_eclipse_jdt_internal_codeassist rslt problemReporter parser tree searcher resolver
     javaClass javaNamespace  |

    "/ cg: avoid prereq of libjava for smallsense
    javaNamespace := Smalltalk at:#JAVA.
    javaClass := Smalltalk at:#Java.

    position := context codeView characterPositionOfCursor.

    stx_libjava_tools := javaNamespace stx libjava tools.
    org_eclipse_jdt := javaNamespace org eclipse jdt.
    org_eclipse_jdt_internal_compiler := org_eclipse_jdt internal compiler.
    org_eclipse_jdt_internal_codeassist := org_eclipse_jdt internal codeassist.

    source := stx_libjava_tools Source new.

    source setContents: codeView list asStringWithoutEmphasis.
"/    parser := JAVA stx libjava tools parser Parser new.
    rslt := org_eclipse_jdt_internal_compiler CompilationResult
                new: source _: 1 _: 1 _: 1000.

    problemReporter := org_eclipse_jdt_internal_compiler problem ProblemReporter
                new: org_eclipse_jdt_internal_compiler DefaultErrorHandlingPolicies proceedWithAllProblems
                  _: stx_libjava_tools parser Parser defaultCompilerOptions   
                  _: stx_libjava_tools parser Parser defaultProblemFactory.

    parser := org_eclipse_jdt_internal_codeassist complete CompletionParser 
                new: problemReporter _: true.

"/    tree := parser parse: source diet: true resolve: true.
    tree := parser dietParse: source _: rslt _: position - 1"Java is 0-based" - 1"cursor is actualy one fter the end of token".
    searcher := org_eclipse_jdt core dom NodeSearcher new: position - 1"Java is 0-based" - 1"cursor is actualy one fter the end of token".
    tree traverse: searcher _: tree scope.
    (searcher found notNil and:[searcher found isKindOf: org_eclipse_jdt_internal_compiler ast AbstractMethodDeclaration]) ifTrue:[ 
        parser parseBlockStatements: searcher found _: tree.
    ].

    "
    (SmallSense::ParseTreeInspector new node:tree source: codeView list asString) open
    "

    resolver := (javaClass classForName: 'stx.libjava.tools.environment.Resolver') new: problemReporter.
    [ 
        resolver resolve: tree.
    ] on: org_eclipse_jdt_internal_codeassist complete CompletionNodeFound do:[:ex |  
        completionNode := ex astNode.
        completionScope := ex scope.
    ].

    context node: completionNode position: position.

    (completionNode isNil or:[completionScope isNil]) ifTrue:[
        result := JavaCompletionEngineSimple new complete: context.
    ] ifFalse:[
        completionNode acceptCompletionEngine: self.
    ].

    ^ result

    "Created: / 02-10-2013 / 13:55:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 13-08-2014 / 21:08:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!JavaCompletionEngine class methodsFor:'documentation'!

version
    ^ '$Header$'
!

version_CVS
    ^ '$Header$'
! !