eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'DoWhatIMeanSupport':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: DoWhatIMeanSupport


Inheritance:

   Object
   |
   +--DoWhatIMeanSupport

Package:
stx:libwidg2
Category:
System-Support
Version:
rev: 1.359 date: 2019/08/11 12:25:39
user: cg
file: DoWhatIMeanSupport.st directory: libwidg2
module: stx stc-classLibrary: libwidg2
Author:
Claus Gittinger (cg@exept.de)

Description:


Attention: this is currently being rewritten and refactored.
Don't get mad at the ugly (and duplicate) code.
Will cleanup when finished.

misc collected UI support (functional)
These used to be in the Smalltalk and SystemBrowser class;
however, they are only needed for programmers, and some of the stuff is useful in multiple
places.
Therefore it is:
    1) not needed for standalone executables
    2) published here to avoid multiple implementations


Class protocol:

cleanup
o  lowSpaceCleanup
(comment from inherited method)
ignored here - redefined in some classes to
cleanup in low-memory situations

code completion
o  codeCompletionFor: aspect language: languageOrNil method: methodOrNil orClass: classOrNil context: contextOrNil codeView: codeView into: actionBlock
aspect is so-called code-aspect symbol saying what's edited - #method, #expression, #classDefinition...
contextOrNil is the current context, if this is called from the debugger;
nil, if called from the browser.
If nonNil, we can make better guesses,
because we actually know what a variable's type is.

o  codeCompletionForLanguage: languageOrNil class: classOrNil context: contextOrNil codeView: codeView
contextOrNil is the current context, if this is called from the debugger;
nil, if called from the browser.
If nonNil, we can make better guesses,
because we actually know what a variable's type is.

code completion - helpers
o  findNodeForInterval: interval in: source
utility

o  findNodeForInterval: interval in: source allowErrors: allowErrors

o  findNodeForInterval: interval in: source allowErrors: allowErrors mustBeMethod: mustBeMethod
if mustBeMethod is true, do not try a regular expression (as in a workspace).

o  findNodeForInterval: interval inParseTree: parseTree

o  findNodeIn: aTree forInterval: anInterval
utility

code completion - obsolete
o  codeCompletionForClass: classOrNil context: contextOrNil codeView: codeView
contextOrNil is the current context, if this is called from the debugger;
nil, if called from the browser.
If nonNil, we can make better guesses, because we actually know what a variable's type is.
This is not yet done, sigh

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  codeCompletionForMethod: methodOrNil orClass: classOrNil context: contextOrNil codeView: codeView into: actionBlock
contextOrNil is the current context, if this is called from the debugger;
nil, if called from the browser.
If nonNil, we can make better guesses, because we actually know what a variable's type is.
This is not yet done, sigh

** This is an obsolete interface - do not use it (it may vanish in future versions) **

input completion support
o  classCategoryCompletion: aPartialCategory inEnvironment: anEnvironment
given a partial class category name, return an array consisting of
2 entries: 1st: the best (longest) match
2nd: collection consisting of matching categories

usage example(s):

     Smalltalk classCategoryCompletion:'Sys'
     Smalltalk classCategoryCompletion:'System'
     Smalltalk classCategoryCompletion:'System-BinaryStorage'

o  classNameEntryCompletionBlock
this block can be used in a dialog to perform className completion

o  classnameCompletion: aPartialClassName filter: filterBlock inEnvironment: anEnvironment
given a partial classname, return an array consisting of
2 entries: 1st: the best (longest) match
2nd: collection consisting of matching names

usage example(s):

     Smalltalk classnameCompletion:'Arr'
     Smalltalk classnameCompletion:'Arra'
     Smalltalk classnameCompletion:'arra'
     Smalltalk classnameCompletion:'*rray'

o  classnameCompletion: aPartialClassName inEnvironment: anEnvironment
given a partial classname, return an array consisting of
2 entries: 1st: the best (longest) match
2nd: collection consisting of matching names

usage example(s):

     self classnameCompletion:'Arr'   inEnvironment:Smalltalk
     self classnameCompletion:'Arra'  inEnvironment:Smalltalk
     self classnameCompletion:'arra'  inEnvironment:Smalltalk
     self classnameCompletion:'*rray' inEnvironment:Smalltalk

