eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'ParseTreeSearcher':

Home

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

Class: ParseTreeSearcher


Inheritance:

   Object
   |
   +--RBProgramNodeVisitor
      |
      +--ParseTreeSearcher
         |
         +--ParseTreeRewriter

Package:
stx:goodies/refactoryBrowser/parser
Category:
Refactory-ParseTree Matching
Version:
rev: 1.73 date: 2019/07/21 06:32:34
user: cg
file: ParseTreeSearcher.st directory: goodies/refactoryBrowser/parser
module: stx stc-classLibrary: parser

Description:


ParseTreeSearcher walks over a normal source code parse tree using the visitor pattern, and then matches these nodes against the meta-nodes using the match:inContext: methods defined for the meta-nodes.

Instance Variables:
	answer  <Object>        the "answer" that is propagated between matches
	argumentSearches        <Collection of: (Association key: BRProgramNode value: BlockClosure)>   argument searches (search for the BRProgramNode and perform the BlockClosure when its found)
	context <BRSmallDictionary>     a dictionary that contains what each meta-node matches against. This could be a normal Dictionary that is created for each search, but is created once and reused (efficiency).
	searches        <Collection of: (Association key: BRProgramNode value: BlockClosure)>   non-argument searches (search for the BRProgramNode and perform the BlockClosure when its found)
	currentSearchContext    the current search context (from checkMethod:) so that match rules can determine where they are (see RBToDoFillRule)


Class protocol:

accessing
o  treeMatching: aString in: aParseTree

o  treeMatchingStatements: aString in: aParseTree

instance creation
o  allMessageSends
return a searcher which searches all messageSends
(collects messageSend nodes)

o  allMessageSendsForWhich: aFilter
return a searcher which searches all messageSends
(collects messageSend nodes)

o  allMessageSendsMatching: pattern ignoreCase: doIgnoreCase
return a searcher which searches all messageSends which match a given pattern
(collects messageSend nodes)

o  allMessageSendsMatchingAny: patternCollection ignoreCase: doIgnoreCase
return a searcher which searches all messageSends which match any pattern of a given set of patterns
(collects messageSend nodes)

o  allMessageSendsTo: searchSelector ignoreCase: doIgnoreCase
return a searcher which searches all messageSends with a particular selector
(collects messageSend nodes)

o  allMessageSendsToAny: selectorCollection ignoreCase: doIgnoreCase
return a searcher which searches all messageSends with a selector from a given set of selectors
(collects messageSend nodes)

o  allModificationsOfAnyVariableIn: aCollectionOfVariableNames
return a searcher which searches all modifications of any variable in aCollectionOfVariableNames
(collects assignment nodes)

o  allModificationsOfGlobalVariablesMatching: aFilter
return a searcher which searches all variable modifications
(collects assignement nodes)

o  allModificationsOfVariablesMatching: aFilter
return a searcher which searches all variable modifications
(collects assignement nodes)

o  allReadsOfAnyVariableIn: aCollectionOfVariableNames
return a searcher which searches all reads of any variable in aCollectionOfVariableNames
(collects variable nodes)

o  allReadsOfVariablesMatching: aFilter
return a searcher which searches all variable reads
(collects variable nodes)

o  allReferencesToAnyVariableIn: aCollectionOfVariableNames
return a searcher which searches all references to any variable in aCollectionOfVariableNames
(collects variable nodes)

o  allReferencesToVariablesMatching: aFilter
return a searcher which searches all variable references
(collects variable nodes)

o  getterMethod: aVarName
return a searcher which matches a getter method.
Returns nil if no match, the selector if it does.

o  handlesException
return a searcher which matches a method which handles an exception.
Returns false if no match, true otherwise.

o  hasGuardingIf
|tree searcher|

tree := RBParser
parseSearchMethod:'foo:arg arg ifTrue:[ arg fooBar ]'
onError: [:str :pos | nil].

searcher := self hasGuardingIf.
searcher executeTree:tree initialAnswer:false.

tree := RBParser
parseSearchMethod:'foo:arg arg fooBar'
onError: [:str :pos | nil].

searcher := self hasGuardingIf.
searcher executeTree:tree initialAnswer:false.

o  isGetterMethod
return a searcher which matches any getter method.
Returns false if no match, true if it does.

o  isGetterOrSetterMethod
return a searcher which matches a getter or setter method.
Returns false if no match, true if it does.

o  isGetterOrSetterMethod: aVarName
return a searcher which matches a getter or setter method for aVarName.
Returns false if no match, true if it does.

o  isJustReturningItsArgument
return a searcher which matches a simple ^ arg.
That method definitely has no side effects.
Returns false if no match, true if it does.

usage example(s):

