91 "Given a source and a substring of it, return a string containing |
91 "Given a source and a substring of it, return a string containing |
92 an explanation. |
92 an explanation. |
93 This is just a q&d implementation - to be correct, it should use the parser, |
93 This is just a q&d implementation - to be correct, it should use the parser, |
94 and explain from the parsetree (instead of doing string matches). |
94 and explain from the parsetree (instead of doing string matches). |
95 This leads to some wrong explanations, for example if some string is |
95 This leads to some wrong explanations, for example if some string is |
96 used as selector within a string. |
96 used as selector within a string, or if a variable is named like a |
|
97 message selector. I.e. the explanation should be context sensitive. |
97 Also, there could be much more detailed explanations." |
98 Also, there could be much more detailed explanations." |
98 |
99 |
99 |parser variables v c string tmp |
100 |parser variables v c string tmp |
100 spc sym| |
101 spc sym sel stringText| |
101 |
102 |
102 string := someText string withoutSeparators. |
103 string := someText string withoutSeparators. |
|
104 stringText := string asText allBold. |
103 |
105 |
104 " |
106 " |
105 ask parser for variable names |
107 ask parser for variable names |
106 " |
108 " |
107 parser := self parseMethod:source in:aClass ignoreErrors:true ignoreWarnings:true. |
109 parser := self parseMethod:source in:aClass ignoreErrors:true ignoreWarnings:true. |
108 parser notNil ifTrue:[ |
110 parser notNil ifTrue:[ |
109 "look for variables" |
111 "look for variables" |
110 |
112 |
111 variables := parser methodVars. |
113 variables := parser methodVars. |
112 (variables notNil and:[variables includes:string]) ifTrue:[ |
114 (variables notNil and:[variables includes:string]) ifTrue:[ |
113 ^ '''' , string , ''' is a method variable' |
115 ^ '''' , stringText , ''' is a method variable' |
114 ]. |
116 ]. |
115 variables := parser methodArgs. |
117 variables := parser methodArgs. |
116 (variables notNil and:[variables includes:string]) ifTrue:[ |
118 (variables notNil and:[variables includes:string]) ifTrue:[ |
117 ^ '''' , string , ''' is a method argument' |
119 ^ '''' , stringText , ''' is a method argument' |
118 ] |
120 ] |
119 ]. |
121 ]. |
120 |
122 |
121 parser isNil ifTrue:[ |
123 parser isNil ifTrue:[ |
122 parser := self for:(ReadStream on:source) in:aClass |
124 parser := self for:(ReadStream on:source) in:aClass |
124 |
126 |
125 "instvars" |
127 "instvars" |
126 c := aClass whichClassDefinesInstVar:string. |
128 c := aClass whichClassDefinesInstVar:string. |
127 c notNil ifTrue:[ |
129 c notNil ifTrue:[ |
128 c isMeta ifTrue:[ |
130 c isMeta ifTrue:[ |
129 ^ '''' , string , ''' is a class instance variable in ' , c soleInstance name |
131 ^ '''' , stringText , ''' is a class instance variable in ' , c soleInstance name |
130 ]. |
132 ]. |
131 |
133 |
132 ^ '''' , string , ''' is an instance variable in ' , c name |
134 ^ '''' , stringText , ''' is an instance variable in ' , c name |
133 ]. |
135 ]. |
134 |
136 |
135 "/ variables := aClass allInstVarNames. |
137 "/ variables := aClass allInstVarNames. |
136 "/ (variables notNil and:[variables includes:string]) ifTrue:[ |
138 "/ (variables notNil and:[variables includes:string]) ifTrue:[ |
137 "/ "where is it" |
139 "/ "where is it" |
162 "/ ]. |
164 "/ ]. |
163 |
165 |
164 "classvars" |
166 "classvars" |
165 c := parser inWhichClassIsClassVar:string. |
167 c := parser inWhichClassIsClassVar:string. |
166 c notNil ifTrue:[ |
168 c notNil ifTrue:[ |
167 ^ '''' , string , ''' is a class variable in ' , c name |
169 ^ '''' , stringText , ''' is a class variable in ' , c name |
168 ]. |
170 ]. |
169 |
171 |
170 aClass isMeta ifTrue:[ |
172 aClass isMeta ifTrue:[ |
171 c := aClass soleInstance. |
173 c := aClass soleInstance. |
172 ] ifFalse:[ |
174 ] ifFalse:[ |
173 c := aClass. |
175 c := aClass. |
174 ]. |
176 ]. |
175 c privateClasses do:[:pClass | |
177 c privateClasses do:[:pClass | |
176 (pClass name = string |
178 (pClass name = string |
177 or:[pClass nameWithoutPrefix = string]) ifTrue:[ |
179 or:[pClass nameWithoutPrefix = string]) ifTrue:[ |
178 ^ ('''' , string , ''' is a private class in ''' , c name , '''.' |
180 ^ ('''' , stringText , ''' is a private class in ''' , c name , '''.' |
179 , '\\It is only visible locally.') withCRs |
181 , '\\It is only visible locally.') withCRs |
180 ]. |
182 ]. |
181 ]. |
183 ]. |
182 |
184 |
183 (spc := aClass nameSpace) notNil ifTrue:[ |
185 (spc := aClass nameSpace) notNil ifTrue:[ |
184 sym := (spc name , '::' , string) asSymbolIfInterned. |
186 sym := (spc name , '::' , string) asSymbolIfInterned. |
185 sym notNil ifTrue:[ |
187 sym notNil ifTrue:[ |
186 (Smalltalk at:sym) isBehavior ifTrue:[ |
188 (Smalltalk at:sym) isBehavior ifTrue:[ |
187 ^ ('''' , string , ''' is a class in the ''' , spc name , ''' nameSpace.' |
189 ^ ('''' , stringText , ''' is a class in the ''' , spc name , ''' nameSpace.' |
188 , '\\It is only visible within this nameSpace.' |
190 , '\\It is only visible within this nameSpace.' |
189 , '\Access from the outside is possible' |
191 , '\Access from the outside is possible' |
190 , '\by the special name ''' , spc name , '::' , string , '''.') withCRs |
192 , '\by the special name ''' , spc name , '::' , string , '''.') withCRs |
191 ]. |
193 ]. |
192 ]. |
194 ]. |
195 "/ string knownAsSymbol ifTrue:[ |
197 "/ string knownAsSymbol ifTrue:[ |
196 "globals & symbols" |
198 "globals & symbols" |
197 |
199 |
198 tmp := self explainKnownSymbol:string inClass:aClass. |
200 tmp := self explainKnownSymbol:string inClass:aClass. |
199 tmp notNil ifTrue:[ ^ tmp]. |
201 tmp notNil ifTrue:[ ^ tmp]. |
|
202 |
|
203 "/ try with added colon ... |
|
204 sel := string , ':'. |
|
205 Symbol allInstancesDo:[:sym | |
|
206 (sym startsWith:sel) ifTrue:[ |
|
207 tmp := self explainKnownSymbol:sym inClass:aClass. |
|
208 tmp notNil ifTrue:[ ^ tmp]. |
|
209 ] |
|
210 ]. |
200 "/ ]. |
211 "/ ]. |
201 |
212 |
202 "try for some obvious things" |
213 "try for some obvious things" |
203 tmp := self explainPseudoVariable:string in:aClass. |
214 tmp := self explainPseudoVariable:string in:aClass. |
204 tmp notNil ifTrue:[ ^ tmp]. |
215 tmp notNil ifTrue:[ ^ tmp]. |
236 sym isNil ifTrue:[^ nil]. |
247 sym isNil ifTrue:[^ nil]. |
237 |
248 |
238 "try globals" |
249 "try globals" |
239 |
250 |
240 (Smalltalk includesKey:sym) ifTrue:[ |
251 (Smalltalk includesKey:sym) ifTrue:[ |
241 tmp := '''' , string , ''' is a global variable.'. |
252 tmp := '''' , string asText allBold , ''' is a global variable.'. |
242 val := Smalltalk at:sym. |
253 val := Smalltalk at:sym. |
243 val isBehavior ifTrue:[ |
254 val isBehavior ifTrue:[ |
244 val name = string ifTrue:[ |
255 val name = string ifTrue:[ |
245 tmp := tmp , ' |
256 tmp := tmp , ' |
246 |
257 |