o  entryCompletionBlockFor: completionSelector
this block can be used in a dialog to perform className completion

o  globalNameCompletion: aPartialGlobalName inEnvironment: anEnvironment
given a partial globalName, return an array consisting of
2 entries: 1st: the best (longest) match
2nd: collection consisting of matching names

o  globalNameCompletion: aPartialGlobalName inEnvironment: anEnvironment match: doMatch
given a partial globalName, return an array consisting of
2 entries: 1st: the best (longest) match
2nd: collection consisting of matching names

o  methodProtocolCompletion: aPartialProtocolName inEnvironment: anEnvironment
given a partial method protocol name, return an array consisting of
2 entries: 1st: the best (longest) match
2nd: collection consisting of matching protocols

usage example(s):

     Smalltalk methodProtocolCompletion:'doc'
     Smalltalk methodProtocolCompletion:'docu'
     Smalltalk methodProtocolCompletion:'documenta'

o  nameSpaceCompletion: aPartialClassName inEnvironment: anEnvironment
given a partial name, return an array consisting of
2 entries: 1st: the best (longest) match
2nd: collection consisting of matching names

usage example(s):

     DoWhatIMeanSupport nameSpaceCompletion:'To'  inEnvironment:Smalltalk

o  packageCompletion: aPartialPackage inEnvironment: anEnvironment
given a partial package name, return an array consisting of
2 entries: 1st: the best (longest) match
2nd: collection consisting of matching packages

usage example(s):

     DoWhatIMeanSupport packageCompletion:'stx:' inEnvironment:Smalltalk
     DoWhatIMeanSupport packageCompletion:'stx:libw' inEnvironment:Smalltalk

o  packageNameEntryCompletionBlock
this block can be used in a dialog to perform className completion

o  poolnameCompletion: aPartialClassName inEnvironment: anEnvironment
given a partial poolname, return an array consisting of
2 entries: 1st: the best (longest) match
2nd: collection consisting of matching names

usage example(s):

     self poolnameCompletion:'Win' inEnvironment:Smalltalk
     self poolnameCompletion:'Z'   inEnvironment:Smalltalk
     self poolnameCompletion:'a'   inEnvironment:Smalltalk

o  resourceCompletion: aPartialResourceName inEnvironment: anEnvironment match: doMatch ignoreCase: ignoreCase
given a partial resource name, return an array consisting of
2 entries: 1st: the longest match
2nd: collection consisting of matching defined resources

usage example(s):

     DoWhatIMeanSupport resourceCompletion:'*debug*' inEnvironment:Smalltalk match:true ignoreCase:false
     DoWhatIMeanSupport resourceCompletion:'context' inEnvironment:Smalltalk match:true ignoreCase:false
     DoWhatIMeanSupport resourceCompletion:'key' inEnvironment:Smalltalk match:true ignoreCase:false
     DoWhatIMeanSupport resourceCompletion:'cont' inEnvironment:Smalltalk match:true ignoreCase:false

o  selectorCompletion: aPartialSymbolName inEnvironment: anEnvironment
given a partial selector, return an array consisting of
2 entries: 1st: the longest match
2nd: collection consisting of matching implemented selectors

o  selectorCompletion: aPartialSymbolName inEnvironment: anEnvironment match: doMatch
given a partial selector, return an array consisting of
2 entries: 1st: the longest match
2nd: collection consisting of matching implemented selectors

usage example(s):

     DoWhatIMeanSupport selectorCompletion:'inst*p' inEnvironment:Smalltalk match:true
     DoWhatIMeanSupport selectorCompletion:'inst*pl' inEnvironment:Smalltalk match:true
     DoWhatIMeanSupport selectorCompletion:'at:p' inEnvironment:Smalltalk match:true
     DoWhatIMeanSupport selectorCompletion:'nextP' inEnvironment:Smalltalk match:true
     DoWhatIMeanSupport selectorCompletion:'nextp' inEnvironment:Smalltalk match:true

o  selectorCompletion: aPartialSymbolName inEnvironment: anEnvironment match: doMatch ignoreCase: ignoreCase
given a partial selector, return an array consisting of
2 entries: 1st: the longest match
2nd: collection consisting of matching implemented selectors

