ClassDefinitionChange.st
author Claus Gittinger <cg@exept.de>
Thu, 07 Jul 2011 14:40:50 +0200
changeset 2425 b0011db09dfe
parent 2410 b09cc8e12790
child 2504 c0f78584ae54
permissions -rw-r--r--
changed: #apply

"
 COPYRIGHT (c) 1993 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
"{ Package: 'stx:libbasic3' }"

ClassChange subclass:#ClassDefinitionChange
	instanceVariableNames:'objectType superClassName classType indexedType otherParameters
		instanceVariableNames classVariableNames
		classInstanceVariableNames poolDictionaries category private
		definitionSelector owningClassName'
	classVariableNames:''
	poolDictionaries:''
	category:'System-Changes'
!

!ClassDefinitionChange class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1993 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

documentation
"
    instances represent class definition-changes. 
    They are typically held in a ChangeSet.

    [author:]
        Claus Gittinger
"
! !

!ClassDefinitionChange methodsFor:'accessing'!

basicSuperClassName 
    ^ superClassName
!

category
    category isNil ifTrue:[
        self setupFromSource.
    ].
    ^ category

    "Modified: / 11-10-2006 / 14:12:01 / cg"
!

category:something
    category := something.
!

classInstanceVariableNames
    ^ classInstanceVariableNames
!

classInstanceVariableNames:something
    classInstanceVariableNames := something.
!

classVariableNames
    ^ classVariableNames
!

classVariableNames:something
    classVariableNames := something.
!

