thanks for your analysis I will have a look at it. I was thinking to check if I should redefine UndefinedObject>>subclass: to raise an error
Stef On Dec 3, 2013, at 3:17 PM, Clément Bera <[email protected]> wrote: > do you know if the OCUndeclaredVariable is raised for unknown superclass? > > this code: > > AnUnknownClass subclass: #Adaptor1Example > instanceVariableNames: 'customers accountID address name phoneNumber' > classVariableNames: '' > poolDictionaries: '' > category: 'Examples-Cookbook' > > is run as a Do It. In Do It, unknown variables (as here AnUnknownClass) raise > an OCUndeclaredVariableWarning. > For example, running: > > AnUnknownClass subclass: #Adaptor1Example > instanceVariableNames: 'customers accountID address name phoneNumber' > classVariableNames: '' > poolDictionaries: '' > category: 'Examples-Cookbook' > > executes the default action for OCUndeclaredVariableWarning, which is opening > a pop-up titled: "Unknown variable ...". Here the error is raised at > compilation time, therefore it would have no effect to wrap this with a > #on:do: > > [ AnUnknownClass subclass: #Adaptor1Example > instanceVariableNames: 'customers accountID address name phoneNumber' > classVariableNames: '' > poolDictionaries: '' > category: 'Examples-Cookbook' ] on: OCSemanticWarning do: [ ] > > ==> same problem. > > Now if you do: > > [ OpalCompiler new evaluate: 'AnUnknownClass subclass: #Adaptor1Example > instanceVariableNames: ''customers accountID address name > phoneNumber'' > classVariableNames: '''' > poolDictionaries: '''' > category: ''Examples-Cookbook''' ] on: OCSemanticWarning do: [ :e | e > halt ] > > Here we catch the error, and you can handle it. > Now it is not easily possible to resume the error, because you want a global > instead and Opal expects a temp (there are way to resume but with very deep > stack manipulation that I do not want to show to young pharoers present on > this mailing list). So the best is to retry it. One solution is therefore: > > [ OpalCompiler new evaluate: 'AnUnknownClass subclass: #Adaptor1Example > instanceVariableNames: ''customers accountID address phoneNumber'' > classVariableNames: '''' > poolDictionaries: '''' > category: ''Examples-Cookbook''' ] > on: OCSemanticWarning do: [ :e | > Smalltalk at: e node name put: StubRootClass. > e retry ] > > with e node name answering #AnUnknownClass here. > Now you need to make sure that the exception block is executed for the case > of a missing superclass and not something else or you will end up creating > loads of globals. > > The exception block should be something similar to: > > [ :e | > e node name first isUppercase and: [ "some condition" ] ifTrue: [ > Smalltalk at: e node name put: StubRootClass. > ^ e retry ]. > e pass ] > > How to undefined and OCUndeclaredVariableWarning relate? > > In your case, while loading from Monticello the code is compiled and > evaluated in non interactive mode. Therefore it cannot trigger the default > action of OCUndeclaredVariableWarning which is a UI event. So it sets by > default the unknown global to: > > Undeclared at: varName asSymbol put: nil. > OCUndeclaredVariable new name: varName asSymbol > > in: OCUndeclaredVariableWarning >>defaultAction > > which then later triggers the code in UndefinedObject. > > > > 2013/12/3 Stéphane Ducasse <[email protected]> > > On Dec 3, 2013, at 11:20 AM, Clément Bera <[email protected]> wrote: > >> Then for your project replace ProtoObject by StubRootClass in >> UndefinedObject>>subclass:instanceVariableNames:classVariableNames:poolDictionaries:category: >> it will work. > > yes but this is ugly because I do not want override. > So I will introduce an exception so that we can do that in a clean way. > > >> An alternative is to catch OCSemanticWarning or its subclass >> OCUndeclaredVariableWarning while loading the new classes and execute >> another code instead of the default action in the exception handling block > > > do you know if the OCUndeclaredVariable is raised for unknown superclass? > How to undefined and OCUndeclaredVariableWarning relate? > > Stef >> >> >> 2013/12/3 Stéphane Ducasse <[email protected]> >> > Well if the class does not exists it calls the method on UndefinedObject >> > (UndeclaredBinding). And you have: >> >> I will check and see if I can set up a hook because having classes >> subclasses of protoobject is not a good idea >> when loading broken code. >> >> > UndefinedObject>>subclass: nameOfClass >> > instanceVariableNames: instVarNames >> > classVariableNames: classVarNames >> > poolDictionaries: poolDictnames >> > category: category >> > "Calling this method is now considered an accident. If you really >> > want to create a class with a nil superclass, then create the class and >> > then set the superclass using #superclass:" >> > self traceCr: ('Attempt to create ', nameOfClass, ' as a subclass of >> > nil. Possibly a class is being loaded before its superclass.'). >> > ^ProtoObject >> > subclass: nameOfClass >> > instanceVariableNames: instVarNames >> > classVariableNames: classVarNames >> > poolDictionaries: poolDictnames >> > category: category >> > >> > The best is to set manually the superclass after with #superclass: >> >> No because I have no idea what are the classes whose superclasses are not in >> the image. >> With a proper hook I could just say >> if the superclass is unknow please use the "StubRootClass" of my >> framework. >> else let the system handles it. >> >> Stef >> > >