usage example(s):

     DoWhatIMeanSupport selectorCompletion:'inst*p' inEnvironment:Smalltalk match:true
     DoWhatIMeanSupport selectorCompletion:'inst*pl' inEnvironment:Smalltalk match:true
     DoWhatIMeanSupport selectorCompletion:'at:p' inEnvironment:Smalltalk match:true
     DoWhatIMeanSupport selectorCompletion:'nextP' inEnvironment:Smalltalk match:true
     DoWhatIMeanSupport selectorCompletion:'nextp' inEnvironment:Smalltalk match:true

rename support
o  goodRenameDefaultFor: oldName lastOld: lastOldName lastNew: lastNewName
generate a reasonable default for a rename operation.
(used for rename category etc.)

usage example(s):

     self goodRenameDefaultFor:'bar' lastOld:'foo' lastNew:'fooXX'
     self goodRenameDefaultFor:'bar' lastOld:'foo' lastNew:'XXfoo'

     self goodRenameDefaultFor:'barXX' lastOld:'fooXX' lastNew:'foo'
     self goodRenameDefaultFor:'XXbar' lastOld:'XXfoo' lastNew:'foo'

     self goodRenameDefaultFor:'barXX' lastOld:'fooXX' lastNew:'fooYY'
     self goodRenameDefaultFor:'XXbar' lastOld:'XXfoo' lastNew:'foo'

     self goodRenameDefaultFor:'bar2' lastOld:'foo1' lastNew:'foo01'
     self goodRenameDefaultFor:'barXY' lastOld:'fooXY' lastNew:'fooY'
     self goodRenameDefaultFor:'bar' lastOld:'foo' lastNew:'fXoo'
     self goodRenameDefaultFor:'bar' lastOld:'foo' lastNew:'fXXXoo'
     self goodRenameDefaultFor:'bar' lastOld:'foo' lastNew:'foXXXo'

     self goodRenameDefaultFor:'bar001' lastOld:'foo001' lastNew:'foo002_001'
     self goodRenameDefaultFor:'CoastCore-CSFoo' lastOld:'CoastCore-CSBar' lastNew:'Coast-Core-CSBar'

     self goodRenameDefaultFor:'mti.odt2.level1HeadlineStyle'
                       lastOld:'mti.odt2.level1HeadlineMatchPattern'
                       lastNew:'Key_odt2_level1HeadlineMatchPattern'

o  goodRenameDefaultForFile: oldName lastOld: lastOldName lastNew: lastNewName
generate a reasonable default for a file rename operation.
(Try to rename multiple files in the new fileBrowser,
to see what this is doing)

typing distance
o  isKey: k1 nextTo: k2
return true, if k1 and k2 are adjacent keys on the keyboard.
This is used to specially priorize plausible typing errors of adjacent keys.
CAVEAT: hard coded us-, german and french keyboards here; data should come from somewhere else.

usage example(s):

     self isKey:$a nextTo:$a
     self isKey:$a nextTo:$s
     self isKey:$a nextTo:$q
     self isKey:$a nextTo:$w
     self isKey:$a nextTo:$z
     self isKey:$a nextTo:$x

o  isKey: k1 nextTo: k2 onKeyboard: keys
return true, if k1 and k2 are adjacent keys on the keyboard defined by keys.
This is used to specially priorize plausible typing errors of adjacent keys.
(typo checker uses a modified levenshtein,
in which keys next to each other are valued differently)

usage example(s):

     self isKey:$a nextTo:$q
     self isKey:$a nextTo:$x

o  keyboard
the keyboard layout
(useful to figure out which keys are nearby a key, to find possible typing errors)
CAVEAT: hard coded us-, german and french keyboards here; data should come from somewhere else.

usage example(s):

     self keyboard


Instance protocol:

code completion
o  codeCompletionFor: codeAspectArg language: languageOrNilArg method: methodOrNilArg orClass: classOrNilArg context: contextOrNilArg codeView: codeViewArg into: actionBlock
provide code completion information by analyzing what the editing state is in codeViewArg
(cursor position, characters around cursor etc.) and calling back into actionBlock, passing
the info as argument.
The interface has been defined in that way
(and tight coupling with internals of the editor) because
1) the completer needs to know about the text around the cursor position
2) the edit operation for completion may be non-trivial
(although not yet fully implemented, non-local rewrite procedures may and will be added in the future
For example, in many situations, both a completion of a unary selector before the cursor,
or adding another keyword part after the cursor is possible.
Thus, this provides a list of completions PLUS a list of edit operations (as per completion), to
perform the completion.
The caller has to open a dialog, providing the suggestions, and perform the corresponding edit operation.
An additional array containing a textual description for each suggestion is also provided, which could
be shown as info or appended to the suggestions (such as 'complete variable', 'complete keyword', etc.

ContextOrNil is the current context, if this is called from the debugger;
or nil, if called from the browser.
If nonNil, we can make better guesses, because we actually know what a variable's type is

o  codeCompletionForLanguage: languageOrNil class: classOrNilArg context: contextOrNilArg codeView: codeViewArg
going to become OBSOLETE; migrating to use the the new 'xxx: into:' protocol.
contextOrNil is the current context, if this is called from the debugger;
nil, if called from the browser.
If nonNil, we can make better guesses,
because we actually know what a variable's type is.

o  setClass: classOrNilArg andContext: contextOrNilArg

o  setSelf: instanceOrNilArg

code completion - JavaScript
o  codeCompletionForJavascriptMethod: methodOrNilArg orClass: classOrNilArg context: contextOrNilArg codeView: codeViewArg into: actionBlock
provide code completion information by analyzing what the editing state is in codeViewArg
(cursor position, characters around cursor etc.) and calling back into actionBlock, passing
the info as argument.
The interface has been defined in that way
(and tight coupling with internals of the editor) because
1) the completer needs to know about the text around the cursor position
2) the edit operation for completion may be non-trivial
(although not yet fully implemented, non-local rewrite procedures may and will be added in the future
For example, in many situations, both a completion of a unary selector before the cursor,
or adding another keyword part after the cursor is possible.
Thus, this provides a list of completions PLUS a list of edit operations (as per completion), to
perform the completion.
The caller has to open a dialog, providing the suggestions, and perform the corresponding edit operation.
An additional array containing a textual description for each suggestion is also provided, which could
be shown as info or appended to the suggestions (such as 'complete variable', 'complete keyword', etc.

ContextOrNil is the current context, if this is called from the debugger;
or nil, if called from the browser.
If nonNil, we can make better guesses, because we actually know what a variable's type is

code completion - Smalltalk
o  codeCompletionForSmalltalkClass: classOrNilArg context: contextOrNilArg codeView: codeViewArg
OBSOLETE; migrating to use the the new 'xxx: into:' protocol.
contextOrNil is the current context, if this is called from the debugger;
nil, if called from the browser.
If nonNil, we can make better guesses, because we actually know what a variable's type is.
This is not yet done, sigh

o  codeCompletionForSmalltalkMethod: methodOrNilArg orClass: classOrNilArg context: contextOrNilArg codeView: codeViewArg into: actionBlock
provide code completion information by analyzing what the editing state is in codeViewArg
(cursor position, characters around cursor etc.) and calling back into actionBlock, passing
the info as argument.
The interface has been defined in that way
(and tight coupling with internals of the editor)
because
1) the completer needs to know about the text around the cursor position
2) the edit operation for completion may be non-trivial
(although not yet fully implemented, non-local rewrite procedures may and will be added in the future)