should match

     |tree searcher|

     tree := RBParser
                     parseSearchMethod:'foo:arg ^arg'
                     onError: [:str :pos | nil].

     searcher := ParseTreeSearcher isJustReturningItsArgument.
     searcher executeTree:tree initialAnswer:false.

usage example(s):

should NOT match

     |tree searcher|

     tree := RBParser
                     parseSearchMethod:'foo:arg1 foo:arg2 ^arg1'
                     onError: [:str :pos | nil].

     searcher := ParseTreeSearcher isJustReturningItsArgument.
     searcher executeTree:tree initialAnswer:false.

usage example(s):

should NOT match
     |tree searcher|

     tree := RBParser
                     parseSearchMethod:'foo ^123'
                     onError: [:str :pos | nil].

     searcher := ParseTreeSearcher isJustReturningItsArgument.
     searcher executeTree:tree initialAnswer:false.

usage example(s):

should NOT match
     |tree searcher|

     tree := RBParser
                     parseSearchMethod:'foo ^ bar'
                     onError: [:str :pos | nil].

     searcher := ParseTreeSearcher isJustReturningItsArgument.
     searcher executeTree:tree initialAnswer:false.

usage example(s):

should NOT match
     |tree searcher|

     tree := RBParser
                     parseSearchMethod:'foo ^ 123 bla'
                     onError: [:str :pos | nil].

     searcher := ParseTreeSearcher isJustReturningItsArgument.
     searcher executeTree:tree initialAnswer:false.

o  isJustReturningLiteralString: aLiteralString
return a searcher which matches a simple ^ literal.
Returns false if no match, true if it does.
Notice the somewhat misleading name of this method:
not a string-literal, but the string of a literal is passed in;
i.e. to test for a true-returner, pass 'true',
but for a true-string returner, pass '''true''' (with quotes).

ATTENTION:
the original implementation (from RefactoryInc/Squeak) only matched unary methods;
this was changed in ST/X to also match methods with arguments
(i.e. `@methods instead of `methods in the match pattern)

o  isJustReturningSelf
return a searcher which matches a simple ^ self.
That method definitely has no side effects.
Returns false if no match, true if it does.

ATTENTION:
matches methods with or without arguments

o  isJustReturningSomething
return a searcher which matches a simple ^ something.
That method definitely has no side effects.
Returns false if no match, true if it does.

ATTENTION:
the original implementation (from RefactoryInc/Squeak) only matched unary methods;
this was changed in ST/X to also match methods with arguments
(i.e. `@method instead of `method in the match pattern)

o  isJustReturningTrue
return a searcher which matches a simple ^true method (i.e. a tester).
Returns false if no match, true if it does.

ATTENTION:
the original implementation (from RefactoryInc/Squeak) only matched unary methods;
this was changed in ST/X to also match methods with arguments
(i.e. `@methods instead of `methods in the match pattern)

o  isJustReturningTrueOrFalse
return a searcher which matches a simple ^true or ^false method (i.e. a tester).
Returns false if no match, true if it does.

ATTENTION:
the original implementation (from RefactoryInc/Squeak) only matched unary methods;
this was changed in ST/X to also match methods with arguments
(i.e. `@methods instead of `methods in the match pattern)

o  isSetterMethod
return a searcher which matches a setter method.
Returns false if no match, true if it does.

o  isSubclassResponsibility
return a searcher which matches a simple 'self subclassResponsibility'.
Returns false if no match, true if it does.

o  justDelegates
return a searcher which matches a delegating method.
Returns false if no match, true if it does.

o  justSendsSuper
return a searcher which matches a super-sending method.
Returns false if no match, true if it does.

o  raisesException
return a searcher which matches a method which raises an exception.
Returns false if no match, true otherwise.

o  returnSetterMethod: aVarName
return a searcher which matches a returning setter method.
Returns nil if no match, the selector if it does.

o  setterMethod: aVarName
return a searcher which matches a setter method.
Returns nil if no match, the selector if it does.

private
o  buildSelectorString: aSelector

o  buildSelectorTree: aSelector

o  buildTree: aString method: aBoolean

utilities
o  isDefinitelyGetterMethod: aMethod
checks a method for being a true getter (name equals variable returned)

o  matchMethod: aMethod with: aMatcher
common helper for common matches

o  methodIsGetterMethod: aMethod
checks a method for being a true getter (name equals variable returned)

o  methodIsJustReturningSomething: aMethod
checks a method for being a simple return something method
(i.e. definitely no side effects)

