dolphinsmalltalk / Dolphin

Dolphin Smalltalk Core Image
MIT License
301 stars 58 forks source link

Methods of Namespace classes compiled in custom environment cannot bind identifiers imported into that environment #1129

Closed blairmcg closed 2 years ago

blairmcg commented 3 years ago

This bug requires some background explanation to understand.

In Dolphin8, unqualified static variable names in code are normally resolved in the context of the method's class. The search proceeds from locally defined (class) variables, up through the superclass chain, looks in the class' environment (namespace), and finally searches for bindings in imported namespaces. Imports of the class itself, its superclass chain, and into its environment are considered.

It is also possible to compile methods in a specific namespace. This can be useful, for example, when adding extension methods in a package to a class owned by another package. For example the IDE packages define a large number of extension methods in Core and Kernel classes that mainly reference variables in the Tools namespace. It makes sense, therefore, to compile these methods in the Tools namespace to avoid having to fully qualify Tools class references. Another use case is for loading legacy packages. All legacy classes are defined in the Smalltalk namespace. Extension methods in the legacy package, however, may extend namespaced classes that no longer have visibility of identifiers in Smalltalk, and so the methods may fail to compile with undefined references to classes defined in the same package! To avoid this problem, legacy packages compile all extension methods as if their binding environment were Smalltalk.

As Dolphin8 namespaces are actually classes (i.e. each namespace is a subclass of the Namespace class, rather than an instance of it), they can also define their own methods to add behaviour. Packages can also extend Namespace classes like any other, and the extension methods can be compiled in a different namespace as with any other methods. The bug is that extension methods of Namespace classes that are compiled in a different namespace will fail to resolve bindings via the imports of the custom namespace.

An example is the canModifyBinding:newValue: method of SharedPool class:

canModifyBinding: aVariableBinding newValue: anObject
    #namespaceToDo. "Due to an oddity of Namespace redefining Class>>resolveImportedBinding:, variables of UI will not be found here by unqualified name even though imported into the Tools namespace in which this method is compiled."

    ^UI.ConfirmationRequiredWarning
        signal: ('Would you like to recompile references to <1p>.<2s> to reflect the new value <3p> (currently <4p>)?'
                expandMacrosWith: self
                with: aVariableBinding key
                with: anObject
                with: aVariableBinding value)

This method is compiled in the Tools namespace. Tools imports UI, so it should not be necessary to qualify the reference to ConfirmationRequiredWarning, as the unqualified name should be found through that import.

The bug is caused by the Namespace class override of the Class>>resolveImportedBinding: method.