828 start:something |
846 start:something |
829 "set the value of the instance variable 'start' (automatically generated)" |
847 "set the value of the instance variable 'start' (automatically generated)" |
830 |
848 |
831 start := something.! ! |
849 start := something.! ! |
832 |
850 |
833 !SnapShotImageMemory::ImageObject methodsFor:'object protocol'! |
851 !SnapShotImageMemory::ImageObject methodsFor:'method protocol'! |
834 |
852 |
835 at:aSelector ifAbsent:exceptionValue |
853 byteCode |
836 |symPtr symRef mthdPtr mthdRef s| |
854 |byteCodeSlotOffset byteCodePtr byteCodeRef byteCode| |
837 |
855 |
838 self isMethodDictionary ifTrue:[ |
856 self isMethod ifTrue:[ |
839 1 to:self size by:2 do:[:idx | |
857 byteCodeSlotOffset := Method instVarOffsetOf:'byteCode'. |
840 symPtr := self at:idx. |
858 ]. |
841 symRef := memory fetchObjectAt:symPtr. |
859 byteCodeSlotOffset notNil ifTrue:[ |
842 symRef isImageSymbol ifFalse:[self halt]. |
860 byteCodePtr := self at:byteCodeSlotOffset. |
843 s := memory fetchStringFor:symRef. |
861 byteCodeRef := memory fetchObjectAt:byteCodePtr. |
844 mthdPtr := self at:idx + 1. |
862 byteCodeRef isNil ifTrue:[^ nil]. |
845 mthdRef := memory fetchObjectAt:mthdPtr. |
863 |
846 ^ mthdRef. |
864 byteCode := memory fetchByteArrayFor:byteCodeRef. |
847 ]. |
865 ^ byteCode |
848 ]. |
866 ]. |
849 ^ exceptionValue value |
867 |
850 ! |
868 self halt. |
851 |
869 ! |
852 do:aBlock |
870 |
853 |mthdPtr mthdRef| |
871 comment |
854 |
872 |src comment comments parser| |
855 self isMethodDictionary ifTrue:[ |
873 |
856 2 to:self size by:2 do:[:idx | |
874 self isMethod ifTrue:[ |
857 mthdPtr := self at:idx. |
875 src := self source. |
858 mthdRef := memory fetchObjectAt:mthdPtr. |
876 src isNil ifTrue:[^ nil]. |
859 aBlock value:mthdRef. |
877 |
860 ]. |
878 parser := Parser for:src in:nil. |
861 ]. |
879 parser ignoreErrors; ignoreWarnings; saveComments:true. |
862 ! |
880 parser parseMethodSpec. |
|
881 comments := parser comments. |
|
882 comments size ~~ 0 ifTrue:[ |
|
883 comment := comments first string. |
|
884 (comment withoutSpaces endsWith:'}') ifTrue:[ |
|
885 "if first comment is a pragma, take next comment" |
|
886 comment := comments at:2 ifAbsent:nil. |
|
887 comment notNil ifTrue:[ |
|
888 comment := comment string. |
|
889 ]. |
|
890 ]. |
|
891 ]. |
|
892 ^ comment. |
|
893 ]. |
|
894 self isLazyMethod ifTrue:[ |
|
895 ^ '' |
|
896 ]. |
|
897 |
|
898 self halt. |
|
899 ! |
|
900 |
|
901 containingClass |
|
902 self isMethodOrLazyMethod ifTrue:[ |
|
903 ^ self mclass |
|
904 ]. |
|
905 self halt.! |
|
906 |
|
907 hasCode |
|
908 ^ false! |
|
909 |
|
910 isBreakpointed |
|
911 ^ false! |
|
912 |
|
913 isCounting |
|
914 ^ false! |
|
915 |
|
916 isCountingMemoryUsage |
|
917 ^ false! |
|
918 |
|
919 isDynamic |
|
920 ^ false! |
|
921 |
|
922 isExecutable |
|
923 self isMethod ifTrue:[ |
|
924 ^ false |
|
925 ]. |
|
926 self halt.! |
|
927 |
|
928 isIgnored |
|
929 ^ false! |
|
930 |
|
931 isJavaMethod |
|
932 ^ self class name = 'JavaMethod'! |
|
933 |
|
934 isPrivate |
|
935 ^ false! |
|
936 |
|
937 isProtected |
|
938 ^ false! |
|
939 |
|
940 isPublic |
|
941 ^ true! |
|
942 |
|
943 isTimed |
|
944 ^ false! |
|
945 |
|
946 isTraced |
|
947 ^ false! |
863 |
948 |
864 isWrapped |
949 isWrapped |
865 ^ false |
950 ^ false |
866 ! |
951 ! |
867 |
952 |
868 keysAndValuesDo:aBlock |
953 mclass |
869 |symPtr symRef mthdPtr mthdRef s| |
954 |mclassSlotOffset mclassPtr mclass| |
870 |
955 |
871 self isMethodDictionary ifTrue:[ |
956 self isMethod ifTrue:[ |
872 1 to:self size by:2 do:[:idx | |
957 mclassSlotOffset := Method instVarOffsetOf:'mclass'. |
873 symPtr := self at:idx. |
958 mclassPtr := self at:mclassSlotOffset. |
874 symRef := memory fetchObjectAt:symPtr. |
959 mclassPtr ~~ 0 ifTrue:[ |
875 symRef isImageSymbol ifFalse:[self halt]. |
960 mclass := memory fetchObjectAt:mclassPtr. |
876 s := memory fetchStringFor:symRef. |
961 mclass isImageBehavior ifFalse:[ |
877 mthdPtr := self at:idx + 1. |
962 self halt |
878 mthdRef := memory fetchObjectAt:mthdPtr. |
963 ]. |
879 aBlock value:s asSymbol value:mthdRef. |
964 ^ mclass |
880 ]. |
965 ]. |
881 ]. |
966 |
882 ! |
967 "/ search my class ... |
|
968 memory image allClassesDo:[:eachClass | |
|
969 eachClass theNonMetaclass methodDictionary keysAndValuesDo:[:sel :mthdRef | |
|
970 mthdRef == self ifTrue:[ |
|
971 self at:mclassSlotOffset put:eachClass theNonMetaclass. |
|
972 ^ eachClass theNonMetaclass |
|
973 ]. |
|
974 ]. |
|
975 eachClass theMetaclass methodDictionary keysAndValuesDo:[:sel :mthdRef | |
|
976 mthdRef == self ifTrue:[ |
|
977 self at:mclassSlotOffset put:eachClass theMetaclass. |
|
978 ^ eachClass theMetaclass |
|
979 ]. |
|
980 ] |
|
981 ]. |
|
982 self halt. |
|
983 ]. |
|
984 self halt. |
|
985 ! |
|
986 |
|
987 numArgs |
|
988 |flagsSlotOffset flagsPtr flags| |
|
989 |
|
990 self isMethod ifTrue:[ |
|
991 flagsSlotOffset := Method instVarOffsetOf:'flags'. |
|
992 ]. |
|
993 flagsSlotOffset notNil ifTrue:[ |
|
994 flagsPtr := self at:flagsSlotOffset. |
|
995 flags := memory fetchObjectAt:flagsPtr. |
|
996 ^ (flags bitAnd:(Method numArgsMaskInFlags)) bitShift:(Method numArgsShiftInFlags negated) |
|
997 ]. |
|
998 |
|
999 self halt. |
|
1000 ! |
|
1001 |
|
1002 package |
|
1003 |packageSlotOffset packagePtr packageRef package| |
|
1004 |
|
1005 self isImageBehavior ifTrue:[ |
|
1006 self isMeta ifTrue:[ |
|
1007 ^ self theNonMetaclass package |
|
1008 ]. |
|
1009 packageSlotOffset := Class instVarOffsetOf:'package'. |
|
1010 ]. |
|
1011 self isMethod ifTrue:[ |
|
1012 packageSlotOffset := Method instVarOffsetOf:'package'. |
|
1013 ]. |
|
1014 packageSlotOffset notNil ifTrue:[ |
|
1015 packagePtr := self at:packageSlotOffset. |
|
1016 packageRef := memory fetchObjectAt:packagePtr. |
|
1017 packageRef isNil ifTrue:[^ nil]. |
|
1018 |
|
1019 packageRef isImageSymbol ifFalse:[ |
|
1020 self halt. |
|
1021 ]. |
|
1022 package := memory fetchStringFor:packageRef. |
|
1023 ^ package asSymbol |
|
1024 ]. |
|
1025 self isMeta ifTrue:[ |
|
1026 self halt |
|
1027 ]. |
|
1028 |
|
1029 self halt. |
|
1030 ! |
|
1031 |
|
1032 previousVersion |
|
1033 ^ nil! |
883 |
1034 |
884 printStringForBrowserWithSelector:selector |
1035 printStringForBrowserWithSelector:selector |
885 ^ selector |
1036 ^ selector |
886 ! |
1037 ! |
887 |
1038 |
|
1039 privacy |
|
1040 ^ #public! |
|
1041 |
888 resources |
1042 resources |
889 ^ nil |
1043 ^ nil |
890 ! |
1044 ! |
891 |
1045 |
892 source |
1046 source |
893 |sourcePosition source aStream junk| |
1047 |sourcePosition sourcePositionPtr sourcePtr sourceRef source aStream junk| |
894 |
1048 |
895 self isMethod ifTrue:[ |
1049 self isMethodOrLazyMethod ifTrue:[ |
896 sourcePosition := self at:(Method instVarOffsetOf:'sourcePosition'). |
1050 sourcePositionPtr := self at:(Method instVarOffsetOf:'sourcePosition'). |
897 source := self at:(Method instVarOffsetOf:'source'). |
1051 sourcePtr := self at:(Method instVarOffsetOf:'source'). |
898 source := memory fetchObjectAt:source. |
1052 sourceRef := memory fetchObjectAt:sourcePtr. |
899 source isString ifFalse:[ |
1053 sourceRef isString ifFalse:[ |
900 self halt. |
1054 self halt. |
901 ]. |
1055 ]. |
902 source := memory printStringOfString:source. |
1056 source := memory printStringOfString:sourceRef. |
|
1057 sourcePosition := memory fetchObjectAt:sourcePositionPtr. |
903 sourcePosition isNil ifTrue:[ |
1058 sourcePosition isNil ifTrue:[ |
904 self halt. |
|
905 ^ source |
1059 ^ source |
906 ]. |
1060 ]. |
907 sourcePosition := memory fetchObjectAt:sourcePosition. |
|
908 |
1061 |
909 aStream := self sourceStream. |
1062 aStream := self sourceStream. |
910 aStream notNil ifTrue:[ |
1063 aStream notNil ifTrue:[ |
911 Stream positionErrorSignal handle:[:ex | |
1064 Stream positionErrorSignal handle:[:ex | |
912 ^ nil |
1065 ^ nil |
1424 |
1889 |
1425 evaluatorClass |
1890 evaluatorClass |
1426 ^ Object evaluatorClass |
1891 ^ Object evaluatorClass |
1427 ! |
1892 ! |
1428 |
1893 |
|
1894 fileOut |
|
1895 |baseName dirName nm fileName| |
|
1896 |
|
1897 baseName := (Smalltalk fileNameForClass:self name). |
|
1898 nm := baseName asFilename withSuffix:'st'. |
|
1899 |
|
1900 " |
|
1901 this test allows a smalltalk to be built without Projects/ChangeSets |
|
1902 " |
|
1903 Project notNil ifTrue:[ |
|
1904 dirName := Project currentProjectDirectory |
|
1905 ] ifFalse:[ |
|
1906 dirName := Filename currentDirectory |
|
1907 ]. |
|
1908 fileName := (dirName asFilename construct:nm). |
|
1909 fileName makeLegalFilename. |
|
1910 |
|
1911 self fileOutAs:fileName name. |
|
1912 |
|
1913 "/ " |
|
1914 "/ add a change record; that way, administration is much easier, |
|
1915 "/ since we can see in that changeBrowser, which changes have |
|
1916 "/ already found their way into a sourceFile and which must be |
|
1917 "/ applied again |
|
1918 "/ " |
|
1919 "/ self addChangeRecordForClassFileOut:self |
|
1920 |
|
1921 "Modified: / 7.6.1996 / 09:14:43 / stefan" |
|
1922 "Modified: / 27.8.1998 / 02:02:57 / cg"! |
|
1923 |
|
1924 fileOutAllDefinitionsOn:aStream |
|
1925 "append expressions on aStream, which defines myself and all of my private classes." |
|
1926 |
|
1927 self fileOutDefinitionOn:aStream. |
|
1928 aStream nextPutChunkSeparator. |
|
1929 aStream cr; cr. |
|
1930 |
|
1931 "/ |
|
1932 "/ optional classInstanceVariables |
|
1933 "/ |
|
1934 self classRef instanceVariableString isBlank ifFalse:[ |
|
1935 self fileOutClassInstVarDefinitionOn:aStream. |
|
1936 aStream nextPutChunkSeparator. |
|
1937 aStream cr; cr |
|
1938 ]. |
|
1939 |
|
1940 "/ here, the full nameSpace prefixes are output, |
|
1941 "/ to avoid confusing stc |
|
1942 "/ (which otherwise could not find the correct superclass) |
|
1943 "/ |
|
1944 Class fileOutNameSpaceQuerySignal answer:true do:[ |
|
1945 self privateClassesSorted do:[:aClass | |
|
1946 aClass fileOutAllDefinitionsOn:aStream |
|
1947 ] |
|
1948 ]. |
|
1949 |
|
1950 "Created: 15.10.1996 / 11:15:19 / cg" |
|
1951 "Modified: 22.3.1997 / 16:11:56 / cg"! |
|
1952 |
|
1953 fileOutAs:fileNameString |
|
1954 "create a file consisting of all methods in myself in |
|
1955 sourceForm, from which the class can be reconstructed (by filing in). |
|
1956 The given fileName should be a full path, including suffix. |
|
1957 Care is taken, to not clobber any existing file in |
|
1958 case of errors (for example: disk full). |
|
1959 Also, since the classes methods need a valid sourcefile, the current |
|
1960 sourceFile may not be rewritten." |
|
1961 |
|
1962 |aStream fileName newFileName savFilename needRename |
|
1963 mySourceFileName sameFile s mySourceFileID anySourceRef| |
|
1964 |
|
1965 self isLoaded ifFalse:[ |
|
1966 ^ Class fileOutErrorSignal |
|
1967 raiseRequestWith:self |
|
1968 errorString:'will not fileOut unloaded classes' |
|
1969 ]. |
|
1970 |
|
1971 fileName := fileNameString asFilename. |
|
1972 |
|
1973 " |
|
1974 if file exists, copy the existing to a .sav-file, |
|
1975 create the new file as XXX.new-file, |
|
1976 and, if that worked rename afterwards ... |
|
1977 " |
|
1978 (fileName exists) ifTrue:[ |
|
1979 sameFile := false. |
|
1980 |
|
1981 "/ check carefully - maybe, my source does not really come from that |
|
1982 "/ file (i.e. all of my methods have their source as string) |
|
1983 |
|
1984 anySourceRef := false. |
|
1985 self methodDictionary do:[:m| |
|
1986 m sourcePosition notNil ifTrue:[ |
|
1987 anySourceRef := true |
|
1988 ] |
|
1989 ]. |
|
1990 self classRef methodDictionary do:[:m| |
|
1991 m sourcePosition notNil ifTrue:[ |
|
1992 anySourceRef := true |
|
1993 ] |
|
1994 ]. |
|
1995 |
|
1996 anySourceRef ifTrue:[ |
|
1997 s := self sourceStream. |
|
1998 s notNil ifTrue:[ |
|
1999 mySourceFileID := s pathName asFilename info id. |
|
2000 sameFile := (fileName info id) == mySourceFileID. |
|
2001 s close. |
|
2002 ] ifFalse:[ |
|
2003 self classFilename notNil ifTrue:[ |
|
2004 " |
|
2005 check for overwriting my current source file |
|
2006 this is not allowed, since it would clobber my methods source |
|
2007 file ... you have to save it to some other place. |
|
2008 This happens if you ask for a fileOut into the source-directory |
|
2009 (from which my methods get their source) |
|
2010 " |
|
2011 mySourceFileName := Smalltalk getSourceFileName:self classFilename. |
|
2012 sameFile := (fileNameString = mySourceFileName). |
|
2013 sameFile ifFalse:[ |
|
2014 mySourceFileName notNil ifTrue:[ |
|
2015 sameFile := (fileName info id) == (mySourceFileName asFilename info id) |
|
2016 ] |
|
2017 ]. |
|
2018 ] |
|
2019 ]. |
|
2020 ]. |
|
2021 |
|
2022 sameFile ifTrue:[ |
|
2023 ^ Class fileOutErrorSignal |
|
2024 raiseRequestWith:fileNameString |
|
2025 errorString:('may not overwrite sourcefile:', fileNameString) |
|
2026 ]. |
|
2027 |
|
2028 savFilename := Filename newTemporary. |
|
2029 fileName copyTo:savFilename. |
|
2030 newFileName := fileName withSuffix:'new'. |
|
2031 needRename := true |
|
2032 ] ifFalse:[ |
|
2033 "/ another possible trap: if my sourceFileName is |
|
2034 "/ the same as the written one AND the new files directory |
|
2035 "/ is along the sourcePath, we also need a temporary file |
|
2036 "/ first, to avoid accessing the newly written file. |
|
2037 |
|
2038 anySourceRef := false. |
|
2039 self methodDictionary do:[:m| |
|
2040 |mSrc| |
|
2041 |
|
2042 (mSrc := m sourceFilename) notNil ifTrue:[ |
|
2043 mSrc asFilename baseName = fileName baseName ifTrue:[ |
|
2044 anySourceRef := true |
|
2045 ] |
|
2046 ] |
|
2047 ]. |
|
2048 self classRef methodDictionary do:[:m| |
|
2049 |mSrc| |
|
2050 |
|
2051 (mSrc := m sourceFilename) notNil ifTrue:[ |
|
2052 mSrc asFilename baseName = fileName baseName ifTrue:[ |
|
2053 anySourceRef := true |
|
2054 ] |
|
2055 ] |
|
2056 ]. |
|
2057 anySourceRef ifTrue:[ |
|
2058 newFileName := fileName withSuffix:'new'. |
|
2059 needRename := true |
|
2060 ] ifFalse:[ |
|
2061 newFileName := fileName. |
|
2062 needRename := false |
|
2063 ] |
|
2064 ]. |
|
2065 |
|
2066 aStream := newFileName writeStream. |
|
2067 aStream isNil ifTrue:[ |
|
2068 savFilename notNil ifTrue:[ |
|
2069 savFilename delete |
|
2070 ]. |
|
2071 ^ Class fileOutErrorSignal |
|
2072 raiseRequestWith:newFileName |
|
2073 errorString:('cannot create file:', newFileName name) |
|
2074 ]. |
|
2075 self fileOutOn:aStream. |
|
2076 aStream close. |
|
2077 |
|
2078 " |
|
2079 finally, replace the old-file |
|
2080 be careful, if the old one is a symbolic link; in this case, |
|
2081 we have to do a copy ... |
|
2082 " |
|
2083 needRename ifTrue:[ |
|
2084 newFileName copyTo:fileName. |
|
2085 newFileName delete |
|
2086 ]. |
|
2087 savFilename notNil ifTrue:[ |
|
2088 savFilename delete |
|
2089 ]. |
|
2090 |
|
2091 " |
|
2092 add a change record; that way, administration is much easier, |
|
2093 since we can see in that changeBrowser, which changes have |
|
2094 already found their way into a sourceFile and which must be |
|
2095 applied again |
|
2096 " |
|
2097 self addChangeRecordForClassFileOut:self |
|
2098 |
|
2099 "Modified: / 7.6.1996 / 09:14:43 / stefan" |
|
2100 "Created: / 16.4.1997 / 20:44:05 / cg" |
|
2101 "Modified: / 12.8.1998 / 11:14:56 / cg"! |
|
2102 |
|
2103 fileOutCategory:aCategory |
|
2104 "create a file 'class-category.st' consisting of all methods in aCategory. |
|
2105 If the current project is not nil, create the file in the projects |
|
2106 directory." |
|
2107 |
|
2108 |aStream fileName| |
|
2109 |
|
2110 fileName := (self name , '-' , aCategory , '.st') asFilename. |
|
2111 fileName makeLegalFilename. |
|
2112 |
|
2113 "/ |
|
2114 "/ this test allows a smalltalk to be built without Projects/ChangeSets |
|
2115 "/ |
|
2116 Project notNil ifTrue:[ |
|
2117 fileName := Project currentProjectDirectory asFilename construct:(fileName name). |
|
2118 ]. |
|
2119 |
|
2120 "/ |
|
2121 "/ if the file exists, save original in a .sav file |
|
2122 "/ |
|
2123 fileName exists ifTrue:[ |
|
2124 fileName copyTo:(fileName withSuffix:'sav') |
|
2125 ]. |
|
2126 aStream := FileStream newFileNamed:fileName. |
|
2127 aStream isNil ifTrue:[ |
|
2128 ^ Class fileOutErrorSignal |
|
2129 raiseRequestWith:fileName |
|
2130 errorString:('cannot create file:', fileName pathName) |
|
2131 ]. |
|
2132 |
|
2133 self fileOutCategory:aCategory on:aStream. |
|
2134 aStream close |
|
2135 |
|
2136 "Modified: / 1.4.1997 / 16:00:24 / stefan" |
|
2137 "Created: / 1.4.1997 / 16:04:18 / stefan" |
|
2138 "Modified: / 28.10.1997 / 14:40:28 / cg"! |
|
2139 |
|
2140 fileOutCategory:aCategory except:skippedMethods only:savedMethods methodFilter:methodFilter on:aStream |
|
2141 |dict source sortedSelectors first privacy interestingMethods cat| |
|
2142 |
|
2143 dict := self methodDictionary. |
|
2144 dict notNil ifTrue:[ |
|
2145 interestingMethods := OrderedCollection new. |
|
2146 dict do:[:aMethod | |
|
2147 |wanted| |
|
2148 |
|
2149 (methodFilter isNil |
|
2150 or:[methodFilter value:aMethod]) ifTrue:[ |
|
2151 (aCategory = aMethod category) ifTrue:[ |
|
2152 skippedMethods notNil ifTrue:[ |
|
2153 wanted := (skippedMethods includesIdentical:aMethod) not |
|
2154 ] ifFalse:[ |
|
2155 savedMethods notNil ifTrue:[ |
|
2156 wanted := (savedMethods includesIdentical:aMethod). |
|
2157 ] ifFalse:[ |
|
2158 wanted := true |
|
2159 ] |
|
2160 ]. |
|
2161 wanted ifTrue:[interestingMethods add:aMethod]. |
|
2162 ] |
|
2163 ] |
|
2164 ]. |
|
2165 interestingMethods notEmpty ifTrue:[ |
|
2166 first := true. |
|
2167 privacy := nil. |
|
2168 |
|
2169 "/ |
|
2170 "/ sort by selector |
|
2171 "/ |
|
2172 sortedSelectors := interestingMethods collect:[:m | self selectorAtMethod:m]. |
|
2173 sortedSelectors sortWith:interestingMethods. |
|
2174 |
|
2175 interestingMethods do:[:aMethod | |
|
2176 first ifFalse:[ |
|
2177 privacy ~~ aMethod privacy ifTrue:[ |
|
2178 first := true. |
|
2179 aStream space. |
|
2180 aStream nextPutChunkSeparator. |
|
2181 ]. |
|
2182 aStream cr; cr |
|
2183 ]. |
|
2184 |
|
2185 privacy := aMethod privacy. |
|
2186 |
|
2187 first ifTrue:[ |
|
2188 aStream nextPutChunkSeparator. |
|
2189 self printClassNameOn:aStream. |
|
2190 privacy ~~ #public ifTrue:[ |
|
2191 aStream space; nextPutAll:privacy; nextPutAll:'MethodsFor:'. |
|
2192 ] ifFalse:[ |
|
2193 aStream nextPutAll:' methodsFor:'. |
|
2194 ]. |
|
2195 cat := aCategory. |
|
2196 cat isNil ifTrue:[ cat := '' ]. |
|
2197 aStream nextPutAll:aCategory asString storeString. |
|
2198 aStream nextPutChunkSeparator; cr; cr. |
|
2199 first := false. |
|
2200 ]. |
|
2201 source := aMethod source. |
|
2202 source isNil ifTrue:[ |
|
2203 Class fileOutErrorSignal |
|
2204 raiseRequestWith:self |
|
2205 errorString:'no source for method: ', (aMethod displayString) |
|
2206 ] ifFalse:[ |
|
2207 aStream nextChunkPut:source. |
|
2208 ]. |
|
2209 ]. |
|
2210 aStream space. |
|
2211 aStream nextPutChunkSeparator. |
|
2212 aStream cr |
|
2213 ] |
|
2214 ] |
|
2215 |
|
2216 "Modified: 28.8.1995 / 14:30:41 / claus" |
|
2217 "Modified: 12.6.1996 / 11:37:33 / stefan" |
|
2218 "Modified: 15.11.1996 / 11:32:21 / cg" |
|
2219 "Created: 1.4.1997 / 16:04:33 / stefan"! |
|
2220 |
|
2221 fileOutCategory:aCategory methodFilter:methodFilter on:aStream |
|
2222 "file out all methods belonging to aCategory, aString onto aStream" |
|
2223 |
|
2224 self fileOutCategory:aCategory except:nil only:nil methodFilter:methodFilter on:aStream! |
|
2225 |
|
2226 fileOutCategory:aCategory on:aStream |
|
2227 Class fileOutNameSpaceQuerySignal answer:true do:[ |
|
2228 self fileOutCategory:aCategory except:nil only:nil methodFilter:nil on:aStream |
|
2229 ]! |
|
2230 |
|
2231 fileOutClassInstVarDefinitionOn:aStream withNameSpace:withNameSpace |
|
2232 "append an expression to define my classInstanceVariables on aStream" |
|
2233 |
|
2234 |anySuperClassInstVar| |
|
2235 |
|
2236 self isLoaded ifFalse:[ |
|
2237 ^ self basicFileOutDefinitionOn:aStream withNameSpace:withNameSpace |
|
2238 ]. |
|
2239 |
|
2240 withNameSpace ifTrue:[ |
|
2241 self name printOn:aStream. |
|
2242 ] ifFalse:[ |
|
2243 self printClassNameOn:aStream. |
|
2244 ]. |
|
2245 aStream nextPutAll:' class instanceVariableNames:'''. |
|
2246 self class printInstVarNamesOn:aStream indent:8. |
|
2247 aStream nextPutAll:''''. |
|
2248 |
|
2249 "mhmh - good idea; saw this in SmallDraw sourcecode ..." |
|
2250 |
|
2251 anySuperClassInstVar := false. |
|
2252 self allSuperclassesDo:[:aSuperClass | |
|
2253 aSuperClass class instVarNames do:[:ignored | anySuperClassInstVar := true]. |
|
2254 ]. |
|
2255 |
|
2256 aStream cr; cr; nextPut:(Character doubleQuote); cr; space. |
|
2257 anySuperClassInstVar ifFalse:[ |
|
2258 aStream |
|
2259 nextPutLine:'No other class instance variables are inherited by this class.'. |
|
2260 ] ifTrue:[ |
|
2261 aStream |
|
2262 nextPutLine:'The following class instance variables are inherited by this class:'. |
|
2263 aStream cr. |
|
2264 self allSuperclassesDo:[:aSuperClass | |
|
2265 aStream tab; nextPutAll:aSuperClass name; nextPutAll:' - '. |
|
2266 aStream nextPutLine:(aSuperClass class instanceVariableString). |
|
2267 ]. |
|
2268 |
|
2269 ]. |
|
2270 aStream nextPut:(Character doubleQuote); cr. |
|
2271 |
|
2272 "Created: / 10.12.1995 / 16:31:25 / cg" |
|
2273 "Modified: / 1.4.1997 / 16:00:33 / stefan" |
|
2274 "Modified: / 3.2.2000 / 23:05:28 / cg" |
|
2275 ! |
|
2276 |
|
2277 fileOutDefinitionOn:aStream |
|
2278 "append an expression on aStream, which defines myself." |
|
2279 |
|
2280 ^ self basicFileOutDefinitionOn:aStream withNameSpace:false! |
|
2281 |
|
2282 fileOutMethod:aMethod |
|
2283 |aStream fileName selector| |
|
2284 |
|
2285 selector := self selectorAtMethod:aMethod. |
|
2286 selector notNil ifTrue:[ |
|
2287 fileName := (self name , '-' , selector, '.st') asFilename. |
|
2288 fileName makeLegalFilename. |
|
2289 |
|
2290 " |
|
2291 this test allows a smalltalk to be built without Projects/ChangeSets |
|
2292 " |
|
2293 Project notNil ifTrue:[ |
|
2294 fileName := Project currentProjectDirectory asFilename construct:fileName name. |
|
2295 ]. |
|
2296 |
|
2297 " |
|
2298 if file exists, save original in a .sav file |
|
2299 " |
|
2300 fileName exists ifTrue:[ |
|
2301 fileName copyTo:(fileName withSuffix: 'sav') |
|
2302 ]. |
|
2303 |
|
2304 fileName := fileName name. |
|
2305 |
|
2306 aStream := FileStream newFileNamed:fileName. |
|
2307 aStream isNil ifTrue:[ |
|
2308 ^ Class fileOutErrorSignal |
|
2309 raiseRequestWith:fileName |
|
2310 errorString:('cannot create file:', fileName) |
|
2311 ]. |
|
2312 self fileOutMethod:aMethod on:aStream. |
|
2313 aStream close |
|
2314 ] |
|
2315 |
|
2316 "Modified: / 1.4.1997 / 16:00:57 / stefan" |
|
2317 "Created: / 2.4.1997 / 00:24:28 / stefan" |
|
2318 "Modified: / 28.10.1997 / 14:40:34 / cg"! |
|
2319 |
|
2320 fileOutMethod:aMethod on:aStream |
|
2321 |dict cat source privacy| |
|
2322 |
|
2323 dict := self methodDictionary. |
|
2324 dict notNil ifTrue:[ |
|
2325 aStream nextPutChunkSeparator. |
|
2326 self name printOn:aStream. |
|
2327 "/ self printClassNameOn:aStream. |
|
2328 |
|
2329 (privacy := aMethod privacy) ~~ #public ifTrue:[ |
|
2330 aStream space; nextPutAll:privacy; nextPutAll:'MethodsFor:'. |
|
2331 ] ifFalse:[ |
|
2332 aStream nextPutAll:' methodsFor:'. |
|
2333 ]. |
|
2334 cat := aMethod category. |
|
2335 cat isNil ifTrue:[ |
|
2336 cat := '' |
|
2337 ]. |
|
2338 aStream nextPutAll:cat asString storeString. |
|
2339 aStream nextPutChunkSeparator; cr; cr. |
|
2340 source := aMethod source. |
|
2341 source isNil ifTrue:[ |
|
2342 Class fileOutErrorSignal |
|
2343 raiseRequestWith:self |
|
2344 errorString:('no source for method: ' , |
|
2345 self name , '>>' , |
|
2346 (self selectorAtMethod:aMethod)) |
|
2347 ] ifFalse:[ |
|
2348 aStream nextChunkPut:source. |
|
2349 ]. |
|
2350 aStream space. |
|
2351 aStream nextPutChunkSeparator. |
|
2352 aStream cr |
|
2353 ] |
|
2354 |
|
2355 "Modified: 27.8.1995 / 01:23:19 / claus" |
|
2356 "Modified: 12.6.1996 / 11:44:41 / stefan" |
|
2357 "Modified: 15.11.1996 / 11:32:43 / cg" |
|
2358 "Created: 2.4.1997 / 00:24:33 / stefan"! |
|
2359 |
|
2360 fileOutOn:aStream |
|
2361 |
|
2362 ^ self fileOutOn:aStream withTimeStamp:true! |
|
2363 |
|
2364 fileOutOn:aStream withTimeStamp:stampIt |
|
2365 "file out my definition and all methods onto aStream. |
|
2366 If stampIt is true, a timeStamp comment is prepended." |
|
2367 |
|
2368 self fileOutOn:aStream withTimeStamp:stampIt withInitialize:true! |
|
2369 |
|
2370 fileOutOn:aStream withTimeStamp:stampIt withInitialize:initIt |
|
2371 "file out my definition and all methods onto aStream. |
|
2372 If stampIt is true, a timeStamp comment is prepended. |
|
2373 If initIt is true, and the class implements a class-initialize method, |
|
2374 append a corresponding doIt expression for initialization." |
|
2375 |
|
2376 self |
|
2377 fileOutOn:aStream |
|
2378 withTimeStamp:stampIt |
|
2379 withInitialize:initIt |
|
2380 withDefinition:true |
|
2381 methodFilter:nil! |
|
2382 |
|
2383 fileOutOn:aStream withTimeStamp:stampIt withInitialize:initIt withDefinition:withDefinition methodFilter:methodFilter |
|
2384 "file out my definition and all methods onto aStream. |
|
2385 If stampIt is true, a timeStamp comment is prepended. |
|
2386 If initIt is true, and the class implements a class-initialize method, |
|
2387 append a corresponding doIt expression for initialization. |
|
2388 The order by which the fileOut is done is used to put the version string at the end. |
|
2389 Thus, if the version string is expanded (by CVS), the characterPositions of methods should not move" |
|
2390 |
|
2391 |collectionOfCategories copyrightMethod copyrightText comment versionMethod skippedMethods |
|
2392 meta| |
|
2393 |
|
2394 self isLoaded ifFalse:[ |
|
2395 ^ Class fileOutErrorSignal |
|
2396 raiseRequestWith:self |
|
2397 errorString:'will not fileOut unloaded classes' |
|
2398 ]. |
|
2399 |
|
2400 meta := self classRef. |
|
2401 |
|
2402 " |
|
2403 if there is a copyright method, add a copyright comment |
|
2404 at the beginning, taking the string from the copyright method. |
|
2405 We cannot do this unconditionally - that would lead to my copyrights |
|
2406 being put on your code ;-). |
|
2407 On the other hand: I want every file created by myself to have the |
|
2408 copyright string at the beginning be preserved .... even if the |
|
2409 code was edited in the browser and filedOut. |
|
2410 " |
|
2411 (copyrightMethod := meta compiledMethodAt:#copyright) notNil ifTrue:[ |
|
2412 " |
|
2413 get the copyright methods source, |
|
2414 and insert at beginning. |
|
2415 " |
|
2416 copyrightText := copyrightMethod source. |
|
2417 copyrightText isNil ifTrue:[ |
|
2418 " |
|
2419 no source available - trigger an error |
|
2420 " |
|
2421 Class fileOutErrorSignal |
|
2422 raiseRequestWith:'no source for class ' , self name , ' available. Cannot fileOut'. |
|
2423 ^ self |
|
2424 ]. |
|
2425 " |
|
2426 strip off the selector-line |
|
2427 " |
|
2428 copyrightText := copyrightText asCollectionOfLines asStringCollection. |
|
2429 copyrightText := copyrightText copyFrom:2 to:(copyrightText size). |
|
2430 "/ copyrightText do:[:line | aStream nextPutAll:line. aStream cr.]. |
|
2431 copyrightText := copyrightText asString. |
|
2432 aStream nextPutAllAsChunk:copyrightText. |
|
2433 ]. |
|
2434 |
|
2435 stampIt ifTrue:[ |
|
2436 "/ |
|
2437 "/ first, a timestamp |
|
2438 "/ |
|
2439 aStream nextPutAll:(Smalltalk timeStamp). |
|
2440 aStream nextPutChunkSeparator. |
|
2441 aStream cr; cr. |
|
2442 ]. |
|
2443 |
|
2444 withDefinition ifTrue:[ |
|
2445 "/ |
|
2446 "/ then the definition |
|
2447 "/ |
|
2448 self fileOutAllDefinitionsOn:aStream. |
|
2449 "/ |
|
2450 "/ a comment - if any |
|
2451 "/ |
|
2452 (comment := self comment) notNil ifTrue:[ |
|
2453 self fileOutCommentOn:aStream. |
|
2454 aStream cr. |
|
2455 ]. |
|
2456 "/ |
|
2457 "/ primitive definitions - if any |
|
2458 "/ |
|
2459 self fileOutPrimitiveSpecsOn:aStream. |
|
2460 ]. |
|
2461 |
|
2462 "/ |
|
2463 "/ methods from all categories in metaclass (i.e. class methods) |
|
2464 "/ EXCEPT: the version method is placed at the very end, to |
|
2465 "/ avoid sourcePosition-shifts when checked out later. |
|
2466 "/ (RCS expands this string, so its size is not constant) |
|
2467 "/ |
|
2468 collectionOfCategories := meta categories asSortedCollection. |
|
2469 collectionOfCategories notNil ifTrue:[ |
|
2470 "/ |
|
2471 "/ documentation first (if any), but not the version method |
|
2472 "/ |
|
2473 (collectionOfCategories includes:'documentation') ifTrue:[ |
|
2474 versionMethod := meta compiledMethodAt:#version. |
|
2475 versionMethod notNil ifTrue:[ |
|
2476 skippedMethods := Array with:versionMethod |
|
2477 ]. |
|
2478 meta fileOutCategory:'documentation' except:skippedMethods only:nil methodFilter:methodFilter on:aStream. |
|
2479 aStream cr. |
|
2480 ]. |
|
2481 |
|
2482 "/ |
|
2483 "/ initialization next (if any) |
|
2484 "/ |
|
2485 (collectionOfCategories includes:'initialization') ifTrue:[ |
|
2486 meta fileOutCategory:'initialization' methodFilter:methodFilter on:aStream. |
|
2487 aStream cr. |
|
2488 ]. |
|
2489 |
|
2490 "/ |
|
2491 "/ instance creation next (if any) |
|
2492 "/ |
|
2493 (collectionOfCategories includes:'instance creation') ifTrue:[ |
|
2494 meta fileOutCategory:'instance creation' methodFilter:methodFilter on:aStream. |
|
2495 aStream cr. |
|
2496 ]. |
|
2497 collectionOfCategories do:[:aCategory | |
|
2498 ((aCategory ~= 'documentation') |
|
2499 and:[(aCategory ~= 'initialization') |
|
2500 and:[aCategory ~= 'instance creation']]) ifTrue:[ |
|
2501 meta fileOutCategory:aCategory methodFilter:methodFilter on:aStream. |
|
2502 aStream cr |
|
2503 ] |
|
2504 ] |
|
2505 ]. |
|
2506 |
|
2507 "/ |
|
2508 "/ methods from all categories in myself |
|
2509 "/ |
|
2510 collectionOfCategories := self categories asSortedCollection. |
|
2511 collectionOfCategories notNil ifTrue:[ |
|
2512 collectionOfCategories do:[:aCategory | |
|
2513 self fileOutCategory:aCategory methodFilter:methodFilter on:aStream. |
|
2514 aStream cr |
|
2515 ] |
|
2516 ]. |
|
2517 |
|
2518 "/ |
|
2519 "/ any private classes' methods |
|
2520 "/ |
|
2521 self privateClassesSorted do:[:aClass | |
|
2522 aClass fileOutAllMethodsOn:aStream methodFilter:methodFilter |
|
2523 ]. |
|
2524 |
|
2525 |
|
2526 "/ |
|
2527 "/ finally, the previously skipped version method |
|
2528 "/ |
|
2529 versionMethod notNil ifTrue:[ |
|
2530 meta fileOutCategory:'documentation' except:nil only:skippedMethods methodFilter:methodFilter on:aStream. |
|
2531 ]. |
|
2532 |
|
2533 initIt ifTrue:[ |
|
2534 "/ |
|
2535 "/ optionally an initialize message |
|
2536 "/ |
|
2537 (meta implements:#initialize) ifTrue:[ |
|
2538 self printClassNameOn:aStream. aStream nextPutAll:' initialize'. |
|
2539 aStream nextPutChunkSeparator. |
|
2540 aStream cr |
|
2541 ] |
|
2542 ] |
|
2543 |
|
2544 "Created: / 15.11.1995 / 12:53:06 / cg" |
|
2545 "Modified: / 1.4.1997 / 16:01:05 / stefan" |
|
2546 "Modified: / 13.3.1998 / 12:23:59 / cg"! |
|
2547 |
|
2548 fileOutPrimitiveDefinitionsOn:aStream |
|
2549 "append primitive defs (if any) to aStream." |
|
2550 |
|
2551 |s| |
|
2552 |
|
2553 " |
|
2554 primitive definitions - if any |
|
2555 " |
|
2556 (s := self primitiveDefinitionsString) notNil ifTrue:[ |
|
2557 aStream nextPutChunkSeparator. |
|
2558 self printClassNameOn:aStream. |
|
2559 aStream nextPutAll:' primitiveDefinitions'; |
|
2560 nextPutChunkSeparator; |
|
2561 cr. |
|
2562 aStream nextPutAll:s. |
|
2563 aStream nextPutChunkSeparator; space; nextPutChunkSeparator; cr; cr |
|
2564 ]. |
|
2565 (s := self primitiveVariablesString) notNil ifTrue:[ |
|
2566 aStream nextPutChunkSeparator. |
|
2567 self printClassNameOn:aStream. |
|
2568 aStream nextPutAll:' primitiveVariables'; |
|
2569 nextPutChunkSeparator; |
|
2570 cr. |
|
2571 aStream nextPutAll:s. |
|
2572 aStream nextPutChunkSeparator; space; nextPutChunkSeparator; cr; cr |
|
2573 ]. |
|
2574 |
|
2575 "Modified: 8.1.1997 / 17:45:40 / cg"! |
|
2576 |
|
2577 fileOutPrimitiveSpecsOn:aStream |
|
2578 "append primitive defs (if any) to aStream." |
|
2579 |
|
2580 |s| |
|
2581 |
|
2582 " |
|
2583 primitive definitions - if any |
|
2584 " |
|
2585 self fileOutPrimitiveDefinitionsOn:aStream. |
|
2586 " |
|
2587 primitive functions - if any |
|
2588 " |
|
2589 (s := self primitiveFunctionsString) notNil ifTrue:[ |
|
2590 aStream nextPutChunkSeparator. |
|
2591 self printClassNameOn:aStream. |
|
2592 aStream nextPutAll:' primitiveFunctions'; |
|
2593 nextPutChunkSeparator; |
|
2594 cr. |
|
2595 aStream nextPutAll:s. |
|
2596 aStream nextPutChunkSeparator; space; nextPutChunkSeparator; cr; cr |
|
2597 ]. |
|
2598 |
|
2599 "Modified: 8.1.1997 / 17:45:51 / cg"! |
|
2600 |
1429 firstDefinitionSelectorPart |
2601 firstDefinitionSelectorPart |
1430 "return the first part of the selector with which I was (can be) defined in my superclass" |
2602 "return the first part of the selector with which I was (can be) defined in my superclass" |
1431 |
2603 |
1432 self isVariable ifFalse:[ |
2604 self isVariable ifFalse:[ |
1433 ^ #'subclass:' |
2605 ^ #'subclass:' |
1481 idx == 0 ifTrue:[ |
2736 idx == 0 ifTrue:[ |
1482 ^ nm |
2737 ^ nm |
1483 ]. |
2738 ]. |
1484 ^ nm copyFrom:idx+1. |
2739 ^ nm copyFrom:idx+1. |
1485 ! |
2740 ! |
|
2741 |
|
2742 packageSourceCodeInfo |
|
2743 "{ Pragma: +optSpace }" |
|
2744 |
|
2745 "return the sourceCodeInfo, which defines the module and the subdirectory |
|
2746 in which the receiver class was built. |
|
2747 This info is extracted from the package id (which is added to stc-compiled classes). |
|
2748 This method is to be obsoleted soon, since the same info is now found |
|
2749 in the versionString. |
|
2750 |
|
2751 The info returned consists of a dictionary |
|
2752 filled with (at least) values at: #module, #directory and #library. |
|
2753 If no such info is present in the class, nil is returned. |
|
2754 (this happens with autoloaded and filed-in classes) |
|
2755 Auotloaded classes set their package from the revisionInfo, if present. |
|
2756 |
|
2757 By convention, this info is encoded in the classes package |
|
2758 string (which is given as argument to stc) as the last word in parenthesis. |
|
2759 The info consists of 1 to 3 subcomponents, separated by colons. |
|
2760 The first defines the classes module (i.e. some application identifier), |
|
2761 the second defines the subdirectory within that module, the third |
|
2762 defines the name of the class library. |
|
2763 If left blank, the module info defaults to 'stx', |
|
2764 the directory info defaults to library name. |
|
2765 The library name may not be left blank. |
|
2766 (this is done for backward compatibility,) |
|
2767 |
|
2768 For example: |
|
2769 '....(libbasic)' -> module: stx directory: libbasic library: libbasic |
|
2770 '....(stx:libbasic)' -> module: stx directory: libbasic library: libbasic |
|
2771 '....(stx:foo:libbfoo)' -> module: stx directory: foo library: libfoo |
|
2772 '....(aeg:libIECInterface)' -> module: aeg directory: libIECInterface library:libIECInterface |
|
2773 '....(stx:goodies/persistency:libdbase)' -> module: stx directory: goodies/persistency library:libdbase |
|
2774 |
|
2775 The way how the sourceCodeManager uses this to find the source location |
|
2776 depends on the scheme used. For CVS, the module is taken as the -d arg, |
|
2777 while the directory is prepended to the file name. |
|
2778 Other schemes may do things differently - these are not yet specified. |
|
2779 |
|
2780 Caveat: |
|
2781 Encoding this info in the package string seems somewhat kludgy. |
|
2782 " |
|
2783 |
|
2784 |owner sourceInfo packageString idx1 idx2 |
|
2785 moduleString directoryString libraryString components component1 component2 dirComponents mgr |
|
2786 package| |
|
2787 |
|
2788 (owner := self owningClass) notNil ifTrue:[^ owner packageSourceCodeInfo]. |
|
2789 |
|
2790 package := self package. |
|
2791 package isNil ifTrue:[^ nil]. |
|
2792 |
|
2793 packageString := package asString. |
|
2794 idx1 := packageString lastIndexOf:$(. |
|
2795 idx1 ~~ 0 ifTrue:[ |
|
2796 idx2 := packageString indexOf:$) startingAt:idx1+1. |
|
2797 idx2 ~~ 0 ifTrue:[ |
|
2798 sourceInfo := packageString copyFrom:idx1 + 1 to:idx2 - 1 |
|
2799 ] |
|
2800 ] ifFalse:[ |
|
2801 sourceInfo := packageString |
|
2802 ]. |
|
2803 |
|
2804 sourceInfo isNil ifTrue:[^ nil]. |
|
2805 components := sourceInfo asCollectionOfSubstringsSeparatedBy:$:. |
|
2806 components size == 0 ifTrue:[ |
|
2807 "/ moduleString := 'stx'. |
|
2808 "/ directoryString := libraryString := ''. |
|
2809 ^ nil |
|
2810 ]. |
|
2811 |
|
2812 component1 := components at:1. |
|
2813 components size == 1 ifTrue:[ |
|
2814 "/ a single name given - the module becomes 'stx' or |
|
2815 "/ the very first directory component (if such a module exists). |
|
2816 "/ If the component includes slashes, its the directory |
|
2817 "/ otherwise the library. |
|
2818 "/ |
|
2819 dirComponents := Filename concreteClass components:component1. |
|
2820 (dirComponents size > 1 |
|
2821 and:[(mgr := self sourceCodeManager) notNil |
|
2822 and:[mgr checkForExistingModule:dirComponents first]]) ifTrue:[ |
|
2823 moduleString := dirComponents first. |
|
2824 directoryString := libraryString := (Filename fromComponents:(dirComponents copyFrom:2)) asString. |
|
2825 ] ifFalse:[ |
|
2826 "/ non-existing; assume directory under the stx package. |
|
2827 moduleString := 'stx'. |
|
2828 (component1 startsWith:'stx/') ifTrue:[ |
|
2829 component1 := component1 copyFrom:5 |
|
2830 ]. |
|
2831 directoryString := libraryString := component1. |
|
2832 ]. |
|
2833 |
|
2834 (libraryString includes:$/) ifTrue:[ |
|
2835 libraryString := libraryString asFilename baseName |
|
2836 ] |
|
2837 ] ifFalse:[ |
|
2838 component2 := components at:2. |
|
2839 components size == 2 ifTrue:[ |
|
2840 "/ two components - assume its the module and the directory; |
|
2841 "/ the library is assumed to be named after the directory |
|
2842 "/ except, if slashes are in the name; then the libraryname |
|
2843 "/ is the last component. |
|
2844 "/ |
|
2845 moduleString := component1. |
|
2846 directoryString := libraryString := component2. |
|
2847 (libraryString includes:$/) ifTrue:[ |
|
2848 libraryString := libraryString asFilename baseName |
|
2849 ] |
|
2850 ] ifFalse:[ |
|
2851 "/ all components given |
|
2852 moduleString := component1. |
|
2853 directoryString := component2. |
|
2854 libraryString := components at:3. |
|
2855 ] |
|
2856 ]. |
|
2857 |
|
2858 libraryString isEmpty ifTrue:[ |
|
2859 directoryString notEmpty ifTrue:[ |
|
2860 libraryString := directoryString asFilename baseName |
|
2861 ]. |
|
2862 libraryString isEmpty ifTrue:[ |
|
2863 "/ lets extract the library from the liblist file ... |
|
2864 libraryString := Smalltalk libraryFileNameOfClass:self. |
|
2865 libraryString isNil ifTrue:[^ nil]. |
|
2866 ] |
|
2867 ]. |
|
2868 |
|
2869 moduleString isEmpty ifTrue:[ |
|
2870 moduleString := 'stx'. |
|
2871 ]. |
|
2872 directoryString isEmpty ifTrue:[ |
|
2873 directoryString := libraryString. |
|
2874 ]. |
|
2875 |
|
2876 ^ IdentityDictionary |
|
2877 with:(#module->moduleString) |
|
2878 with:(#directory->directoryString) |
|
2879 with:(#library->libraryString) |
|
2880 |
|
2881 " |
|
2882 Object packageSourceCodeInfo |
|
2883 View packageSourceCodeInfo |
|
2884 Model packageSourceCodeInfo |
|
2885 BinaryObjectStorage packageSourceCodeInfo |
|
2886 MemoryMonitor packageSourceCodeInfo |
|
2887 ClockView packageSourceCodeInfo |
|
2888 " |
|
2889 |
|
2890 "Created: 4.11.1995 / 20:36:53 / cg" |
|
2891 "Modified: 19.9.1997 / 10:42:25 / cg"! |
|
2892 |
|
2893 primitiveDefinitionsString |
|
2894 "{ Pragma: +optSpace }" |
|
2895 |
|
2896 "return the primitiveDefinition string or nil" |
|
2897 |
|
2898 ^ self getPrimitiveSpecsAt:1 |
|
2899 |
|
2900 " |
|
2901 Object primitiveDefinitionsString |
|
2902 String primitiveDefinitionsString |
|
2903 "! |
|
2904 |
|
2905 primitiveFunctionsString |
|
2906 "{ Pragma: +optSpace }" |
|
2907 |
|
2908 "return the primitiveFunctions string or nil" |
|
2909 |
|
2910 ^ self getPrimitiveSpecsAt:3! |
|
2911 |
|
2912 primitiveVariablesString |
|
2913 "{ Pragma: +optSpace }" |
|
2914 |
|
2915 "return the primitiveVariables string or nil" |
|
2916 |
|
2917 ^ self getPrimitiveSpecsAt:2! |
|
2918 |
|
2919 printClassNameOn:aStream |
|
2920 |nm| |
|
2921 |
|
2922 Class fileOutNameSpaceQuerySignal query == false ifTrue:[ |
|
2923 nm := self nameWithoutNameSpacePrefix |
|
2924 ] ifFalse:[ |
|
2925 nm := self name. |
|
2926 ]. |
|
2927 |
|
2928 aStream nextPutAll:nm.! |
1486 |
2929 |
1487 printClassVarNamesOn:aStream indent:indent |
2930 printClassVarNamesOn:aStream indent:indent |
1488 "print the class variable names indented and breaking at line end" |
2931 "print the class variable names indented and breaking at line end" |
1489 |
2932 |
1490 self printNameArray:(self classVarNames) on:aStream indent:indent |
2933 self printNameArray:(self classVarNames) on:aStream indent:indent |
1581 ]. |
3032 ]. |
1582 |
3033 |
1583 ^ memory at:nmSym. |
3034 ^ memory at:nmSym. |
1584 ! |
3035 ! |
1585 |
3036 |
|
3037 privateClassesOrAll:allOfThem |
|
3038 "{ Pragma: +optSpace }" |
|
3039 |
|
3040 "return a collection of my direct private classes (if any) |
|
3041 or direct plus indirect private classes (if allOfThem). |
|
3042 An empty collection if there are none. |
|
3043 The classes are in any order." |
|
3044 |
|
3045 |classes myName myNamePrefix myNamePrefixLen| |
|
3046 |
|
3047 myName := self name. |
|
3048 myNamePrefix := myName , '::'. |
|
3049 myNamePrefixLen := myNamePrefix size. |
|
3050 |
|
3051 Smalltalk keysDo:[:nm | |
|
3052 |cls| |
|
3053 |
|
3054 (nm startsWith:myNamePrefix) ifTrue:[ |
|
3055 (allOfThem |
|
3056 or:[(nm indexOf:$: startingAt:myNamePrefixLen + 1) == 0]) ifTrue:[ |
|
3057 cls := Smalltalk at:nm. |
|
3058 |
|
3059 (cls isBehavior and:[cls isMeta not]) ifTrue:[ |
|
3060 classes isNil ifTrue:[ |
|
3061 classes := IdentitySet new:10. |
|
3062 ]. |
|
3063 classes add:cls. |
|
3064 ] |
|
3065 ] |
|
3066 ] |
|
3067 ]. |
|
3068 |
|
3069 ^ classes ? #() |
|
3070 |
|
3071 " |
|
3072 UILayoutTool privateClassesOrAll:true |
|
3073 UILayoutTool privateClassesOrAll:false |
|
3074 " |
|
3075 |
|
3076 "Modified: / 29.5.1998 / 23:23:18 / cg"! |
|
3077 |
|
3078 privateClassesSorted |
|
3079 "{ Pragma: +optSpace }" |
|
3080 |
|
3081 "return a collection of my private classes (if any). |
|
3082 The classes are sorted by inheritance." |
|
3083 |
|
3084 |classes| |
|
3085 |
|
3086 classes := self privateClasses. |
|
3087 (classes size > 0) ifTrue:[ |
|
3088 classes := classes asOrderedCollection topologicalSort:[:a :b | b isSubclassOf:a]. |
|
3089 ]. |
|
3090 ^ classes. |
|
3091 |
|
3092 " |
|
3093 Object privateClassesSorted |
|
3094 " |
|
3095 |
|
3096 "Created: 22.3.1997 / 16:10:42 / cg" |
|
3097 "Modified: 22.3.1997 / 16:11:20 / cg"! |
|
3098 |
|
3099 revisionInfo |
|
3100 "return a dictionary filled with revision info. |
|
3101 This extracts the relevant info from the revisionString. |
|
3102 The revisionInfo contains all or a subset of: |
|
3103 #binaryRevision - the revision upon which the binary of this class is based |
|
3104 #revision - the revision upon which the class is based logically |
|
3105 (different, if a changed class was checked in, but not yet recompiled) |
|
3106 #user - the user who checked in the logical revision |
|
3107 #date - the date when the logical revision was checked in |
|
3108 #time - the time when the logical revision was checked in |
|
3109 #fileName - the classes source file name |
|
3110 #repositoryPath - the classes source container |
|
3111 " |
|
3112 |
|
3113 |vsnString info mgr| |
|
3114 |
|
3115 vsnString := self revisionString. |
|
3116 vsnString notNil ifTrue:[ |
|
3117 mgr := self sourceCodeManager. |
|
3118 mgr notNil ifTrue:[ |
|
3119 info := mgr revisionInfoFromString:vsnString |
|
3120 ] ifFalse:[ |
|
3121 info := Class revisionInfoFromString:vsnString. |
|
3122 ]. |
|
3123 info notNil ifTrue:[ |
|
3124 info at:#binaryRevision put:self binaryRevision. |
|
3125 ] |
|
3126 ]. |
|
3127 ^ info! |
|
3128 |
|
3129 revisionString |
|
3130 "{ Pragma: +optSpace }" |
|
3131 |
|
3132 "return my revision string; that one is extracted from the |
|
3133 classes #version method. Either this is a method returning that string, |
|
3134 or its a comment-only method and the comment defines the version. |
|
3135 If the source is not accessable or no such method exists, |
|
3136 nil is returned." |
|
3137 |
|
3138 |owner cls meta m src val| |
|
3139 |
|
3140 (owner := self owningClass) notNil ifTrue:[^ owner revisionString]. |
|
3141 |
|
3142 thisContext isRecursive ifTrue:[^ nil ]. |
|
3143 |
|
3144 self isMeta ifTrue:[ |
|
3145 meta := self. cls := self soleInstance |
|
3146 ] ifFalse:[ |
|
3147 cls := self. meta := self classRef |
|
3148 ]. |
|
3149 |
|
3150 m := meta compiledMethodAt:#version. |
|
3151 m isNil ifTrue:[ |
|
3152 m := cls compiledMethodAt:#version. |
|
3153 m isNil ifTrue:[^ nil]. |
|
3154 ]. |
|
3155 |
|
3156 m isExecutable ifTrue:[ |
|
3157 "/ |
|
3158 "/ if its a method returning the string, |
|
3159 "/ thats the returned value |
|
3160 "/ |
|
3161 val := cls version. |
|
3162 val isString ifTrue:[^ val]. |
|
3163 ]. |
|
3164 |
|
3165 "/ |
|
3166 "/ if its a method consisting of a comment only |
|
3167 "/ extract it - this may lead to a recursive call |
|
3168 "/ to myself (thats what the #isRecursive is for) |
|
3169 "/ in case we need to access the source code manager |
|
3170 "/ for the source ... |
|
3171 "/ |
|
3172 src := m source. |
|
3173 src isNil ifTrue:[^ nil]. |
|
3174 ^ Class revisionStringFromSource:src |
|
3175 |
|
3176 " |
|
3177 Smalltalk allClassesDo:[:cls | |
|
3178 Transcript showCR:cls revisionString |
|
3179 ]. |
|
3180 |
|
3181 Number revisionString |
|
3182 FileDirectory revisionString |
|
3183 Metaclass revisionString |
|
3184 " |
|
3185 |
|
3186 "Created: 29.10.1995 / 19:28:03 / cg" |
|
3187 "Modified: 23.10.1996 / 18:23:56 / cg" |
|
3188 "Modified: 1.4.1997 / 23:37:25 / stefan"! |
|
3189 |
|
3190 selectorAtMethod:aMethod |
|
3191 ^ self selectorAtMethod:aMethod ifAbsent:[nil]! |
|
3192 |
|
3193 selectorAtMethod:aMethod ifAbsent:failBlock |
|
3194 |md| |
|
3195 |
|
3196 md := self methodDictionary. |
|
3197 md isNil ifTrue:[ |
|
3198 'OOPS - nil methodDictionary' errorPrintCR. |
|
3199 ^ nil |
|
3200 ]. |
|
3201 ^ md keyAtValue:aMethod ifAbsent:failBlock.! |
|
3202 |
|
3203 soleInstance |
|
3204 self isMeta ifFalse:[self halt]. |
|
3205 ^ self theNonMetaclass. |
|
3206 ! |
|
3207 |
1586 sourceCodeManager |
3208 sourceCodeManager |
1587 ^ SourceCodeManager |
3209 ^ SourceCodeManager |
1588 ! |
3210 ! |
1589 |
3211 |
|
3212 sourceStreamFor:source |
|
3213 "return an open stream on a sourcefile, nil if that is not available" |
|
3214 |
|
3215 |owner fileName aStream mgr validated guessedFileName sep mod dir classFilename package name| |
|
3216 |
|
3217 self isMeta ifTrue:[ |
|
3218 ^ self theNonMetaclass sourceStreamFor:source |
|
3219 ]. |
|
3220 |
|
3221 (owner := self owningClass) notNil ifTrue:[^ owner sourceStreamFor:source]. |
|
3222 validated := false. |
|
3223 |
|
3224 classFilename := self classFilename. |
|
3225 package := self package. |
|
3226 name := self name. |
|
3227 |
|
3228 "/ |
|
3229 "/ if there is no SourceCodeManager, |
|
3230 "/ or TryLocalSourceFirst is true, |
|
3231 "/ look in standard places first |
|
3232 "/ |
|
3233 ((mgr := self sourceCodeManager) isNil |
|
3234 or:[Class tryLocalSourceFirst == true]) ifTrue:[ |
|
3235 aStream := self localSourceStreamFor:source. |
|
3236 ]. |
|
3237 |
|
3238 aStream isNil ifTrue:[ |
|
3239 "/ mhmh - still no source file. |
|
3240 "/ If there is a SourceCodeManager, ask it to aquire the |
|
3241 "/ the source for my class, and return an open stream on it. |
|
3242 "/ if that one does not know about the source, look in |
|
3243 "/ standard places |
|
3244 |
|
3245 mgr notNil ifTrue:[ |
|
3246 self classFilename ~= source ifTrue:[ |
|
3247 sep := self package indexOfAny:'/\:'. |
|
3248 sep ~~ 0 ifTrue:[ |
|
3249 mod := package copyTo:sep - 1. |
|
3250 dir := package copyFrom:sep + 1. |
|
3251 aStream := mgr streamForClass:nil fileName:source revision:nil directory:dir module:mod cache:true. |
|
3252 ]. |
|
3253 ]. |
|
3254 aStream isNil ifTrue:[ |
|
3255 classFilename isNil ifTrue:[ |
|
3256 classFilename := guessedFileName := (Smalltalk fileNameForClass:self) , '.st'. |
|
3257 ]. |
|
3258 source asFilename baseName = classFilename asFilename baseName ifTrue:[ |
|
3259 aStream := mgr getSourceStreamFor:self. |
|
3260 ] |
|
3261 ]. |
|
3262 aStream notNil ifTrue:[ |
|
3263 (self validateSourceStream:aStream) ifFalse:[ |
|
3264 ('Class [info]: repositories source for `' |
|
3265 , (self isMeta ifTrue:[self soleInstance name] |
|
3266 ifFalse:[name]) |
|
3267 , ''' is invalid.') infoPrintCR. |
|
3268 aStream close. |
|
3269 aStream := nil |
|
3270 ] ifTrue:[ |
|
3271 validated := true. |
|
3272 ]. |
|
3273 ]. |
|
3274 ] |
|
3275 ]. |
|
3276 |
|
3277 aStream isNil ifTrue:[ |
|
3278 "/ |
|
3279 "/ hard case - there is no source file for this class |
|
3280 "/ (in the source-dir-path). |
|
3281 "/ |
|
3282 |
|
3283 "/ |
|
3284 "/ look if my binary is from a dynamically loaded module, |
|
3285 "/ and, if so, look in the modules directory for the |
|
3286 "/ source file. |
|
3287 "/ |
|
3288 ObjectFileLoader notNil ifTrue:[ |
|
3289 ObjectFileLoader loadedObjectHandlesDo:[:h | |
|
3290 |f classes| |
|
3291 |
|
3292 aStream isNil ifTrue:[ |
|
3293 (classes := h classes) size > 0 ifTrue:[ |
|
3294 (classes includes:self) ifTrue:[ |
|
3295 f := h pathName. |
|
3296 f := f asFilename directory. |
|
3297 f := f construct:source. |
|
3298 f exists ifTrue:[ |
|
3299 aStream := f readStream. |
|
3300 ]. |
|
3301 ]. |
|
3302 ]. |
|
3303 ] |
|
3304 ]. |
|
3305 ]. |
|
3306 ]. |
|
3307 |
|
3308 "/ |
|
3309 "/ try along sourcePath |
|
3310 "/ |
|
3311 aStream isNil ifTrue:[ |
|
3312 aStream := self localSourceStreamFor:source. |
|
3313 ]. |
|
3314 |
|
3315 "/ |
|
3316 "/ final chance: try current directory |
|
3317 "/ |
|
3318 aStream isNil ifTrue:[ |
|
3319 aStream := source asFilename readStream. |
|
3320 ]. |
|
3321 |
|
3322 (aStream notNil and:[validated not]) ifTrue:[ |
|
3323 (self validateSourceStream:aStream) ifFalse:[ |
|
3324 (Smalltalk releaseIdentification = 'ST/X_free_demo_vsn') ifTrue:[ |
|
3325 "/ ('Class [info]: source for ''' , self name , ''' is not available in the demo version.') infoPrintCR |
|
3326 ] ifFalse:[ |
|
3327 ('Class [warning]: source for ''' , self name , ''' is invalid or stripped. Take care.') errorPrintCR |
|
3328 ] |
|
3329 ]. |
|
3330 ]. |
|
3331 (aStream notNil and:[aStream isFileStream]) ifTrue:[ |
|
3332 guessedFileName notNil ifTrue:[ |
|
3333 classFilename := aStream pathName asFilename baseName. |
|
3334 ] |
|
3335 ]. |
|
3336 ^ aStream |
|
3337 |
|
3338 " |
|
3339 Object sourceStream |
|
3340 Clock sourceStream |
|
3341 Autoload sourceStream |
|
3342 " |
|
3343 |
|
3344 "Created: / 10.11.1995 / 21:05:13 / cg" |
|
3345 "Modified: / 22.4.1998 / 19:20:50 / ca" |
|
3346 "Modified: / 23.4.1998 / 15:53:54 / cg" |
|
3347 ! |
|
3348 |
|
3349 subclasses |
|
3350 "return a collection of the direct subclasses of the receiver" |
|
3351 |
|
3352 |newColl| |
|
3353 |
|
3354 "/ "/ use cached information (avoid class hierarchy search) |
|
3355 "/ "/ if possible |
|
3356 "/ |
|
3357 "/ SubclassInfo notNil ifTrue:[ |
|
3358 "/ newColl := SubclassInfo at:self ifAbsent:nil. |
|
3359 "/ newColl notNil ifTrue:[^ newColl asOrderedCollection] |
|
3360 "/ ]. |
|
3361 |
|
3362 newColl := OrderedCollection new. |
|
3363 self subclassesDo:[:aClass | |
|
3364 newColl add:aClass |
|
3365 ]. |
|
3366 "/ SubclassInfo notNil ifTrue:[ |
|
3367 "/ SubclassInfo at:self put:newColl. |
|
3368 "/ ]. |
|
3369 ^ newColl |
|
3370 ! |
|
3371 |
|
3372 subclassesDo:aBlock |
|
3373 "evaluate the argument, aBlock for all immediate subclasses. |
|
3374 This will only enumerate globally known classes - for anonymous |
|
3375 behaviors, you have to walk over all instances of Behavior." |
|
3376 |
|
3377 |coll| |
|
3378 |
|
3379 self isMeta ifTrue:[ |
|
3380 self halt. |
|
3381 "/ metaclasses are not found via Smalltalk allClassesDo: |
|
3382 "/ here, walk over classes and enumerate corresponding metas. |
|
3383 self soleInstance subclassesDo:[:aSubClass | |
|
3384 aBlock value:(aSubClass class) |
|
3385 ]. |
|
3386 ^ self |
|
3387 ]. |
|
3388 |
|
3389 "/ use cached information (avoid class hierarchy search) |
|
3390 "/ if possible |
|
3391 |
|
3392 "/ SubclassInfo isNil ifTrue:[ |
|
3393 "/ Behavior subclassInfo |
|
3394 "/ ]. |
|
3395 "/ SubclassInfo notNil ifTrue:[ |
|
3396 "/ coll := SubclassInfo at:self ifAbsent:nil. |
|
3397 "/ coll notNil ifTrue:[ |
|
3398 "/ coll do:aBlock. |
|
3399 "/ ]. |
|
3400 "/ ^ self |
|
3401 "/ ]. |
|
3402 |
|
3403 Smalltalk allClassesDo:[:aClass | |
|
3404 (aClass superclass == self) ifTrue:[ |
|
3405 aBlock value:aClass |
|
3406 ] |
|
3407 ] |
|
3408 |
|
3409 " |
|
3410 Collection subclassesDo:[:c | Transcript showCR:(c name)] |
|
3411 " |
|
3412 |
|
3413 "Modified: 22.1.1997 / 18:44:01 / cg" |
|
3414 ! |
|
3415 |
1590 syntaxHighlighterClass |
3416 syntaxHighlighterClass |
1591 ^ Object syntaxHighlighterClass |
3417 ^ Object syntaxHighlighterClass |
1592 ! |
3418 ! |
|
3419 |
|
3420 theMetaclass |
|
3421 self isMeta ifTrue:[^ self]. |
|
3422 ^ self classRef.! |
|
3423 |
|
3424 theNonMetaclass |
|
3425 |instSlotOffs clsPtr| |
|
3426 |
|
3427 self isMeta ifFalse:[^ self]. |
|
3428 instSlotOffs := Metaclass instVarOffsetOf:'myClass'. |
|
3429 clsPtr := self at:instSlotOffs. |
|
3430 ^ memory fetchObjectAt:clsPtr. |
|
3431 ! |
|
3432 |
|
3433 validateSourceStream:aStream |
|
3434 "check if aStream really contains my source. |
|
3435 This is done by checking the version methods return value |
|
3436 against the version string as contained in the version method" |
|
3437 |
|
3438 ^ true! |
|
3439 |
|
3440 withAllSuperclasses |
|
3441 "return a collection containing the receiver and all |
|
3442 of the receivers accumulated superclasses" |
|
3443 |
|
3444 |aCollection theSuperClass| |
|
3445 |
|
3446 aCollection := OrderedCollection with:self. |
|
3447 theSuperClass := self superclass. |
|
3448 [theSuperClass notNil] whileTrue:[ |
|
3449 aCollection add:theSuperClass. |
|
3450 theSuperClass := theSuperClass superclass |
|
3451 ]. |
|
3452 ^ aCollection |
|
3453 |
|
3454 " |
|
3455 String withAllSuperclasses |
|
3456 "! |
1593 |
3457 |
1594 withAllSuperclassesDo:aBlock |
3458 withAllSuperclassesDo:aBlock |
1595 |sc| |
3459 |sc| |
1596 |
3460 |
1597 aBlock value:self. |
3461 aBlock value:self. |