usage example(s):

     self methodIsJustReturningSomething:(Workflow::AbstractPin compiledMethodAt:#owner)

o  methodIsJustReturningTrue: aMethod
checks a method for being a simple return true method
(i.e. definitely no side effects)

usage example(s):

     self methodIsJustReturningTrue:(TimeDuration compiledMethodAt:#isTimeDuration)

o  methodIsSetterMethod: aMethod
checks a method for being a true setter (name equals variable returned)


Instance protocol:

accessing
o  addArgumentRule: aParseTreeRule

o  addArgumentRules: ruleCollection

o  addArgumentSearches: aSearchCondition

o  addMethodSearches: aSearchCondition

o  addRule: aParseTreeRule

o  addRules: ruleCollection

o  addSearches: aSearchCondition

o  answer

o  computeQuickSearchStrings
Compute a collection of OR-strings to search for.
Each is a string or collection of AND-strings.
This is collected from the individual searches,
of which each may return a collection of AND-strings.
OR means: if any of the elements is present, do a full match;
otherwise reject.
AND means: all of the elements must be present for a full match,
otherwise reject

o  context

o  currentSearchContext

o  currentSearchContext: aSearchContext

o  executeMethod: aParseTree

o  executeMethod: aParseTree initialAnswer: anObject

o  executeTree: aParseTree
Save our current context, in case someone is performing another search inside a match.

o  executeTree: aParseTree initialAnswer: aValue

o  messages
in ST/X, optimized messages are also in the literal array..

o  moreAnswers
if the rule found multiple places, this returns the other answers

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

o  searches

o  setMessages: aCollection

converting
o  asSearcher

enumerating
o  matchingNodesForSource: aString tree: anRBProgramNode do: aBlock
Evaluate block for each node in source and its corresponding tree that matches

o  selectionIntervalsForSource: aString tree: anRBProgramNode do: aBlock
Evaluate block for each node's sourceInterval (for highlighting)

o  selectionIntervalsForSource: aString tree: anRBProgramNode in: aClass do: aBlock
Evaluate block for each node's sourceInterval (for highlighting)

o  selectionIntervalsForSource: aString tree: anRBProgramNode rule: aRuleOrNil in: aClass do: aBlock
Evaluate block for each node's sourceInterval (for highlighting).
If aRuleOrNil is not nil, it is given a chance to provide a better interval
for highlighting the seletor of the node only

initialize-release
o  answer: anObject
probably am only interested in the very first answer

o  initialize

obsolete
o  addArgumentSearch: aSearchCondition

o  addMethodSearch: aSearchCondition

o  addSearch: aSearchCondition

o  buildMethodParseTreeRuleFor: aSearchCondition

o  buildParseTreeRuleFor: aSearchCondition

private
o  foundMatch

o  lookForMoreMatchesInContext: oldContext

o  performSearches: aSearchCollection on: aNode
please read the comment in alwaysPerformAllSearches

o  recusivelySearchInContext
We need to save the matched context since the other searches might overwrite it.

o  visitNode: aNode matching: aSearchCollection

searching
o  matches: aString do: aBlock

o  matchesAnyArgumentOf: stringCollection do: aBlock

o  matchesAnyMethodOf: aStringCollection do: aBlock

o  matchesAnyOf: aStringCollection do: aBlock

o  matchesAnyTreeOf: treeCollection do: aBlock

o  matchesArgument: aString do: aBlock

o  matchesArgumentTree: aBRProgramNode do: aBlock

o  matchesMethod: aString do: aBlock

o  matchesTree: aBRProgramNode do: aBlock

testing
o  alwaysPerformAllSearches
a flag, to fix a bug? in the performSearches,
which stops after the first matching searchRule, even if there are more rules to be
considered.
This bug affects the literal replacements, inside literal arrays,
in case multiple such replaces have been defined
eg. a rewriter like:
replacer := ParseTreeSourceRewriter new.
replacer replaceLiteral: #lit1 with: #newLit1.
replacer replaceLiteral: #lit2 with: #newLit2.

The original searcher would only replace one literal and stop performing other replaces,
after the first hit. However, if there is a single literal array with both lit1 and lit2 inside,
all other replaces must also be performed.

As I have no idea on what other effects an unconditional change in performSearches might have,
this new behavior is made conditional on the return value of this method
(and it is redefined in ParseTreeSourceRewriter

o  canMatchMethod: aCompiledMethod
this does a quickReject based on the set of sent messages
(in the searches vs. messages in the method)

o  canQuicklyReject: sourceCode
if I have quickSearchStrings, try a quick reject based on them.
This may generate false negatives (i.e. lets source pass, even though
it should not), but still reduces the amount of parser work in the order
of 90%, thus making code searches 10 times faster.

visiting
o  visitArgument: aNode

o  visitNode: aNode



ST/X 7.2.0.0; WebServer 1.670 at bd0aa1f87cdd.unknown:8081; Fri, 19 Apr 2024 19:13:15 GMT