For example, in many situations, both a completion of a unary selector before the cursor,
or adding another keyword part after the cursor is possible.
Thus, this provides a list of completions PLUS a list of edit operations (as per completion),
to perform the completion.
The caller has to open a dialog, providing the suggestions, and perform the corresponding edit operation.
An additional array containing a textual description for each suggestion is also provided, which could
be shown as info or appended to the suggestions (such as 'complete variable', 'complete keyword', etc.

ContextOrNil is the current context, if this is called from the debugger;
or nil, if called from the browser.
If nonNil, we can make better guesses, because we actually know what a variable's type is

code completion - helpers
o  askUserForCompletion: what for: codeView at: position from: allTheBest
cg: until the new stuff works,...

o  askUserForCompletion: what for: codeView from: allTheBest

o  codeCompletionForBlockArgument: node into: actionBlock

o  codeCompletionForLiteralString: partialString node: node considerAll: considerAll into: actionBlock
nothing done here, but redefined in subclasses which may (i.e. expecco code completer)

o  codeCompletionForLiteralString: partialString node: node in: source considerAll: considerAll into: actionBlock
nothing done here, but redefined in subclasses which may (i.e. expecco code completer)

o  codeCompletionForLiteralSymbol: nodeOrNil element: tokenOrNil considerAll: considerAll into: actionBlock
looking for all symbols is way too much and imprecise;
experiment: only present symbols which are used by the class,
and classes in that class category, or at least: implemented as method.
We'll see...

o  codeCompletionForMessage: node into: actionBlock
find good completions for a message selector in a message-send node

o  codeCompletionForMessageTo: node into: actionBlock
find good suggestions for a message send to node, with no input yet.
I.e. right after a receiver (w.o. any input yet)

o  codeCompletionForMethodSpec: node
completion in a method's selector pattern

o  codeCompletionForMethodSpec: node into: actionBlock
completion in a method's selector pattern

o  codeCompletionForTempVariable: node into: actionBlock

o  codeCompletionForVariable: node into: actionBlock
Transcript show:'var in '; show:methodOrNil; show:' / '; showCR:classOrNil.

o  editActionToInsert: aString

o  editActionToInsertFromSuggestions: suggestions

o  editActionToReplaceCodeFrom: start to: stop by: aString

o  editActionToReplaceCodeFrom: start to: stop byWordIn: suggestions

o  editActionToReplaceNode: node by: word

o  editActionToReplaceNode: node byWordIn: suggestions

o  findBest: node for: selector inClasses: srchClassesArg
find the best suggestions for a partial selector in a given set of classes.
Notice: the returned collection is unsorted; it needs some postprocessing to
present the most reasonable items first

o  findNodeForInterval: interval in: source

o  findNodeForInterval: interval in: source allowErrors: allowErrors

o  findNodeForInterval: interval in: source allowErrors: allowErrors mustBeMethod: mustBeMethod
if mustBeMethod is true, do not try a regular expression (as in a workspace).

o  findNodeForInterval: interval in: source allowErrors: allowErrors mustBeMethod: mustBeMethod mustBeExpression: mustBeExpression
parse source, and find the node which is in the given interval
(typically a selection or a word in the source).

parse it as expression or method;
if mustBeMethod is true, do not try as expression;
if mustBeExpression is true, do not try as method
expression syntax parsing is done in workspaces (doIt).

Big hack as workaround a limitation of RBParser:
in case of an error, the parent chain of a node is usually not yet set.
(because the code is written as:
parentNode addChild:(self parseChild)
and the parent-chain of the parsed child is set in addChild).
However:
when doing code completion, having invalid syntax to parse is the normal case.

Workaround:
remember created nodes as the parse proceeds.
Thus, I can construct a partial the parent chain.

o  findNodeForInterval: interval inParseTree: parseTree

o  findNodeIn: aTree forInterval: anInterval

o  insertAdditonalStuffAfterSelector: chosenCompletion
codeView cursorLeft:1+extra size.

o  messagesSentTo: varName in: aTree
collect messages sent

o  old_askUserForCompletion: what for: codeView from: allTheBest
move tha last choice to the top of the list, if it is in.

o  sortSelectors: list forSelector: selector lcSelector: lcSelector
(a startsWith:'sho') ifTrue:[

o  sortUsefulSelectorsIn: selectorList
cosmetics:

o  splitSelectorList: list by: condition

o  treeForCode: source allowErrors: allowErrors
parserOrNil isNil if raised by the scanner

o  tryCodeCompletionWithSource: source nodeInterval: interval at: characterPositionOfCursor mustBeExpression: mustBeExpression into: actionBlock
this is tried multiple times;
first with cursor line only
then with the source copied up to the cursor position,
then with the full source.
Either one may give better results (for example, when completing
after a keyword selector, and the remaining code would lead to a syntactically
legal, but stupid message send to be parsed...
(which happens often after inserting)

o  withoutSelectorsUnlikelyFor: aClass from: selectorsArg forPartial: partialSelector
some heuristics;
as best selectors has been chosen by implemented methods for aClass,
some of them should be filtered (for example, at:/at:put:, which are
found in object, but only make sense for variable objects or those which do
implement at:put: themself.
I have currently no better idea than hardcoding stuff I found irritating...

code completion - helpers-old
o  codeCompletionForLiteralSymbol: node inClass: classOrNil codeView: codeView
self showInfo:best.

o  codeCompletionForMessage: node inClass: classOrNil instance: instanceOrNil context: contextOrNil codeView: codeView
going to be OBSOLETE

o  codeCompletionForVariable: node inClass: classOrNil codeView: codeView
if we are behind the variable and a space has already been entered,

code completion - obsolete
o  codeCompletionForClass: classOrNilArg context: contextOrNil codeView: codeViewArg
OBSOLETE; migrating to use the the new 'xxx: into:' protocol.
contextOrNil is the current context, if this is called from the debugger;
nil, if called from the browser.
If nonNil, we can make better guesses, because we actually know what a variable's type is.
This is not yet done, sigh

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  codeCompletionForMethod: methodOrNilArg orClass: classOrNilArg context: contextOrNilArg codeView: codeViewArg into: actionBlock

helpers - naive type inference
o  addClassesFromAssignmentTo: varName in: aTree to: setOfTypes
assignments...

o  addClassesFromMessagesSentTo: varNode in: aTree to: setOfTypes
from the set of messages sent at other places,

o  addClassesOfBlockVarForWellknownBlocks: variableNode inScope: blockScope to: setOfTypes
if the parent of the block is an enumeration message, and the receiver is known,

o  addClassesOfExpression: expr inClass: classOrNil to: setOfPossibleClasses
and:[expr name = 'secondsOrNil']

o  addClassesOfInstVarNamed: varName inClass: aClass to: setOfTypes
ask the class

o  addClassesOfMessage: expr inClass: classOrNil to: setOfTypes
heuristic: quickly assume boolean for some:

o  addClassesOfVariable: varName inExpression: expr inClass: classOrNil to: setOfPossibleClasses
expr is either a variable-node or a message in which varName is the selector

o  classOfNode: aNode
returns the class of a receiver, if it is well-known.
Otherwise nil (either unknown, or multiple possibilities)
When showing possible completions for a message,
it is a good idea to know what the receiver is.

o  classesFromAssignmentTo: varName in: aTree

o  classesOfInstVarNamed: varName inClass: aClass

o  classesOfNode: aNode
returns the set of possible classes of a parsenode.
or nil if unknown.
When showing possible completions for a message,
it is a good idea to know what the kind receiver is.

o  extractConstraintsFor: expr inClass: dummyClassOrNil
see if expr is contained inside an isXXX ifTrue:[...]
then, we know a lot more...
For example, to expand possible messages for XXX in:
foo isString ifTrue:[
f XXX
].
we now have to care for instances for which isString returns true only

o  isNonDestructive: aMessageNode whenSentTo: receiverValue
return true, if it is safe to send aSelector to receiverValue
(i.e. has no side effects)

o  valueAndKindOfVariable: aVariableName
when showing possible completions for a variable,
it is a good idea to know what the reveiver's value is.
Sigh - returns nil as value both if unknown AND if a real nil is there

o  valueOfNode: aNode
when showing possible completions for a message,
it is a good idea to know what the reveiver's value is.
Sigh - returns nil both if unknown AND if a real nil is there.

o  valueOfVariable: aVariableName
when showing possible completions for a variable,
it is a good idea to know what the reveiver's value is.
Sigh - returns nil both if unknown AND if a real nil is there.

setup
o  classResolverHook: aBlock
additional hook to allow for special class resolving.
If non-nil, this hook is called for expression nodes,
and may return a class or nil.
Used eg. with expecco to resolve pin types

usage example(s):

     self new classResolverHook:[:expr |
         (expr isVariable and:[expr name = 'foo']) ifTrue:[
             { String }
         ] ifFalse:[
             nil
         ]
     ].

o  language: aProgrammingLanguage


Private classes:

    InputCompletionResult


ST/X 7.2.0.0; WebServer 1.670 at bd0aa1f87cdd.unknown:8081; Fri, 29 Mar 2024 14:34:45 GMT