delta

    | class |
    class := self changeClass.
    class ifNil:[^#+].
    ^(self class isSource: self source sameSourceAs: class definition)
        ifTrue:[#=]
        ifFalse:[#~]
!

instanceVariableNames
    ^ instanceVariableNames
!

instanceVariableNames:something
    instanceVariableNames := something.
!

nameSpaceName
    objectType == #variable ifTrue:[
        ^ nil
    ].
    ^ self cutNameSpaceOf:(nameSpaceOverride ? super nameSpaceName)

    "Modified: / 15-06-2010 / 14:50:27 / cg"
!

nameSpaceName: aNameSpaceName classType: aClassType otherParameters:otherParametersArg
    "this instance setup message is used when reading from a VW-xml change file.
     Support for this is not yet complete."

    |indexedType imports|

    nameSpaceOverride := aNameSpaceName.
    classType := aClassType.
    otherParameters := Dictionary new addAll:otherParametersArg; yourself.

    superClassName := otherParameters at:#superclass: ifAbsent:nil.
    superClassName notNil ifTrue:[
        superClassName := superClassName pathString.
    ].
    indexedType := otherParameters at:#indexedType: ifAbsent:nil.
    private := otherParameters at:#private: ifAbsent:nil.
    instanceVariableNames := otherParameters at:#instanceVariableNames: ifAbsent:nil.
    classInstanceVariableNames := otherParameters at:#classInstanceVariableNames: ifAbsent:nil.
    imports := otherParameters at:#imports: ifAbsent:nil.
    category := otherParameters at:#category: ifAbsent:nil.

    "Modified: / 15-06-2010 / 14:50:35 / cg"
!

objectType
    "return the value of the instance variable 'objectType' (automatically generated)"

    ^ objectType
!

objectType:something
    "set the value of the instance variable 'objectType' (automatically generated)"

    objectType := something.
!

package:aPackageID
    package := aPackageID
!

poolDictionaries
    ^ poolDictionaries
!

poolDictionaries:something
    poolDictionaries := something.
!

private:aBoolean
    private := aBoolean.

    "Created: / 30-08-2010 / 13:56:11 / cg"
!

source
    "return the source of the change"

    |src|

    (src := source) isNil ifTrue:[
        src := self definitionString
    ].

    nameSpaceOverride notNil ifTrue:[
        (className startsWith:(nameSpaceOverride,'::')) ifFalse:[
            ^ '"{ NameSpace: ' , nameSpaceOverride , ' }"' , 
                Character cr, Character cr , 
                src string
        ].
    ].
    ^ src

    "Modified: / 15-06-2010 / 14:51:09 / cg"
!

superClassName 
    |nm|

    nm := superClassName.
    nm notNil ifTrue:[
        (nm includes:$.) ifTrue:[
            ^ nm copyReplaceAll:$. withAll:'::'.
        ]
    ].
    ^ nm
!

superClassName:something
    superClassName := something.
    self invalidateSource.
!

superClassNameWithoutMyNamespace
    |nm|

    superClassName isNil ifTrue:[^ 'nil'].

    nm := self cutMyNameSpaceOf:superClassName.
    (nm includes:$.) ifTrue:[
        ^ nm copyReplaceAll:$. withAll:'::'.
    ].
    ^ nm

    "Modified: / 03-03-2007 / 13:09:07 / cg"
!

superClassNameWithoutNamespace
    |nm|

    nm := self cutNameSpaceOf:superClassName.
    (nm includes:$.) ifTrue:[
        ^ nm copyReplaceAll:$. withAll:'::'.
    ].
    ^ nm
! !

!ClassDefinitionChange methodsFor:'applying'!

apply
    superClassName isNil ifTrue:[
        self setupFromSource
    ].
    superClassName isNil ifTrue:[
        self error:'Should not happen'
    ].
    (Smalltalk classNamed:superClassName) isNil ifTrue:[
        Class undeclared:superClassName
    ].
    Parser evaluate:(self source).
    package notNil ifTrue:[
        self changeClass setPackage:package.
    ].

    "
      (ClassDefinitionChange className: #TestB source: 'TestA subclass: #TestB
          instanceVariableNames:''''
          classVariableNames:''''
          poolDictionaries:''''
          category:''* remove me *''')
          apply
    "

    "Modified: / 08-11-2010 / 16:10:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (comment): / 07-07-2011 / 14:40:44 / cg"
! !

!ClassDefinitionChange methodsFor:'comparing'!

isForSameAs:changeB
    "return true, if the given change represents a change for the same
     thingy as the receiver (i.e. same method, same definition etc.)."

    changeB isClassDefinitionChange ifFalse:[^ false].   

    className ~= changeB className ifTrue:[^ false].
    ^ true





!

sameAs:changeB
    "return true, if the given change represents the same change as the receiver."

    (self isForSameAs:changeB) ifFalse:[^ false].
    ^ self sameSourceAs:changeB



! !

!ClassDefinitionChange methodsFor:'converting'!

asAntiChange

    ^ClassRemoveChange className: self className

    "Created: / 02-11-2009 / 11:11:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!ClassDefinitionChange methodsFor:'printing & storing'!

definitionString
    objectType == #variable ifTrue:[
        ^ String streamContents:[:stream |
            nameSpaceOverride notNil ifTrue:[
                stream 
                    nextPutAll:((nameSpaceOverride asCollectionOfSubstringsSeparatedBy:$.) asStringWith:'::')
            ] ifFalse:[
                self halt:'can this happen ?'.
                stream 
                    nextPutAll:'Smalltalk'
            ].

            stream 
                nextPutAll:' addClassVarName:';
                nextPutAll:className asString storeString
          ].
    ].

    ^ String streamContents:[:stream |
        stream 
            nextPutAll:self superClassNameWithoutMyNamespace;
            nextPutAll:' subclass:';
            nextPutAll: self classNameWithoutNamespace asSymbol storeString
            ;
            cr;
            spaces:4;
            nextPutAll:'instanceVariableNames: ';
            nextPutAll:(instanceVariableNames ? '') storeString;
            cr;
            spaces:4;
            nextPutAll:'classVariableNames: ';
            nextPutAll:(classVariableNames ? '') storeString;
            cr;
            spaces:4;
            nextPutAll:'poolDictionaries: ';
            nextPutAll:(poolDictionaries ? '') storeString;
            cr;
            spaces:4;
            nextPutAll:'category: ';
            nextPutAll:(category ? '') storeString
      ]

    "Modified: / 15-06-2010 / 14:53:57 / cg"
!

printOn:aStream
    aStream 
        nextPutAll:className; nextPutAll:' {definition}'

    "Modified: / 12-10-2006 / 17:48:28 / cg"
!

printWithoutClassNameOn:aStream
    aStream nextPutAll:('definition of ' , className)


! !

!ClassDefinitionChange methodsFor:'queries'!

definitionSelector
    definitionSelector isNil ifTrue:[
        self setupFromSource.
    ].
    ^ definitionSelector

    "Modified: / 11-10-2006 / 14:11:44 / cg"
!

isClassDefinitionChange
    ^ true
!

isPrivateClassDefinitionChange
    private isNil ifTrue:[
        (className includes:$:) ifFalse:[
            "/ cannot be private
            private := false
        ] ifTrue:[
            source isNil ifTrue:[^ false ].
            (source includesString:'private') ifFalse:[
                private := false.
            ] ifTrue:[
"/                (self changeClass notNil
"/                and:[self changeClass isLoaded not]) ifTrue:[
"/                    "/ cannot be private
"/                    private := false
"/                ] ifTrue:[
                    self setupFromSource.
"/                ].
            ].
        ].
    ].
    ^ private

    "Created: / 11-10-2006 / 14:19:03 / cg"
    "Modified: / 16-11-2006 / 16:34:19 / cg"
!

owningClassName
    self isPrivateClassDefinitionChange ifTrue:[
        owningClassName isNil ifTrue:[
            self setupFromSource.
        ].
    ].
    ^ owningClassName

    "Created: / 12-10-2006 / 23:07:25 / cg"
!

owningClassName:aStringOrSymbol
    owningClassName := aStringOrSymbol

    "Created: / 30-08-2010 / 13:55:37 / cg"
! !

!ClassDefinitionChange methodsFor:'special'!

installAsAutoloadedClassIfPublicWithFilename:aFilenameString
    "install the class defined by this change as autoloaded.
     Skip private classes.
     Enter class file name as abbreviation"

    |parseTree sel cat clsName cls catIdx pkg|

    private == true ifTrue:[^ self].

    parseTree := Parser parseExpression:self source.
    parseTree isMessage ifFalse:[
        self error:'bad change source'.
    ].

    sel := parseTree selector.
    (sel endsWith:':privateIn:') ifTrue:[^ self].

    catIdx := sel asSymbol keywords indexOf:'category:'.  
    catIdx ~~ 0 ifTrue:[
        cat := (parseTree args at:catIdx) evaluate.
    ].

    clsName := self className asSymbol.
    cls := Smalltalk at:clsName.

    pkg := package ? Project current package.   

    (cls isNil 
     or:[cls isBehavior not
     or:[cls isLoaded not]]) ifTrue:[
        |autoloadedClass|

        autoloadedClass := Smalltalk 
           installAutoloadedClassNamed:clsName 
           category:cat 
           package:pkg 
           revision:nil.
        aFilenameString notNil ifTrue:[
            autoloadedClass setClassFilename:aFilenameString.
            "/ Smalltalk setFilename:aFilenameString forClass:clsName package:pkg.
        ]
    ] ifFalse:[
        cls notNil ifTrue:[
            cls isBehavior ifTrue:[
                cls package ~= pkg ifTrue:[
Transcript showCR:('Autoloaded class: %1 not installed (package would change from %2 to %3)' 
                        bindWith:clsName with:cls package with:pkg).
                ]
            ].
        ].
    ].

    "Modified: / 03-07-2011 / 18:34:05 / cg"
!

invalidateSource
    "internal - flush the sourceString if it got invalidated due to a
     className, superclassName, etc... change"

    source := nil.
!

setupFromSource
    "extract privacy, category and selector from the source"

    |parseTree catIdx|

    source notNil ifTrue:[
        parseTree := Parser parseExpression:source.
        (parseTree notNil and:[parseTree isMessage]) ifFalse:[
            self error:'bad change source' mayProceed:true.
            ^ self
        ].

        definitionSelector := parseTree selector.

        private := (definitionSelector endsWith:':privateIn:').
        private ifTrue:[
            owningClassName := parseTree args last name.
        ].

        catIdx := definitionSelector keywords indexOf:'category:'.  
        catIdx ~~ 0 ifTrue:[
            category := (parseTree args at:catIdx) evaluate.
        ].

        superClassName := parseTree receiver name.
    ].

    "Created: / 11-10-2006 / 14:10:02 / cg"
    "Modified: / 26-10-2006 / 19:29:17 / cg"
    "Modified: / 08-11-2010 / 13:47:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!ClassDefinitionChange class methodsFor:'documentation'!

version_CVS
    ^ '$Header: /cvs/stx/stx/libbasic3/ClassDefinitionChange.st,v 1.59 2011-07-07 12:40:50 cg Exp $'
!

version_SVN
    ^ '§ Id: ClassDefinitionChange.st 1867 2011-06-08 21:57:08Z vranyj1  §'
! !