From VisualWorks®, 7.6 of February 8, 2008 on March 3, 2008 at 9:43:05 pm (Dialog confirm: 'You are filing-in a Parcel source file!\\While this is possible it will not have\the same effect as loading the parcel.\None of the Parcel''s prerequisites will\be loaded and none of its load actions\will be performed.\\Are you sure you want to file-in?' withCRs) ifFalse: [self error: 'Parcel file-in abandoned. Choose terminate or close.'] <class> <name>RBToken</name> <environment>Refactory.Browser</environment> <super>Core.Object</super> <private>false</private> none sourcePointer comments <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBToken
RBToken is the abstract superclass of all of the RB tokens. These tokens (unlike the standard parser's) remember where they came from in the original source code. Subclasses must implement the following messages: accessing length Instance Variables: sourcePointer <Integer> The position in the original source code where this token began.
</comment> <class> <name>RBValueToken</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBToken</super> <private>false</private> none value <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBValueToken
RBValueToken is the abstract superclass of all tokens that have additional information attached. For example, the BinarySelector token holds onto the actual character (e.g. $+). Instance Variables: value <String> The value of this token
</comment> <class> <name>RBLiteralToken</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueToken</super> <private>false</private> none stopPosition <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBLiteralToken
RBLiteralToken is the first-class representation of a literal token (entire literals, even literal arrays, are a single token in the ST80 grammar.). Instance Variables: stopPosition <Integer> The position within the source code where the token terminates.
</comment> <class> <name>RBProgramNode</name> <environment>Refactory.Browser</environment> <super>Core.Object</super> <private>false</private> none parent comments <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBProgramNode
RBProgramNode is an abstract class that represents an abstract syntax tree node in a Smalltalk program. Subclasses must implement the following messages: accessing start stop visitor acceptVisitor: The #start and #stop methods are used to find the source that corresponds to this node. "source copyFrom: self start to: self stop" should return the source for this node. The #acceptVisitor: method is used by RBProgramNodeVisitors (the visitor pattern). This will also require updating all the RBProgramNodeVisitors so that they know of the new node. Subclasses might also want to redefine match:inContext: and copyInContext: to do parse tree searching and replacing. Subclasses that contain other nodes should override equalTo:withMapping: to compare nodes while ignoring renaming temporary variables, and children that returns a collection of our children nodes. Instance Variables: comments <Collection of: Interval> the intervals in the source that have comments for this node parent <RBProgramNode> the node we're contained in Shared Variables: FormatterClass <Behavior> the formatter class that is used when we are formatted
</comment> <class> <name>RBValueNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBProgramNode</super> <private>false</private> none parentheses <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBValueNode
RBValueNode is an abstract class that represents a node that returns some value. Subclasses must implement the following messages: accessing startWithoutParentheses stopWithoutParentheses testing needsParenthesis Instance Variables: parentheses <SequenceableCollection of: Inteval> the positions of the parethesis around this node. We need a collection of intervals for stupid code such as "((3 + 4))" that has multiple parethesis around the same expression.
</comment> <class> <name>RBBlockNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueNode</super> <private>false</private> none left right colons body arguments bar <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBBlockNode
RBBlockNode is an AST node that represents a block "[...]". Instance Variables: arguments <SequenceableCollection of: RBVariableNode> the arguments for the block bar <Integer | nil> position of the | after the arguments body <RBSequenceNode> the code inside the block colons <SequenceableCollection of: Integer> positions of each : before each argument left <Integer> position of [ right <Integer> position of ]
</comment> <class> <name>RBPatternBlockNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBBlockNode</super> <private>false</private> none valueBlock <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBPatternBlockNode
RBPatternBlockNode is the node in matching parse trees (it never occurs in normal Smalltalk code) that executes a block to determine if a match occurs. valueBlock takes two arguments, the first is the actual node that we are trying to match against, and second node is the dictionary that contains all the metavariable bindings that the matcher has made thus far. Instance Variables: valueBlock <BlockClosure> The block to execute when attempting to match this to a node.
</comment> <class> <name>RBMultiKeywordLiteralToken</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBLiteralToken</super> <private>false</private> none <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <class> <name>RBParseTreeRule</name> <environment>Refactory.Browser</environment> <super>Core.Object</super> <private>false</private> none searchTree owner <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBParseTreeRule
RBParseTreeRule is the abstract superclass of all of the parse tree searching rules. A parse tree rule is the first class representation of a particular rule to search for. The owner of a rule is the algorithm that actually executes the search. This arrangement allows multiple searches to be conducted by a single Searcher. Instance Variables: owner <ParseTreeSearcher> The searcher that is actually performing the search. searchTree <RBProgramNode> The parse tree to be searched.
</comment> <class> <name>RBSearchRule</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBParseTreeRule</super> <private>false</private> none answerBlock <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBSearchRule
RBSearchRule is a parse tree rule that simply searches for matches to the rule. Every time a match is found, answerBlock is evaluated with the node that matches and the cureent answer. This two-argument approach allows a collection to be formed from all of the matches (Think inject:into:). Instance Variables: answerBlock <BlockClosure> Block to evaluate with the matching node and the current answer.
</comment> <class> <name>RBProgramNodeVisitor</name> <environment>Refactory.Browser</environment> <super>Core.Object</super> <private>false</private> none <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBProgramNodeVisitor
RBProgramNodeVisitor is an abstract visitor for the RBProgramNodes.
</comment> <class> <name>RBConfigurableFormatter</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBProgramNodeVisitor</super> <private>false</private> none codeStream indent lookaheadCode originalSource lineStart <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBConfigurableFormatter
RBConfigurableFormatter formats the Refactoring Browser's parse trees. It has many more formatting options than the default formatter used by the classic RB. For some refactorings the RB must reformat the code after the change, so it is good to have a formatter configured to your tastes. To change the RB to use another formatter, execute "RBProgramNode formatterClass: YourFormatterClass". Instance Variables: codeStream <PositionableStream> the stream we are writing our output to indent <Integer> how many times are we indenting a new line -- indents are normally tabs but could be any whitespace string lineStart <Integer> the position of the character that started the current line. This is used for calculating the line length. lookaheadCode <Dictionary key: RBProgramNode value: String> sometimes we need to lookahead while formatting, this dictionary contains the nodes that have already been formatted by lookahead originalSource <String> the original source before we started formatting. This is used to extract the comments from the original source.
</comment> <class> <name>RBSpecialCharacterToken</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueToken</super> <private>false</private> none <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBSpecialCharacterToken
RBSpecialCharacterToken is the first class representation of special characters.
</comment> <class> <name>RBMessageNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueNode</super> <private>false</private> none receiver selector selectorParts arguments <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBMessageNode
RBMessageNode is an AST node that represents a message send. Instance Variables: arguments <SequenceableCollection of: RBValueNode> our argument nodes receiver <RBValueNode> the receiver's node selector <Symbol | nil> the selector we're sending (lazy cached) selectorParts <SequenceableCollection of: RBValueToken> the tokens for each keyword
</comment> <class> <name>RBPatternMessageNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBMessageNode</super> <private>false</private> none isList isCascadeList <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBPatternMessageNode
RBPatternMessageNode is a RBMessageNode that will match other message nodes without their selectors being equal. Instance Variables: isCascadeList <Boolean> are we matching a list of message nodes in a cascaded message isList <Boolean> are we matching each keyword or matching all keywords together (e.g., `keyword1: would match a one argument method whereas `@keywords: would match 0 or more arguments)
</comment> <class> <name>RBScanner</name> <environment>Refactory.Browser</environment> <super>Core.Stream</super> <private>false</private> none stream buffer tokenStart currentCharacter characterType classificationTable comments errorBlock classificationTable <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBScanner
RBScanner is a stream that returns a sequence of token from the string that it is created on. The tokens know where they came from in the source code and which comments were attached to them. Instance Variables: buffer <PositionableStream> Accumulates the text for the current token. characterType <ByteSymbol> The type of the next character. (e.g. #alphabetic, etc.) classificationTable <Array of: Symbol> Mapping from Character values to their characterType. comments <Collection of: Interval> Source intervals of scanned comments that must be attached to the next token. currentCharacter <Character> The character currently being processed. errorBlock <BlockClosure> The block to execute on lexical errors. extendedLiterals <Boolean> True if IBM-type literals are allowed. In VW, this is false. nameSpaceCharacter <Character> The character used to separate namespaces. numberType <ByteSymbol> The method to perform: to scan a number. separatorsInLiterals <Boolean> True if separators are allowed within literals. stream <PositionableStream> Contains the text to be scanned. tokenStart <Integer> The source position of the beginning of the current token Class Instance Variables: classificationTable <Array> the default classification table for all characters Shared Variables: PatternVariableCharacter <Character> the character that starts a pattern node
</comment> <class> <name>RBPatternScanner</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBScanner</super> <private>false</private> none <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBPatternScanner
RBPatternScanner is a subclass of RBScanner that allows the extended syntax of pattern matching trees.
</comment> <class> <name>RBSequenceNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBProgramNode</super> <private>false</private> none leftBar rightBar statements periods temporaries <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBSequenceNode
RBSequenceNode is an AST node that represents a sequence of statements. Both RBBlockNodes and RBMethodNodes contain these. Instance Variables: leftBar <Integer | nil> the position of the left | in the temporaries definition periods <SequenceableCollection of: Integer> the positions of all the periods that separate the statements rightBar <Integer | nil> the position of the right | in the temporaries definition statements <SequenceableCollection of: RBStatementNode> the statement nodes temporaries <SequenceableCollection of: RBVariableNode> the temporaries defined
</comment> <class> <name>ParseTreeSearcher</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBProgramNodeVisitor</super> <private>false</private> none searches answer argumentSearches context messages <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.ParseTreeSearcher
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: RBProgramNode value: BlockClosure)> argument searches (search for the BRProgramNode and perform the BlockClosure when its found) context <RBSmallDictionary> 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). messages <Collection> the sent messages in our searches searches <Collection of: (Association key: RBProgramNode value: BlockClosure)> non-argument searches (search for the BRProgramNode and perform the BlockClosure when its found)
</comment> <class> <name>RBIdentifierToken</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueToken</super> <private>false</private> none <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBIdentifierToken
RBIdentifierToken is the first class representation of an identifier token (e.g. Class)
</comment> <class> <name>RBTagNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBProgramNode</super> <private>false</private> none selector selectorParts arguments brackets <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBTagNode
RBTagNode is an AST node that represents a "Tag" (or Pragma) in a method body. E.g. '<primitive: 42>' or '<resource: #image>'. TagNodes look like MessageNodes, but differ in that they have no reciever, and their arguments are constrianed to literals. Also, the selector(Parts) cannot be a binary type selector (e.g. +, -, etc). Instance Variables: arguments <Stack of: RBLiteralNode> nodes for the literals associate with each keyword, empty when unary selector <Symbol | nil> the selector we're sending (lazy cached) selectorParts <Stack of: RBValueToken> the tokens for each keyword brackets<Interval> the start and stop in the source of the < >'s
</comment> <class> <name>RBCDeclarationNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBTagNode</super> <private>false</private> none <imports></imports> <category>My Classes</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBCDeclarationNode
I am a specialized form of a Method Tag.
</comment> <class> <name>RBPatternWrapperBlockNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBPatternBlockNode</super> <private>false</private> none wrappedNode <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBPatternWrapperBlockNode
RBPatternWrapperBlockNode allows further matching using a block after a node has been matched by a pattern node. Instance Variables: wrappedNode <RBProgramNode> The original pattern node to match
</comment> <class> <name>RBLiteralNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueNode</super> <private>false</private> none <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <class> <name>RBLiteralArrayNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBLiteralNode</super> <private>false</private> none isByteArray stop contents start <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBLiteralArrayNode
I represent literal arrays of both the byte array and literal kind. Instance Variables: contents <(Collection of: (RBLiteralNode ))> description of contents isByteArray <Boolean> am I a ByteArray? start <Integer> start position for the node stop <Integer> stop positon for the node
</comment> <class> <name>RBReturnNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBProgramNode</super> <private>false</private> none return value <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBReturnNode
RBReturnNode is an AST node that represents a return expression. Instance Variables: return <Integer> the position of the ^ character value <RBValueNode> the value that is being returned
</comment> <class> <name>RBBinarySelectorToken</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueToken</super> <private>false</private> none <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBBinarySelectorToken
RBBinarySelectorToken is the first-class representation of a binary selector (e.g. +)
</comment> <class> <name>RBAssignmentToken</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBToken</super> <private>false</private> none <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBAssignmentToken
RBAssignmentToken is the first-class representation of the assignment token ':='
</comment> <class> <name>RBLiteralArrayToken</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueToken</super> <private>false</private> none <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBLiteralArrayToken
I'm the first class respresentation of a literal array. e.g. #(1 2 #symbol #[255] #('embedded'))
</comment> <class> <name>RBKeywordToken</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueToken</super> <private>false</private> none <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBKeywordToken
RBKeywordToken is the first-class representation of a keyword token (e.g. add:)
</comment> <class> <name>RBAssignmentNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueNode</super> <private>false</private> none variable assignment value <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBAssignmentNode
RBAssignmentNode is an AST node for assignment statements Instance Variables: assignment <Integer> position of the := value <RBValueNode> the value that we're assigning variable <RBVariableNode> the variable being assigned
</comment> <class> <name>RBLiteralValueNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBLiteralNode</super> <private>false</private> none token <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBLiteralValueNode
RBLiteralNode is an AST node that represents literals (e.g., #foo, #(1 2 3), true, etc.). Instance Variables: token <RBLiteralToken> the token that contains the literal value as well as its source positions
</comment> <class> <name>RBVariableNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueNode</super> <private>false</private> none token <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBVariableNode
RBVariableNode is an AST node that represent a variable (global, inst var, temp, etc.). Instance Variables: token <RBValueToken> the token that contains our name and position
</comment> <class> <name>RBPatternVariableNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBVariableNode</super> <private>false</private> none recurseInto isList isLiteral isStatement isAnything <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBPatternVariableNode
RBPatternVariableNode is an AST node that is used to match several other types of nodes (literals, variables, value nodes, statement nodes, and sequences of statement nodes). The different types of matches are determined by the name of the node. If the name contains a # character, then it will match a literal. If it contains, a . then it matches statements. If it contains no extra characters, then it matches only variables. These options are mutually exclusive. The @ character can be combined with the name to match lists of items. If combined with the . character, then it will match a list of statement nodes (0 or more). If used without the . or # character, then it matches anything except for list of statements. Combining the @ with the # is not supported. Adding another ` in the name will cause the search/replace to look for more matches inside the node that this node matched. This option should not be used for top level expressions since that would cause infinite recursion (e.g., searching only for "``@anything"). Instance Variables: isAnything <Boolean> can we match any type of node isList <Boolean> can we match a list of items (@) isLiteral <Boolean> only match a literal node (#) isStatement <Boolean> only match statements (.) recurseInto <Boolean> search for more matches in the node we match (`)
</comment> <class> <name>RBReplaceRule</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBParseTreeRule</super> <private>false</private> none verificationBlock <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBReplaceRule
RBReplaceRule is the abstract superclass of all of the transforming rules. The rules change the source code by replacing the node that matches the rule. Subclasses implement different strategies for this replacement. Subclasses must implement the following messages: matching foundMatchFor: Instance Variables: verificationBlock <BlockClosure> Is evaluated with the matching node. This allows for further verification of a match beyond simple tree matching.
</comment> <class> <name>RBBlockReplaceRule</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBReplaceRule</super> <private>false</private> none replaceBlock <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBBlockReplaceRule
RBBlockReplaceRule replaces the matching node by the result of evaluating replaceBlock. This allows arbitrary computation to come up with a replacement. Instance Variables: replaceBlock <BlockClosure> The block that returns the node to replace to matching node with.
</comment> <class> <name>RBPatternBlockToken</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueToken</super> <private>false</private> none <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBPatternBlockToken
RBPatternBlockToken is the first-class representation of the pattern block token.
</comment> <class> <name>RBMethodNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBProgramNode</super> <private>false</private> none selector selectorParts body source arguments tags replacements nodeReplacements <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBMethodNode
RBMethodNode is the AST that represents a Smalltalk method. Instance Variables: arguments <SequenceableCollection of: RBVariableNode> the arguments to the method body <BRSequenceNode> the body/statements of the method nodeReplacements <Dictionary> a dictionary of oldNode -> newNode replacements replacements <Collection of: RBStringReplacement> the collection of string replacements for each node replacement in the parse tree selector <Symbol | nil> the method name (cached) selectorParts <SequenceableCollection of: RBValueToken> the tokens for the selector keywords source <String> the source we compiled tags <SequenceableCollection of: RBTagNode> nodes for any tags (annotations/pragmas) this method defines
</comment> <class> <name>RBPatternMethodNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBMethodNode</super> <private>false</private> none isList <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBPatternMethodNode
RBPatternMethodNode is a RBMethodNode that will match other method nodes without their selectors being equal. Instance Variables: isList <Boolean> are we matching each keyword or matching all keywords together (e.g., `keyword1: would match a one argument method whereas `@keywords: would match 0 or more arguments)
</comment> <class> <name>RBStringReplaceRule</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBReplaceRule</super> <private>false</private> none replaceTree <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBStringReplaceRule
RBStringReplaceRule replaces a matched tree with another tree (which may include metavariable from the matching tree). This is a very succint syntax for specifying most rewrites. Instance Variables: replaceTree <RBProgramNode> The tree to replace the matched tree with.
</comment> <class> <name>RBSmallDictionary</name> <environment>Refactory.Browser</environment> <super>Core.KeyedCollection</super> <private>false</private> none keys values size <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBSmallDictionary
RBSmallDictionary is a special dictionary optimized for small collections. In addition to the normal dictionary protocol, it also supports an #empty message which "empties" the collection but may hang on to the original elements (so it could collect garbage). Without #empty we would either need to create a new dictionary or explicitly remove everything from the dictionary. Both of these take more time and #empty. Instance Variables: keys <Array of: Object> array of keys (we don't use Associations for our key value pairs) size <Integer> the size of the dictionary values <Array of: Object> array of our values
</comment> <class> <name>ParseTreeRewriter</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.ParseTreeSearcher</super> <private>false</private> none tree <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.ParseTreeRewriter
ParseTreeRewriter walks over and transforms its RBProgramNode (tree). If the tree is modified, then answer is set to true, and the modified tree can be retrieved by the #tree method. Instance Variables: tree <RBProgramNode> the parse tree we're transforming
</comment> <class> <name>RBNumberLiteralToken</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBLiteralToken</super> <private>false</private> none source <imports></imports> <category>Browser-Scanner</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <class> <name>RBCascadeNode</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBValueNode</super> <private>false</private> none messages semicolons <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBCascadeNode
RBCascadeNode is an AST node for cascaded messages (e.g., "self print1 ; print2"). Instance Variables: messages <SequenceableCollection of: RBMessageNode> the messages semicolons <SequenceableCollection of: Integer> positions of the ; between messages
</comment> <class> <name>RBStringReplacement</name> <environment>Refactory.Browser</environment> <super>Core.Object</super> <private>false</private> none startPosition stopPosition string <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBStringReplacement
RBStringReplacement represents replacing source in the original method with a different string. These are used when reformatting code after a parse tree change has been made. Depending on the change, it may be possible to minimally change the parse tree without needing to format it. Instance Variables: startPosition <Integer> the start position in the original source stopPosition <Integer> the end position in the original source string <String> replaces everything from the startPosition to the endPosition with this string
</comment> <class> <name>RBParser</name> <environment>Refactory.Browser</environment> <super>Core.Object</super> <private>false</private> none scanner currentToken nextToken errorBlock source comments <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBParser
RBParser takes a source code string and generates an AST for it. This is a hand-written, recursive descent parser and has been optimized for speed. The simplest way to call this is either 'RBParser parseExpression: aString' if you want the AST for an expression, or 'RBParser parseMethod: aString' if you want to parse an entire method. Instance Variables: currentToken <RBToken> The current token being processed. emptyStatements <Boolean> True if empty statements are allowed. In IBM, they are, in VW they aren't. errorBlock <BlockClosure> The block to evaluate on a syntax error. nextToken <RBToken> The next token that will be processed. This allows one-token lookahead. scanner <RBScanner> The scanner that generates a stream of tokens to parse. source <String> The source code to parse tags <Collection of: Interval> The source intervals of the tags appearing at the top of a method (e.g. Primitive calls) Shared Variables: ParserType <Symbol> the type code we are parsing
</comment> <class> <name>RBPatternParser</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBParser</super> <private>false</private> none <imports></imports> <category>Browser-Parser</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBPatternParser
RBPatternParser is a subclass of RBParser that allows the extended syntax that creates matching trees. These trees can be used by the ParseTreeMatcher to search and transform source code.
</comment> <class> <name>RBReadBeforeWrittenTester</name> <environment>Refactory.Browser</environment> <super>Refactory.Browser.RBProgramNodeVisitor</super> <private>false</private> none read checkNewTemps scopeStack <imports></imports> <category>Browser-Parse Tree Matching</category> <attributes> <package>Browser-Parser</package> </attributes> </class> <comment> Refactory.Browser.RBReadBeforeWrittenTester
RBReadBeforeWrittenTester is a visitor that identifies variables that may have been read before they are initialized. Instance Variables: checkNewTemps <Boolean> description of checkNewTemps read <Collection> description of read scopeStack <OrderedCollection> description of scopeStack
</comment> <name>TraditionalBinaryPrecedence</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>true</private> <constant>false</constant> <category>other shares</category> <initializer>#(#($| $& $?) #($= $~ $< $>) #($- $+) #($* $/ $% $\) #($@))</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>NewLinesAfterMethodPattern</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>1</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>NewLineBeforeFirstKeyword</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>true</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>StringFollowingReturn</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>true</private> <constant>false</constant> <category>configuration settings</category> <initializer>String new</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>RetainBlankLinesBetweenStatements</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>false</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>PeriodsAtEndOfMethod</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>false</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>FormatCommentWithStatements</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>true</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>NewLinesAfterMethodComment</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>1</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>NewLineBeforeFirstCascade</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>true</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>StringInsideBlocks</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>true</private> <constant>false</constant> <category>configuration settings</category> <initializer>String new</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>IndentString</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>true</private> <constant>false</constant> <category>configuration settings</category> <initializer>String with: Character tab</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>NewLineAfterCascade</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>true</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>NumberOfArgumentsForMultiLine</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>2</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>StringInsideParentheses</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>true</private> <constant>false</constant> <category>configuration settings</category> <initializer>String new</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>UseTraditionalBinaryPrecedenceForParentheses</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>true</private> <constant>false</constant> <category>configuration settings</category> <initializer>true</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>IndentsForKeywords</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>1</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>NewLinesAfterTemporaries</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>1</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>MethodSignatureOnMultipleLines</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>false</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>NewLinesBeforeMethodBody</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>1</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>MaxLineLength</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>75</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>LineUpBlockBrackets</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>false</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>MinimumNewLinesBetweenStatements</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>1</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>PeriodsAtEndOfBlock</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>false</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>PeriodsAsTerminators</name> <environment>Refactory.Browser.RBConfigurableFormatter</environment> <private>false</private> <constant>false</constant> <category>configuration settings</category> <initializer>false</initializer> <attributes> <package>Browser-Parser</package> </attributes> <name>FormatterClass</name> <environment>Refactory.Browser.RBProgramNode</environment> <private>false</private> <constant>false</constant> <category>As yet unclassified</category> <attributes> <package>Browser-Parser</package> </attributes> <name>PatternVariableCharacter</name> <environment>Refactory.Browser.RBScanner</environment> <private>false</private> <constant>false</constant> <category>characters</category> <attributes> <package>Browser-Parser</package> </attributes> <methods> Refactory.Browser.RBToken <category>testing</category>
isAssignment ^false
isBinary ^false
isIdentifier ^false
isKeyword ^false
isLiteral ^self isLiteralToken
isLiteralArrayToken ^false
isLiteralToken ^false
isPatternBlock ^false
isPatternVariable ^false
isSpecial ^false
</methods> <methods> Refactory.Browser.RBToken <category>accessing</category>
comments ^comments
comments: anObject comments := anObject
length ^self subclassResponsibility
removePositions sourcePointer := nil
start ^sourcePointer
stop ^self start + self length - 1
</methods> <methods> Refactory.Browser.RBToken <category>printing</category>
printOn: aStream aStream nextPut: $ ; nextPutAll: self class name
</methods> <methods> Refactory.Browser.RBToken <category>initialize-release</category>
start: anInteger sourcePointer := anInteger
</methods> <methods> Refactory.Browser.RBToken class <category>instance creation</category>
start: anInterval ^self new start: anInterval
</methods> <methods> Refactory.Browser.RBValueToken <category>private</category>
length ^value size
</methods> <methods> Refactory.Browser.RBValueToken <category>printing</category>
printOn: aStream super printOn: aStream. aStream nextPut: $(. value printOn: aStream. aStream nextPutAll: ')'
</methods> <methods> Refactory.Browser.RBValueToken <category>accessing</category>
value ^value
value: anObject value := anObject
</methods> <methods> Refactory.Browser.RBValueToken <category>initialize-release</category>
value: aString start: anInteger value := aString. sourcePointer := anInteger
</methods> <methods> Refactory.Browser.RBValueToken class <category>instance creation</category>
value: aString start: anInteger ^self new value: aString start: anInteger
</methods> <methods> Refactory.Browser.RBLiteralToken <category>testing</category>
isLiteralToken ^true
isMultiKeyword ^false
</methods> <methods> Refactory.Browser.RBLiteralToken <category>private</category>
length ^stopPosition - self start + 1
</methods> <methods> Refactory.Browser.RBLiteralToken <category>accessing</category>
realValue ^value
stop: anObject stopPosition := anObject
</methods> <methods> Refactory.Browser.RBLiteralToken <category>initialize-release</category>
value: aString start: anInteger stop: stopInteger value := aString. sourcePointer := anInteger. stopPosition := stopInteger
</methods> <methods> Refactory.Browser.RBLiteralToken <category>printing</category>
storeOn: aStream value isSymbol ifTrue: [aStream nextPut: $#. ((RBScanner isSelector: value) and: [value ~~ #'||']) ifTrue: [aStream nextPutAll: value] ifFalse: [value asString printOn: aStream]. ^self]. value class == Character ifTrue: [aStream nextPut: $$; nextPut: value. ^self]. value storeOn: aStream
</methods> <methods> Refactory.Browser.RBLiteralToken class <category>instance creation</category>
value: anObject | literal | literal := anObject class == Array ifTrue: [anObject collect: [:each | self value: each]] ifFalse: [anObject]. ^self value: literal start: nil stop: nil
value: aString start: anInteger stop: stopInteger ^(self new) value: aString start: anInteger stop: stopInteger; yourself
</methods> <methods> Refactory.Browser.RBProgramNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor self subclassResponsibility
</methods> <methods> Refactory.Browser.RBProgramNode <category>accessing</category>
allArgumentVariables | children | children := self children. children isEmpty ifTrue: [^#()]. ^children inject: OrderedCollection new into: [:vars :each | vars addAll: each allArgumentVariables; yourself]
allDefinedVariables | children | children := self children. children isEmpty ifTrue: [^#()]. ^children inject: OrderedCollection new into: [:vars :each | vars addAll: each allDefinedVariables; yourself]
allTemporaryVariables | children | children := self children. children isEmpty ifTrue: [^#()]. ^children inject: OrderedCollection new into: [:vars :each | vars addAll: each allTemporaryVariables; yourself]
asReturn "Change the current node to a return node." parent isNil ifTrue: [self error: (#CannotChangeWithoutParent << #browser >> 'Cannot change to a return without a parent node.')]. parent isSequence ifFalse: [self error: (#ParentMustBeSequence << #browser >> 'Parent node must be a sequence node.')]. (parent isLast: self) ifFalse: [self error: (#ReturnNodeMustBeLast << #browser >> 'Return node must be last.')]. ^parent addReturn
blockVariables ^parent isNil ifTrue: [#()] ifFalse: [parent blockVariables]
children ^#()
comments ^comments isNil ifTrue: [#()] ifFalse: [comments]
comments: aCollection comments := aCollection
formattedCode ^self formatterClass new format: self
formatterClass ^self class formatterClass
mappingFor: aNode | method | method := self methodNode. method isNil ifTrue: [^aNode]. ^method mappingFor: aNode
methodComments ^self comments
methodNode ^parent isNil ifTrue: [nil] ifFalse: [parent methodNode]
newSource ^self formattedCode
parent ^parent
parent: aRBProgramNode parent := aRBProgramNode
precedence ^6
sentMessages | messages | messages := Set new. self children do: [:each | messages addAll: each sentMessages]. ^messages
source ^parent notNil ifTrue: [parent source] ifFalse: [nil]
sourceInterval ^self start to: self stop
start self subclassResponsibility
statementComments | statementComments | statementComments := OrderedCollection withAll: self comments. self children do: [:each | statementComments addAll: each statementComments]. ^statementComments asSortedCollection: [:a :b | a first < b first]
stop self subclassResponsibility
temporaryVariables ^parent isNil ifTrue: [#()] ifFalse: [parent temporaryVariables]
</methods> <methods> Refactory.Browser.RBProgramNode <category>testing</category>
assigns: aVariableName ^self children anySatisfy: [:each | each assigns: aVariableName]
containedBy: anInterval ^anInterval first <= self start and: [anInterval last >= self stop]
containsReturn ^self children anySatisfy: [:each | each containsReturn]
defines: aName ^false
directlyUses: aNode ^true
evaluatedFirst: aNode self children do: [:each | each == aNode ifTrue: [^true]. each isImmediateNode ifFalse: [^false]]. ^false
intersectsInterval: anInterval ^(anInterval first between: self start and: self stop) or: [self start between: anInterval first and: anInterval last]
isAssignment ^false
isBlock ^false
isCascade ^false
isDirectlyUsed "This node is directly used as an argument, receiver, or part of an assignment." ^parent isNil ifTrue: [false] ifFalse: [parent directlyUses: self]
isEvaluatedFirst "Return true if we are the first thing evaluated in this statement." ^parent isNil or: [parent isSequence or: [parent evaluatedFirst: self]]
isImmediateNode ^false
isLast: aNode | children | children := self children. ^children notEmpty and: [children last == aNode]
isLiteralArray ^false
isLiteralNode ^false
isMessage ^false
isMethod ^false
isReturn ^false
isSequence ^false
isUsed "Answer true if this node could be used as part of another expression. For example, you could use the result of this node as a receiver of a message, an argument, the right part of an assignment, or the return value of a block. This differs from isDirectlyUsed in that it is conservative since it also includes return values of blocks." ^parent isNil ifTrue: [false] ifFalse: [parent uses: self]
isValue ^false
isVariable ^false
lastIsReturn ^self isReturn
references: aVariableName ^self children anySatisfy: [:each | each references: aVariableName]
uses: aNode ^true
</methods> <methods> Refactory.Browser.RBProgramNode <category>querying</category>
bestNodeFor: anInterval | selectedChildren | (self intersectsInterval: anInterval) ifFalse: [^nil]. (self containedBy: anInterval) ifTrue: [^self]. selectedChildren := self children select: [:each | each intersectsInterval: anInterval]. ^selectedChildren size == 1 ifTrue: [selectedChildren first bestNodeFor: anInterval] ifFalse: [self]
selfMessages | searcher | searcher := ParseTreeSearcher new. searcher matches: 'self `@msg: ``@args' do: [:aNode :answer | answer add: aNode selector; yourself]. ^searcher executeTree: self initialAnswer: Set new
statementNode "Return your topmost node that is contained by a sequence node." (parent isNil or: [parent isSequence]) ifTrue: [^self]. ^parent statementNode
superMessages | searcher | searcher := ParseTreeSearcher new. searcher matches: 'super `@msg: ``@args' do: [:aNode :answer | answer add: aNode selector; yourself]. ^searcher executeTree: self initialAnswer: Set new
whichNodeIsContainedBy: anInterval | selectedChildren | (self intersectsInterval: anInterval) ifFalse: [^nil]. (self containedBy: anInterval) ifTrue: [^self]. selectedChildren := self children select: [:each | each intersectsInterval: anInterval]. ^selectedChildren size == 1 ifTrue: [selectedChildren first whichNodeIsContainedBy: anInterval] ifFalse: [nil]
whoDefines: aName ^(self defines: aName) ifTrue: [self] ifFalse: [parent ifNotNil: [parent whoDefines: aName]]
</methods> <methods> Refactory.Browser.RBProgramNode <category>meta variable-accessing</category>
cascadeListCharacter ^$;
listCharacter ^$@
literalCharacter ^$#
recurseIntoCharacter ^$`
statementCharacter ^$.
</methods> <methods> Refactory.Browser.RBProgramNode <category>enumeration</category>
collect: aBlock "Hacked to fit collection protocols" ^aBlock value: self
do: aBlock "Hacked to fit collection protocols" aBlock value: self
size "Hacked to fit collection protocols" ^1
</methods> <methods> Refactory.Browser.RBProgramNode <category>copying</category>
copyCommentsFrom: aNode "Add all comments from aNode to us. If we already have the comment, then don't add it." | newComments | newComments := OrderedCollection new. aNode nodesDo: [:each | newComments addAll: each comments]. self nodesDo: [:each | each comments do: [:comment | newComments remove: comment ifAbsent: []]]. newComments isEmpty ifTrue: [^self]. newComments := newComments asSortedCollection: [:a :b | a first < b first]. self comments: newComments
</methods> <methods> Refactory.Browser.RBProgramNode <category>matching</category>
copyInContext: aDictionary ^self copy
copyList: matchNodes inContext: aDictionary | newNodes | newNodes := OrderedCollection new. matchNodes do: [:each | | object | object := each copyInContext: aDictionary. newNodes addAll: object]. ^newNodes
match: aNode inContext: aDictionary ^self = aNode
matchList: matchNodes against: programNodes inContext: aDictionary ^self matchList: matchNodes index: 1 against: programNodes index: 1 inContext: aDictionary
matchList: matchNodes index: matchIndex against: programNodes index: programIndex inContext: aDictionary | node currentIndex currentDictionary nodes | matchNodes size < matchIndex ifTrue: [^programNodes size < programIndex]. node := matchNodes at: matchIndex. node isList ifTrue: [currentIndex := programIndex - 1. [currentDictionary := aDictionary copy. programNodes size < currentIndex or: [nodes := programNodes copyFrom: programIndex to: currentIndex. (currentDictionary at: node ifAbsentPut: [nodes]) = nodes and: [(self matchList: matchNodes index: matchIndex + 1 against: programNodes index: currentIndex + 1 inContext: currentDictionary) ifTrue: [currentDictionary keysAndValuesDo: [:key :value | aDictionary at: key put: value]. ^true]. false]]] whileFalse: [currentIndex := currentIndex + 1]. ^false]. programNodes size < programIndex ifTrue: [^false]. (node match: (programNodes at: programIndex) inContext: aDictionary) ifFalse: [^false]. ^self matchList: matchNodes index: matchIndex + 1 against: programNodes index: programIndex + 1 inContext: aDictionary
</methods> <methods> Refactory.Browser.RBProgramNode <category>comparing</category>
equalTo: aNode exceptForVariables: variableNameCollection | dictionary | dictionary := Dictionary new. (self equalTo: aNode withMapping: dictionary) ifFalse: [^false]. dictionary keysAndValuesDo: [:key :value | (key = value or: [variableNameCollection includes: key]) ifFalse: [^false]]. ^true
equalTo: aNode withMapping: aDictionary ^self = aNode
</methods> <methods> Refactory.Browser.RBProgramNode <category>testing-matching</category>
canMatchMethod: aCompiledMethod ^self sentMessages allSatisfy: [:each | (self class optimizedSelectors includes: each) or: [aCompiledMethod refersToLiteral: each]]
isList ^false
isPatternNode ^false
recurseInto ^false
</methods> <methods> Refactory.Browser.RBProgramNode <category>iterating</category>
nodesDo: aBlock aBlock value: self. self children do: [:each | each nodesDo: aBlock]
</methods> <methods> Refactory.Browser.RBProgramNode <category>printing</category>
printOn: aStream aStream nextPutAll: self class fullName; nextPut: $(; nextPutAll: self formattedCode; nextPut: $)
</methods> <methods> Refactory.Browser.RBProgramNode <category>replacing</category>
addReplacement: aStringReplacement parent isNil ifTrue: [^self]. parent addReplacement: aStringReplacement
clearReplacements parent isNil ifTrue: [^self]. parent clearReplacements
removeDeadCode self children do: [:each | each removeDeadCode]
replaceMethodSource: aNode "We are being replaced with aNode -- if possible try to perform an in place edit of the source." | method | method := self methodNode. method notNil ifTrue: [method map: self to: aNode]. aNode parent: self parent. [self replaceSourceWith: aNode] on: Error do: [:ex | self clearReplacements. ex return]
replaceNode: aNode withNode: anotherNode self error: (#IDontStoreOtherNodes << #browser >> 'I don''t store other nodes')
replaceWith: aNode parent isNil ifTrue: [self error: (#ThisNodeHasNoParent << #browser >> 'This node doesn''t have a parent')]. self replaceMethodSource: aNode. parent replaceNode: self withNode: aNode
</methods> <methods> Refactory.Browser.RBProgramNode <category>private-replacing</category>
replaceSourceFrom: aNode self clearReplacements
replaceSourceWith: aNode aNode replaceSourceFrom: self
</methods> <methods> Refactory.Browser.RBProgramNode <category>utility</category>
composeSelector: aSequenceOfTokens ^aSequenceOfTokens size = 1 ifTrue: [aSequenceOfTokens first value asSymbol] ifFalse: [| ws | ws := String new writeStream. aSequenceOfTokens do: [:each | ws nextPutAll: each value]. ws contents asSymbol]
</methods> <methods> Refactory.Browser.RBProgramNode class <category>accessing</category>
formatterClass ^FormatterClass isNil ifTrue: [RBConfigurableFormatter] ifFalse: [FormatterClass]
formatterClass: aClass FormatterClass := aClass
optimizedSelectors ^#(#ifTrue: #ifTrue:ifFalse: #ifFalse: #ifFalse:ifTrue: #whileTrue: #whileTrue #whileFalse: #whileFalse #to:do: #to:by:do: #and: #or: #repeat #timesRepeat:)
</methods> <methods> Refactory.Browser.RBValueNode <category>accessing</category>
addParenthesis: anInterval parentheses isNil ifTrue: [parentheses := OrderedCollection new: 1]. parentheses add: anInterval
parentheses ^parentheses isNil ifTrue: [#()] ifFalse: [parentheses]
start ^parentheses isNil ifTrue: [self startWithoutParentheses] ifFalse: [parentheses last first]
startWithoutParentheses ^self subclassResponsibility
stop ^parentheses isNil ifTrue: [self stopWithoutParentheses] ifFalse: [parentheses last last]
stopWithoutParentheses ^self subclassResponsibility
</methods> <methods> Refactory.Browser.RBValueNode <category>testing</category>
containedBy: anInterval ^anInterval first <= self startWithoutParentheses and: [anInterval last >= self stopWithoutParentheses]
hasParentheses ^self parentheses notEmpty
isValue ^true
needsParenthesis ^self subclassResponsibility
</methods> <methods> Refactory.Browser.RBBlockNode <category>comparing</category>
= anObject self == anObject ifTrue: [^true]. self class = anObject class ifFalse: [^false]. self body = anObject body ifFalse: [^false]. self arguments size = anObject arguments size ifFalse: [^false]. 1 to: self arguments size do: [:i | (self arguments at: i) = (anObject arguments at: i) ifFalse: [^false]]. ^true
equalTo: anObject withMapping: aDictionary self class = anObject class ifFalse: [^false]. self arguments size = anObject arguments size ifFalse: [^false]. 1 to: self arguments size do: [:i | ((self arguments at: i) equalTo: (anObject arguments at: i) withMapping: aDictionary) ifFalse: [^false]]. (self body equalTo: anObject body withMapping: aDictionary) ifFalse: [^false]. self arguments do: [:each | aDictionary removeKey: each name]. ^true
hash ^self arguments hash bitXor: self body hash
</methods> <methods> Refactory.Browser.RBBlockNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptBlockNode: self
</methods> <methods> Refactory.Browser.RBBlockNode <category>accessing</category>
allArgumentVariables ^(self argumentNames asOrderedCollection) addAll: super allArgumentVariables; yourself
allDefinedVariables ^(self argumentNames asOrderedCollection) addAll: super allDefinedVariables; yourself
argumentNames ^self arguments collect: [:each | each name]
arguments ^arguments
arguments: argCollection arguments := argCollection. arguments do: [:each | each parent: self]
bar ^bar
bar: anObject bar := anObject
blockVariables | vars | vars := super blockVariables asOrderedCollection. vars addAll: self argumentNames. ^vars
body ^body
body: stmtsNode body := stmtsNode. body parent: self
children ^self arguments copyWith: self body
colons: aCollection colons := aCollection
left ^left
left: anObject left := anObject
precedence ^0
right ^right
right: anObject right := anObject
startWithoutParentheses ^left
statementComments ^self comments
stopWithoutParentheses ^right
</methods> <methods> Refactory.Browser.RBBlockNode <category>matching</category>
copyInContext: aDictionary ^(self class new) arguments: (self copyList: arguments inContext: aDictionary); body: (body copyInContext: aDictionary); yourself
match: aNode inContext: aDictionary aNode class == self class ifFalse: [^false]. ^(self matchList: arguments against: aNode arguments inContext: aDictionary) and: [body match: aNode body inContext: aDictionary]
</methods> <methods> Refactory.Browser.RBBlockNode <category>testing</category>
defines: aName ^arguments anySatisfy: [:each | each name = aName]
directlyUses: aNode ^false
isBlock ^true
isImmediateNode ^true
isLast: aNode ^body isLast: aNode
needsParenthesis ^false
references: aVariableName ^body references: aVariableName
uses: aNode aNode = body ifFalse: [^false]. ^parent isMessage ifTrue: [(#(#ifTrue:ifFalse: #ifTrue: #ifFalse: #ifFalse:ifTrue:) includes: parent selector) not or: [parent isUsed]] ifFalse: [self isUsed]
</methods> <methods> Refactory.Browser.RBBlockNode <category>copying</category>
postCopy super postCopy. arguments := arguments collect: [:each | each copy]. body := body copy
</methods> <methods> Refactory.Browser.RBBlockNode <category>replacing</category>
replaceNode: aNode withNode: anotherNode body == aNode ifTrue: [self body: anotherNode]. self arguments: (arguments collect: [:each | each == aNode ifTrue: [anotherNode] ifFalse: [each]])
</methods> <methods> Refactory.Browser.RBBlockNode class <category>instance creation</category>
arguments: argNodes body: sequenceNode ^(self new) arguments: argNodes; body: sequenceNode; yourself
body: sequenceNode ^self arguments: #() body: sequenceNode
</methods> <methods> Refactory.Browser.RBPatternBlockNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptPatternBlockNode: self
</methods> <methods> Refactory.Browser.RBPatternBlockNode <category>matching</category>
addArgumentWithNameBasedOn: aString to: aRBBlockNode | name index vars | name := aString. vars := aRBBlockNode allDefinedVariables. index := 0. [vars includes: name] whileTrue: [index := index + 1. name := name , index printString]. aRBBlockNode arguments: (aRBBlockNode arguments copyWith: (RBVariableNode named: name))
constructLookupNodeFor: aString in: aRBBlockNode | argumentNode | argumentNode := RBLiteralNode literalToken: (RBLiteralToken value: aString start: nil stop: nil). ^RBMessageNode receiver: (RBVariableNode named: 'self') selector: #lookupMatchFor:in: arguments: (Array with: argumentNode with: aRBBlockNode arguments last)
copyInContext: aDictionary ^self replacingBlock value: aDictionary
createBlockFor: aRBBlockNode | source | self replacePatternNodesIn: aRBBlockNode. source := aRBBlockNode formattedCode. ^Compiler evaluate: source for: self logged: false
createMatchingBlock | newBlock | self arguments size > 2 ifTrue: [self error: (#GenKey7 << #browser >> 'Search blocks can only contain arguments for the node and matching dictionary')]. newBlock := RBBlockNode arguments: arguments body: body. newBlock arguments isEmpty ifTrue: [self addArgumentWithNameBasedOn: 'aNode' to: newBlock]. newBlock arguments size = 1 ifTrue: [self addArgumentWithNameBasedOn: 'aDictionary' to: newBlock]. ^self createBlockFor: newBlock
createReplacingBlock | newBlock | self arguments size > 1 ifTrue: [self error: (#GenKey8 << #browser >> 'Replace blocks can only contain an argument for the matching dictionary')]. newBlock := RBBlockNode arguments: arguments body: body. self arguments isEmpty ifTrue: [self addArgumentWithNameBasedOn: 'aDictionary' to: newBlock]. ^self createBlockFor: newBlock
lookupMatchFor: aString in: aDictionary ^aDictionary at: aString ifAbsent: [| variableNode | variableNode := RBPatternVariableNode named: aString. aDictionary at: variableNode ifAbsent: [nil]]
match: aNode inContext: aDictionary ^self matchingBlock value: aNode value: aDictionary
matchingBlock ^valueBlock isNil ifTrue: [valueBlock := self createMatchingBlock] ifFalse: [valueBlock]
replacePatternNodesIn: aRBBlockNode aRBBlockNode body nodesDo: [:each | (each isVariable and: [each isPatternNode]) ifTrue: [each replaceWith: (self constructLookupNodeFor: each name in: aRBBlockNode)]]
replacingBlock ^valueBlock isNil ifTrue: [valueBlock := self createReplacingBlock] ifFalse: [valueBlock]
</methods> <methods> Refactory.Browser.RBPatternBlockNode <category>accessing</category>
sentMessages ^OrderedCollection new
</methods> <methods> Refactory.Browser.RBMultiKeywordLiteralToken <category>testing</category>
isMultiKeyword ^true
</methods> <methods> Refactory.Browser.RBParseTreeRule <category>matching</category>
canMatch: aProgramNode ^true
foundMatchFor: aProgramNode ^aProgramNode
performOn: aProgramNode self context empty. ^((searchTree match: aProgramNode inContext: self context) and: [self canMatch: aProgramNode]) ifTrue: [owner recursivelySearchInContext. self foundMatchFor: aProgramNode] ifFalse: [nil]
</methods> <methods> Refactory.Browser.RBParseTreeRule <category>private</category>
context ^owner context
</methods> <methods> Refactory.Browser.RBParseTreeRule <category>initialize-release</category>
initialize
methodSearchString: aString searchTree := RBParser parseRewriteMethod: aString
owner: aParseTreeSearcher owner := aParseTreeSearcher
searchString: aString searchTree := RBParser parseRewriteExpression: aString
</methods> <methods> Refactory.Browser.RBParseTreeRule <category>accessing</category>
sentMessages ^searchTree sentMessages
</methods> <methods> Refactory.Browser.RBParseTreeRule class <category>instance creation</category>
methodSearch: aString ^(self new) methodSearchString: aString; yourself
new ^(super new) initialize; yourself
search: aString ^(self new) searchString: aString; yourself
</methods> <methods> Refactory.Browser.RBSearchRule <category>testing</category>
canMatch: aProgramNode owner answer: (answerBlock value: aProgramNode value: owner answer). ^true
</methods> <methods> Refactory.Browser.RBSearchRule <category>initialize-release</category>
searchFor: aString thenDo: aBlock self searchString: aString. answerBlock := aBlock
searchForMethod: aString thenDo: aBlock self methodSearchString: aString. answerBlock := aBlock
searchForTree: aBRProgramNode thenDo: aBlock searchTree := aBRProgramNode. answerBlock := aBlock
</methods> <methods> Refactory.Browser.RBSearchRule class <category>instance creation</category>
searchFor: aString thenDo: aBlock ^self new searchFor: aString thenDo: aBlock
searchForMethod: aString thenDo: aBlock ^self new searchForMethod: aString thenDo: aBlock
searchForTree: aBRProgramNode thenDo: aBlock ^self new searchForTree: aBRProgramNode thenDo: aBlock
</methods> <methods> Refactory.Browser.RBProgramNodeVisitor <category>visitor-double dispatching</category>
acceptAssignmentNode: anAssignmentNode self visitNode: anAssignmentNode variable. self visitNode: anAssignmentNode value
acceptBlockNode: aBlockNode self visitArguments: aBlockNode arguments. self visitNode: aBlockNode body
acceptCascadeNode: aCascadeNode aCascadeNode messages do: [:each | self visitNode: each]
acceptCDeclarationNode: aCDeclarationNode
acceptLiteralArrayNode: aRBLiteralArrayNode aRBLiteralArrayNode contents do: [:each | self visitNode: each]
acceptLiteralNode: aLiteralNode
acceptMessageNode: aMessageNode (aMessageNode isCascaded not or: [aMessageNode isFirstCascaded]) ifTrue: [self visitNode: aMessageNode receiver]. aMessageNode arguments do: [:each | self visitNode: each]
acceptMethodNode: aMethodNode self visitArguments: aMethodNode arguments. aMethodNode tagsDo: [:each | self visitNode: each]. self visitNode: aMethodNode body
acceptOptimizedNode: anOptimizedNode self visitNode: anOptimizedNode body
acceptPatternBlockNode: aRBPatternBlockNode self visitArguments: aRBPatternBlockNode arguments. self visitNode: aRBPatternBlockNode body
acceptPatternWrapperBlockNode: aRBPatternWrapperBlockNode self visitNode: aRBPatternWrapperBlockNode wrappedNode. self visitArguments: aRBPatternWrapperBlockNode arguments. self visitNode: aRBPatternWrapperBlockNode body
acceptReturnNode: aReturnNode self visitNode: aReturnNode value
acceptSequenceNode: aSequenceNode self visitArguments: aSequenceNode temporaries. aSequenceNode statements do: [:each | self visitNode: each]
acceptTagNode: aTagNode aTagNode arguments do: [:each | self visitNode: each]
acceptVariableNode: aVariableNode
</methods> <methods> Refactory.Browser.RBProgramNodeVisitor <category>initialize-release</category>
initialize
</methods> <methods> Refactory.Browser.RBProgramNodeVisitor <category>visiting</category>
visitArgument: each "Here to allow subclasses to detect arguments or temporaries." ^self visitNode: each
visitArguments: aNodeCollection ^aNodeCollection do: [:each | self visitArgument: each]
visitNode: aNode ^aNode acceptVisitor: self
</methods> <methods> Refactory.Browser.RBProgramNodeVisitor class <category>instance creation</category>
new ^super new initialize
</methods> <methods> Refactory.Browser.RBConfigurableFormatter <category>private-formatting</category>
addNewLinesBeforeStatementStartingAt: anInteger | newLines | newLines := MinimumNewLinesBetweenStatements max: (RetainBlankLinesBetweenStatements ifTrue: [self newLinesBeforeStartingAt: anInteger] ifFalse: [0]). newLines = 0 ifTrue: [self space] ifFalse: [self newLines: newLines]
formatBlock: aBlockNode (LineUpBlockBrackets and: [self willBeMultiline: aBlockNode body]) ifTrue: [self newLine] ifFalse: [codeStream nextPutAll: StringInsideBlocks]. self formatBlockArgumentsFor: aBlockNode. self visitNode: aBlockNode body. ^(LineUpBlockBrackets and: [self willBeMultiline: aBlockNode body]) ifTrue: [self newLine] ifFalse: [codeStream nextPutAll: StringInsideBlocks]
formatBlockArgumentsFor: aBlockNode aBlockNode arguments isEmpty ifTrue: [^self]. aBlockNode arguments do: [:each | codeStream nextPut: $:. self visitNode: each. FormatCommentWithStatements ifTrue: [self formatCommentsFor: each]. self space]. codeStream nextPutAll: '| '. (self willBeMultiline: aBlockNode body) ifTrue: [self newLine]
formatCommentsFor: aNode originalSource isNil ifTrue: [^self]. aNode comments do: [:each | codeStream space; nextPutAll: (originalSource copyFrom: each first to: each last)]
formatMethodBodyFor: aMethodNode self indentAround: [self newLines: NewLinesAfterMethodPattern. self formatMethodCommentFor: aMethodNode. NewLinesBeforeMethodBody isZero ifFalse: [self newLines: NewLinesBeforeMethodBody]. self formatTagsFor: aMethodNode. self visitNode: aMethodNode body]
formatMethodCommentFor: aMethodNode originalSource isNil ifTrue: [^self]. (FormatCommentWithStatements ifTrue: [aMethodNode methodComments] ifFalse: [aMethodNode comments]) do: [:each | codeStream nextPutAll: (originalSource copyFrom: each first to: each last). self newLines: NewLinesAfterMethodComment]
formatMethodPatternFor: aMethodNode aMethodNode arguments isEmpty ifTrue: [codeStream nextPutAll: aMethodNode selector] ifFalse: [self with: aMethodNode selectorParts and: aMethodNode arguments do: [:key :arg | codeStream nextPutAll: key value. self space. self visitNode: arg] separatedBy: [MethodSignatureOnMultipleLines ifTrue: [self newLine] ifFalse: [self space]]]
formatSelectorAndArguments: aMessageNode | newLineBetweenArguments | newLineBetweenArguments := self isMultiLineMessage: aMessageNode. self indent: IndentsForKeywords around: [self formatSelectorAndArguments: aMessageNode firstSeparator: (newLineBetweenArguments & NewLineBeforeFirstKeyword ifTrue: [[self newLine]] ifFalse: [[self space]]) restSeparator: (newLineBetweenArguments ifTrue: [[self newLine]] ifFalse: [[self space]])]
formatSelectorAndArguments: aMessageNode firstSeparator: firstBlock restSeparator: restBlock | separatorBlock | separatorBlock := firstBlock. aMessageNode isUnary ifTrue: [(self isLineTooLong: aMessageNode selector) ifTrue: [self newLine] ifFalse: [separatorBlock value]. codeStream nextPutAll: aMessageNode selector] ifFalse: [aMessageNode selectorParts with: aMessageNode arguments do: [:selector :argument | (self isLineTooLong: selector value) ifTrue: [self newLine] ifFalse: [separatorBlock value]. separatorBlock := restBlock. self indentAround: [codeStream nextPutAll: selector value. ((self willBeMultiline: argument) or: [self isLineTooLong: (self formattedSourceFor: argument)]) ifTrue: [self newLine] ifFalse: [self space]. self visitNode: argument]]]
formatSequenceCommentsFor: aSequenceNode originalSource isNil ifTrue: [^self]. aSequenceNode comments do: [:each | codeStream nextPutAll: (originalSource copyFrom: each first to: each last). self newLine]
formatSequenceNodeStatementsFor: aSequenceNode | statements | statements := aSequenceNode statements. statements isEmpty ifTrue: [^self]. 1 to: statements size do: [:i | self visitNode: (statements at: i). (i < statements size or: [aSequenceNode parent ifNil: [self class periodsAsTerminators] ifNotNil: [:parent | parent isBlock ifTrue: [self class periodsAtEndOfBlock] ifFalse: [self class periodsAtEndOfMethod]]]) ifTrue: [codeStream nextPut: $.]. self formatStatementCommentsFor: (statements at: i). i < statements size ifTrue: [self addNewLinesBeforeStatementStartingAt: (statements at: i + 1) start]]
formatStatementCommentsFor: aStatementNode originalSource isNil ifTrue: [^self]. FormatCommentWithStatements ifFalse: [^self]. aStatementNode statementComments do: [:each | codeStream tab; nextPutAll: (originalSource copyFrom: each first to: each last)]
formatTagsFor: aMethodNode | newLineBetweenArguments | newLineBetweenArguments := false. aMethodNode tagsDo: [:each | newLineBetweenArguments := newLineBetweenArguments or: [self isMultiLineMessage: each]. self visitNode: each]. (newLineBetweenArguments or: [aMethodNode tagCount > 1]) ifTrue: [self newLine]
formatTemporariesFor: aSequenceNode aSequenceNode temporaries isEmpty ifTrue: [^self]. self bracketWith: '|' around: [self space. aSequenceNode temporaries do: [:each | self visitNode: each. FormatCommentWithStatements ifTrue: [self formatCommentsFor: each]. self space]]. self newLines: NewLinesAfterTemporaries
isMultiLineMessage: aMessageNode | messageStream | (aMessageNode arguments allSatisfy: [:each | each isLiteralNode or: [each isVariable]]) ifTrue: [^false]. aMessageNode arguments size >= NumberOfArgumentsForMultiLine ifTrue: [^true]. (aMessageNode arguments anySatisfy: [:each | self indent: IndentsForKeywords + 1 around: [self willBeMultiline: each]]) ifTrue: [^true]. aMessageNode isUnary ifTrue: [^self isLineTooLong: aMessageNode selector]. messageStream := WriteStream on: (String new: 100). self with: aMessageNode selectorParts and: aMessageNode arguments do: [:sel :arg | messageStream nextPutAll: sel value; space; nextPutAll: (self formattedSourceFor: arg)] separatedBy: [messageStream space]. ^self isLineTooLong: messageStream contents
</methods> <methods> Refactory.Browser.RBConfigurableFormatter <category>private</category>
bracketWith: bracketString around: aBlock bracketString isEmpty ifTrue: [^aBlock value]. codeStream nextPut: bracketString first. ^aBlock ensure: [codeStream nextPut: bracketString last]
currentLineLength ^codeStream position - lineStart
formattedSourceFor: aNode ^lookaheadCode at: aNode ifAbsentPut: [self class format: aNode withIndents: indent]
indent: anInteger around: aBlock indent := indent + anInteger. ^aBlock ensure: [indent := indent - anInteger]
indentAround: aBlock self indent: 1 around: aBlock
isLineTooLong: aString ^self currentLineLength + aString size >= MaxLineLength
needsParenthesisFor: aNode | parent grandparent | parent := aNode parent. (parent isNil or: [parent isMessage not]) ifTrue: [^false]. (aNode isMessage and: [parent isMessage and: [parent receiver == aNode]]) ifTrue: [grandparent := parent parent. (grandparent notNil and: [grandparent isCascade]) ifTrue: [^true]]. aNode precedence < parent precedence ifTrue: [^false]. (parent receiver ~~ aNode and: [aNode precedence >= parent precedence]) ifTrue: [^true]. (parent receiver == aNode and: [aNode precedence > parent precedence or: [aNode isKeyword]]) ifTrue: [^true]. aNode isBinary ifFalse: [^false]. ^UseTraditionalBinaryPrecedenceForParentheses and: [self precedenceOf: parent selector greaterThan: aNode selector]
newLine self newLines: 1
newLines: anInteger anInteger + IndentString size = 0 ifTrue: [codeStream space]. anInteger timesRepeat: [codeStream cr]. lineStart := codeStream position. indent timesRepeat: [codeStream nextPutAll: IndentString]
newLinesBeforeStartingAt: anIndex | count cr lf index char | (anIndex isNil or: [anIndex > originalSource size]) ifTrue: [^0]. cr := Character value: 13. lf := Character value: 10. count := 0. index := anIndex - 1. [index > 0 and: [(char := originalSource at: index) isSeparator]] whileTrue: [char == lf ifTrue: [count := count + 1. (originalSource at: (index - 1 max: 1)) == cr ifTrue: [index := index - 1]]. char == cr ifTrue: [count := count + 1]. index := index - 1]. ^count
precedenceOf: parentSelector greaterThan: childSelector "Put parenthesis around things that are preceived to have 'lower' precedence. For example, 'a + b * c' -> '(a + b) * c' but 'a * b + c' -> 'a * b + c'" | childIndex parentIndex | childIndex := 0. parentIndex := 0. 1 to: TraditionalBinaryPrecedence size do: [:i | ((TraditionalBinaryPrecedence at: i) includes: parentSelector first) ifTrue: [parentIndex := i]. ((TraditionalBinaryPrecedence at: i) includes: childSelector first) ifTrue: [childIndex := i]]. ^childIndex < parentIndex
space codeStream space
willBeMultiline: aNode ^(self formattedSourceFor: aNode) includes: Character cr
writeString: aString | index | index := aString lastIndexOf: Character cr ifAbsent: [0]. codeStream nextPutAll: aString. index > 0 ifTrue: [lineStart := codeStream position - (aString size - index)]
</methods> <methods> Refactory.Browser.RBConfigurableFormatter <category>initialize-release</category>
indent: anInteger indent := anInteger
initialize super initialize. lineStart := 0. indent := 0. lookaheadCode := IdentityDictionary new. codeStream := WriteStream on: (String new: 256)
</methods> <methods> Refactory.Browser.RBConfigurableFormatter <category>visiting</category>
visitNode: aNode | needsParenthesis | (lookaheadCode includesKey: aNode) ifTrue: [^self writeString: (lookaheadCode at: aNode)]. needsParenthesis := self needsParenthesisFor: aNode. self bracketWith: (needsParenthesis ifTrue: ['()'] ifFalse: ['']) around: [needsParenthesis ifTrue: [codeStream nextPutAll: StringInsideParentheses]. super visitNode: aNode. (FormatCommentWithStatements or: [aNode isMethod or: [aNode isSequence]]) ifFalse: [self formatCommentsFor: aNode]. needsParenthesis ifTrue: [codeStream nextPutAll: StringInsideParentheses]]
</methods> <methods> Refactory.Browser.RBConfigurableFormatter <category>visitor-double dispatching</category>
acceptAssignmentNode: anAssignmentNode self visitNode: anAssignmentNode variable. codeStream nextPutAll: ' := '. self visitNode: anAssignmentNode value
acceptBlockNode: aBlockNode self bracketWith: '[]' around: [self formatBlock: aBlockNode]
acceptCascadeNode: aCascadeNode self visitNode: aCascadeNode receiver. self indentAround: [NewLineBeforeFirstCascade ifTrue: [self newLine] ifFalse: [self space]. aCascadeNode messages do: [:each | self indentAround: [self formatSelectorAndArguments: each firstSeparator: [] restSeparator: ((self isMultiLineMessage: each) ifTrue: [[self newLine]] ifFalse: [[self space]])]] separatedBy: [codeStream nextPut: $;. NewLineAfterCascade ifTrue: [self newLine] ifFalse: [self space]]]
acceptCDeclarationNode: aCDeclarationNode self indentAround: [self bracketWith: '<>' around: [codeStream nextPutAll: 'C: '; nextPutAll: aCDeclarationNode arguments first value]]. self newLine
acceptLiteralArrayNode: aLiteralArrayNode codeStream nextPut: $#. aLiteralArrayNode looksLikeStructuredArrayEncoding ifTrue: [self formatStructuredLiteralArray: aLiteralArrayNode] ifFalse: [self formatSimpleLiteralArray: aLiteralArrayNode]
acceptLiteralNode: aLiteralNode self writeString: aLiteralNode token storeString
acceptMessageNode: aMessageNode self visitNode: aMessageNode receiver. self formatSelectorAndArguments: aMessageNode
acceptMethodNode: aMethodNode self formatMethodPatternFor: aMethodNode. self formatMethodBodyFor: aMethodNode
acceptOptimizedNode: anOptimizedNode codeStream nextPutAll: '##'. self bracketWith: '()' around: [self indentAround: [self visitNode: anOptimizedNode body]]
acceptPatternBlockNode: aRBPatternBlockNode codeStream nextPut: $`. self bracketWith: '{}' around: [self formatBlock: aRBPatternBlockNode]
acceptPatternWrapperBlockNode: aRBPatternWrapperBlockNode self visitNode: aRBPatternWrapperBlockNode wrappedNode. codeStream nextPut: $`. self bracketWith: '{}' around: [self formatBlock: aRBPatternWrapperBlockNode]
acceptReturnNode: aReturnNode codeStream nextPut: $^; nextPutAll: StringFollowingReturn. self visitNode: aReturnNode value
acceptSequenceNode: aSequenceNode self formatTemporariesFor: aSequenceNode. self formatSequenceCommentsFor: aSequenceNode. self formatSequenceNodeStatementsFor: aSequenceNode
acceptTagNode: aTagNode self indentAround: [self bracketWith: '<>' around: [self formatSelectorAndArguments: aTagNode firstSeparator: nil restSeparator: ((self isMultiLineMessage: aTagNode) ifTrue: [[self newLine]] ifFalse: [[self space]])]]. self newLine
acceptVariableNode: aVariableNode codeStream nextPutAll: aVariableNode name
formatSimpleLiteralArray: aLiteralArrayNode self bracketWith: (aLiteralArrayNode isForByteArray ifTrue: ['[]'] ifFalse: ['()']) around: [aLiteralArrayNode contents do: [:each | self visitNode: each] separatedBy: [self space]]
formatStructuredLiteralArray: aLiteralArrayNode | ratchet | self bracketWith: (aLiteralArrayNode isForByteArray ifTrue: ['[]'] ifFalse: ['()']) around: [self indentAround: [ratchet := false. aLiteralArrayNode contents do: [:each | ratchet ifTrue: [self newLine]. ratchet := ratchet not. self visitNode: each] separatedBy: [self space]]]
</methods> <methods> Refactory.Browser.RBConfigurableFormatter <category>utility</category>
with: firstCollection and: secondCollection do: aBlock separatedBy: separatorBlock firstCollection isEmpty ifTrue: [^self]. aBlock value: firstCollection first value: secondCollection first. 2 to: firstCollection size do: [:i | separatorBlock value. aBlock value: (firstCollection at: i) value: (secondCollection at: i)]
</methods> <methods> Refactory.Browser.RBConfigurableFormatter <category>public interface</category>
format: aParseTree originalSource := aParseTree source. self visitNode: aParseTree. ^codeStream contents
</methods> <methods> Refactory.Browser.RBConfigurableFormatter class <category>settings</category>
formatCommentWithStatements ^FormatCommentWithStatements
formatCommentWithStatements: aBoolean FormatCommentWithStatements := aBoolean
indentsForKeywords ^IndentsForKeywords
indentsForKeywords: anInteger IndentsForKeywords := anInteger
indentString ^IndentString
indentString: aString IndentString := aString
lineUpBlockBrackets ^LineUpBlockBrackets
lineUpBlockBrackets: aBoolean LineUpBlockBrackets := aBoolean
maxLineLength ^MaxLineLength
maxLineLength: anInteger MaxLineLength := anInteger
methodSignatureOnMultipleLines ^MethodSignatureOnMultipleLines
methodSignatureOnMultipleLines: aBoolean MethodSignatureOnMultipleLines := aBoolean
minimumNewLinesBetweenStatements ^MinimumNewLinesBetweenStatements
minimumNewLinesBetweenStatements: anInteger MinimumNewLinesBetweenStatements := anInteger
newLineAfterCascade ^NewLineAfterCascade
newLineAfterCascade: aBoolean NewLineAfterCascade := aBoolean
newLineBeforeFirstCascade ^NewLineBeforeFirstCascade
newLineBeforeFirstCascade: aBoolean NewLineBeforeFirstCascade := aBoolean
newLineBeforeFirstKeyword ^NewLineBeforeFirstKeyword
newLineBeforeFirstKeyword: aBoolean NewLineBeforeFirstKeyword := aBoolean
newLinesAfterMethodComment ^NewLinesAfterMethodComment
newLinesAfterMethodComment: anInteger NewLinesAfterMethodComment := anInteger.
newLinesAfterMethodPattern ^NewLinesAfterMethodPattern
newLinesAfterMethodPattern: anInteger NewLinesAfterMethodPattern := anInteger
newLinesAfterTemporaries ^NewLinesAfterTemporaries
newLinesAfterTemporaries: anInteger NewLinesAfterTemporaries := anInteger
newLinesBeforeMethodBody ^NewLinesBeforeMethodBody
newLinesBeforeMethodBody: anInteger NewLinesBeforeMethodBody := anInteger
numberOfArgumentsForMultiLine ^NumberOfArgumentsForMultiLine
numberOfArgumentsForMultiLine: anInteger NumberOfArgumentsForMultiLine := anInteger
periodsAsTerminators ^PeriodsAtEndOfBlock and: [PeriodsAtEndOfMethod]
periodsAsTerminators: aBoolean PeriodsAtEndOfBlock := aBoolean. PeriodsAtEndOfMethod := aBoolean
periodsAtEndOfBlock ^PeriodsAtEndOfBlock
periodsAtEndOfBlock: aBoolean PeriodsAtEndOfBlock := aBoolean
periodsAtEndOfMethod ^PeriodsAtEndOfMethod
periodsAtEndOfMethod: aBoolean PeriodsAtEndOfMethod := aBoolean
retainBlankLinesBetweenStatements ^RetainBlankLinesBetweenStatements
retainBlankLinesBetweenStatements: aBoolean RetainBlankLinesBetweenStatements := aBoolean
stringFollowingReturn ^StringFollowingReturn
stringFollowingReturn: aString StringFollowingReturn := aString
stringInsideBlocks ^StringInsideBlocks
stringInsideBlocks: aString StringInsideBlocks := aString
stringInsideParentheses ^StringInsideParentheses
stringInsideParentheses: aString StringInsideParentheses := aString
traditionalBinaryPrecedence ^TraditionalBinaryPrecedence
traditionalBinaryPrecedence: anArray TraditionalBinaryPrecedence := anArray
useTraditionalBinaryPrecedenceForParentheses ^UseTraditionalBinaryPrecedenceForParentheses
useTraditionalBinaryPrecedenceForParentheses: aBoolean UseTraditionalBinaryPrecedenceForParentheses := aBoolean
</methods> <methods> Refactory.Browser.RBConfigurableFormatter class <category>public interface</category>
format: aParseTree ^self format: aParseTree withIndents: 0
format: aParseTree withIndents: anInteger ^(self new) indent: anInteger; format: aParseTree
</methods> <methods> Refactory.Browser.RBSpecialCharacterToken <category>testing</category>
isSpecial ^true
</methods> <methods> Refactory.Browser.RBSpecialCharacterToken <category>private</category>
length ^1
</methods> <methods> Refactory.Browser.RBMessageNode <category>comparing</category>
= anObject self == anObject ifTrue: [^true]. self class = anObject class ifFalse: [^false]. (self receiver = anObject receiver and: [self selector = anObject selector]) ifFalse: [^false]. 1 to: self arguments size do: [:i | (self arguments at: i) = (anObject arguments at: i) ifFalse: [^false]]. ^true
equalTo: anObject withMapping: aDictionary self class = anObject class ifFalse: [^false]. ((self receiver equalTo: anObject receiver withMapping: aDictionary) and: [self selector = anObject selector]) ifFalse: [^false]. 1 to: self arguments size do: [:i | ((self arguments at: i) equalTo: (anObject arguments at: i) withMapping: aDictionary) ifFalse: [^false]]. ^true
hash ^(self receiver hash bitXor: self selector hash) bitXor: (self arguments isEmpty ifTrue: [0] ifFalse: [self arguments first hash])
</methods> <methods> Refactory.Browser.RBMessageNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptMessageNode: self
</methods> <methods> Refactory.Browser.RBMessageNode <category>accessing</category>
arguments ^arguments isNil ifTrue: [#()] ifFalse: [arguments]
arguments: argCollection arguments := argCollection. arguments do: [:each | each parent: self]
children ^(OrderedCollection with: self receiver) addAll: self arguments; yourself
numArgs ^self selector numArgs
precedence ^self isUnary ifTrue: [1] ifFalse: [self isKeyword ifTrue: [3] ifFalse: [2]]
receiver ^receiver
receiver: aValueNode receiver := aValueNode. receiver parent: self
renameSelector: newSelector andArguments: varNodeCollection self arguments: varNodeCollection; selector: newSelector
selector ^selector == nil ifTrue: [selector := self composeSelector: selectorParts] ifFalse: [selector]
selector: aSelector | keywords numArgs | keywords := aSelector keywords. numArgs := aSelector numArgs. numArgs == arguments size ifFalse: [self error: (#AssignmentWithWrongArgNumber << #browser >> 'Attempting to assign selector with wrong number of arguments.')]. selectorParts := numArgs == 0 ifTrue: [Array with: (RBIdentifierToken value: keywords first start: nil)] ifFalse: [keywords first last == $: ifTrue: [keywords collect: [:each | RBKeywordToken value: each start: nil]] ifFalse: [Array with: (RBBinarySelectorToken value: aSelector start: nil)]]. selector := aSelector
sentMessages ^(super sentMessages) add: self selector; yourself
startWithoutParentheses ^receiver start
stopWithoutParentheses ^arguments isEmpty ifTrue: [selectorParts first stop] ifFalse: [arguments last stop]
</methods> <methods> Refactory.Browser.RBMessageNode <category>querying</category>
bestNodeFor: anInterval (self intersectsInterval: anInterval) ifFalse: [^nil]. (self containedBy: anInterval) ifTrue: [^self]. selectorParts do: [:each | ((anInterval first between: each start and: each stop) or: [each start between: anInterval first and: anInterval last]) ifTrue: [^self]]. self children do: [:each | | node | node := each bestNodeFor: anInterval. node notNil ifTrue: [^node]]
</methods> <methods> Refactory.Browser.RBMessageNode <category>private</category>
buildSelector | selectorStream | selectorStream := WriteStream on: (String new: 50). selectorParts do: [:each | selectorStream nextPutAll: each value]. ^selectorStream contents asSymbol
selectorParts ^selectorParts
selectorParts: tokenCollection selectorParts := tokenCollection
</methods> <methods> Refactory.Browser.RBMessageNode <category>testing</category>
isBinary ^(self isUnary or: [self isKeyword]) not
isCascaded ^parent notNil and: [parent isCascade]
isFirstCascaded ^self isCascaded and: [parent messages first == self]
isKeyword ^selectorParts first value last == $:
isMessage ^true
isUnary ^arguments isEmpty
lastIsReturn ^(#(#ifTrue:ifFalse: #ifFalse:ifTrue:) includes: self selector) and: [arguments first isBlock and: [arguments first body lastIsReturn and: [arguments last isBlock and: [arguments last body lastIsReturn]]]]
needsParenthesis ^parent isNil ifTrue: [false] ifFalse: [self precedence > parent precedence or: [self precedence = parent precedence and: [self isUnary not]]]
</methods> <methods> Refactory.Browser.RBMessageNode <category>matching</category>
copyInContext: aDictionary ^(self class new) receiver: (receiver copyInContext: aDictionary); selectorParts: (selectorParts collect: [:each | each removePositions]); arguments: (arguments collect: [:each | each copyInContext: aDictionary]); yourself
match: aNode inContext: aDictionary aNode class == self class ifFalse: [^false]. self selector == aNode selector ifFalse: [^false]. (receiver match: aNode receiver inContext: aDictionary) ifFalse: [^false]. 1 to: arguments size do: [:i | ((arguments at: i) match: (aNode arguments at: i) inContext: aDictionary) ifFalse: [^false]]. ^true
</methods> <methods> Refactory.Browser.RBMessageNode <category>copying</category>
postCopy super postCopy. receiver := receiver copy. arguments := arguments collect: [:each | each copy]
</methods> <methods> Refactory.Browser.RBMessageNode <category>initialize-release</category>
receiver: aValueNode selectorParts: keywordTokens arguments: valueNodes self receiver: aValueNode. selectorParts := keywordTokens. self arguments: valueNodes
</methods> <methods> Refactory.Browser.RBMessageNode <category>replacing</category>
replaceNode: aNode withNode: anotherNode "If we're inside a cascade node and are changing the receiver, change all the receivers" receiver == aNode ifTrue: [self receiver: anotherNode. (parent notNil and: [parent isCascade]) ifTrue: [parent messages do: [:each | each receiver: anotherNode]]]. self arguments: (arguments collect: [:each | each == aNode ifTrue: [anotherNode] ifFalse: [each]])
</methods> <methods> Refactory.Browser.RBMessageNode <category>private-replacing</category>
isContainmentReplacement: aNode ^(self mappingFor: self receiver) = aNode or: [self arguments anySatisfy: [:each | (self mappingFor: each) = aNode]]
replaceContainmentSourceWith: aNode | originalNode needsParenthesis | needsParenthesis := aNode hasParentheses not and: [aNode needsParenthesis]. originalNode := (self mappingFor: self receiver) = aNode ifTrue: [self receiver] ifFalse: [self arguments detect: [:each | (self mappingFor: each) = aNode]]. self addReplacement: (RBStringReplacement replaceFrom: self start to: originalNode start - 1 with: (needsParenthesis ifTrue: ['('] ifFalse: [''])); addReplacement: (RBStringReplacement replaceFrom: originalNode stop + 1 to: self stop with: (needsParenthesis ifTrue: [')'] ifFalse: ['']))
replaceSourceWith: aNode (self isContainmentReplacement: aNode) ifTrue: [^self replaceContainmentSourceWith: aNode]. aNode isMessage ifFalse: [^super replaceSourceWith: aNode]. ^self replaceSourceWithMessageNode: aNode
replaceSourceWithMessageNode: aNode | isBinaryToKeyword | self numArgs = aNode numArgs ifFalse: [^super replaceSourceWith: aNode]. (self mappingFor: self receiver) = aNode receiver ifFalse: [^super replaceSourceWith: aNode]. self arguments with: aNode arguments do: [:old :new | (self mappingFor: old) = new ifFalse: [^super replaceSourceWith: aNode]]. (isBinaryToKeyword := self isBinary and: [aNode isKeyword]) ifTrue: [(self hasParentheses not and: [self parent precedence <= aNode precedence]) ifTrue: [self addReplacement: (RBStringReplacement replaceFrom: self start to: self start - 1 with: '('); addReplacement: (RBStringReplacement replaceFrom: self stop + 1 to: self stop with: ')')]]. self selectorParts with: aNode selectorParts do: [:old :new | old value ~= new value ifTrue: [self addReplacement: (RBStringReplacement replaceFrom: old start to: old stop with: ((isBinaryToKeyword and: [(self source at: old start - 1) isSeparator not]) ifTrue: [' ' , new value] ifFalse: [new value]))]]
</methods> <methods> Refactory.Browser.RBMessageNode class <category>instance creation</category>
receiver: aValueNode selector: aSymbol ^self receiver: aValueNode selector: aSymbol arguments: #()
receiver: aValueNode selector: aSymbol arguments: valueNodes ^(self new) receiver: aValueNode; arguments: valueNodes; selector: aSymbol; yourself
receiver: aValueNode selectorParts: keywordTokens arguments: valueNodes ^(self new) receiver: aValueNode selectorParts: keywordTokens arguments: valueNodes; yourself
</methods> <methods> Refactory.Browser.RBPatternMessageNode <category>matching</category>
copyInContext: aDictionary | selectors | self isList ifTrue: [^aDictionary at: self]. selectors := self isSelectorList ifTrue: [(aDictionary at: selectorParts first value) keywords] ifFalse: [selectorParts collect: [:each | aDictionary at: each value]]. ^(RBMessageNode new) receiver: (receiver copyInContext: aDictionary); selectorParts: (selectors collect: [:each | (each last == $: ifTrue: [RBKeywordToken] ifFalse: [RBIdentifierToken]) value: each start: nil]); arguments: (self copyList: arguments inContext: aDictionary); yourself
match: aNode inContext: aDictionary aNode class == self matchingClass ifFalse: [^false]. (receiver match: aNode receiver inContext: aDictionary) ifFalse: [^false]. self isSelectorList ifTrue: [^(aDictionary at: selectorParts first value ifAbsentPut: [aNode selector]) == aNode selector and: [(aDictionary at: arguments first ifAbsentPut: [aNode arguments]) = aNode arguments]]. ^self matchArgumentsAgainst: aNode inContext: aDictionary
matchArgumentsAgainst: aNode inContext: aDictionary self arguments size == aNode arguments size ifFalse: [^false]. (self matchSelectorAgainst: aNode inContext: aDictionary) ifFalse: [^false]. 1 to: arguments size do: [:i | ((arguments at: i) match: (aNode arguments at: i) inContext: aDictionary) ifFalse: [^false]]. ^true
matchSelectorAgainst: aNode inContext: aDictionary | keyword | 1 to: selectorParts size do: [:i | keyword := selectorParts at: i. (aDictionary at: keyword value ifAbsentPut: [keyword isPatternVariable ifTrue: [(aNode selectorParts at: i) value] ifFalse: [keyword value]]) = (aNode selectorParts at: i) value ifFalse: [^false]]. ^true
</methods> <methods> Refactory.Browser.RBPatternMessageNode <category>testing-matching</category>
isList ^isCascadeList and: [parent notNil and: [parent isCascade]]
isPatternNode ^true
isSelectorList ^isList
</methods> <methods> Refactory.Browser.RBPatternMessageNode <category>private</category>
matchingClass ^RBMessageNode
</methods> <methods> Refactory.Browser.RBPatternMessageNode <category>initialize-release</category>
receiver: aValueNode selectorParts: keywordTokens arguments: valueNodes | message | super receiver: aValueNode selectorParts: keywordTokens arguments: valueNodes. isCascadeList := isList := false. message := keywordTokens first value. 2 to: message size do: [:i | | character | character := message at: i. character == self listCharacter ifTrue: [isList := true] ifFalse: [character == self cascadeListCharacter ifTrue: [isCascadeList := true] ifFalse: [^self]]]
</methods> <methods> Refactory.Browser.RBPatternMessageNode <category>accessing</category>
sentMessages ^(super sentMessages) remove: self selector ifAbsent: []; yourself
</methods> <methods> Refactory.Browser.RBPatternMessageNode class <category>instance creation</category>
receiver: aValueNode selectorParts: keywordTokens arguments: valueNodes ^(keywordTokens anySatisfy: [:each | each isPatternVariable]) ifTrue: [super receiver: aValueNode selectorParts: keywordTokens arguments: valueNodes] ifFalse: [RBMessageNode receiver: aValueNode selectorParts: keywordTokens arguments: valueNodes]
</methods> <methods> Refactory.Browser.RBScanner <category>testing</category>
atEnd ^characterType == #eof
isReadable ^true
isWritable ^false
</methods> <methods> Refactory.Browser.RBScanner <category>accessing</category>
contents | contentsStream | contentsStream := WriteStream on: (Array new: 50). self do: [:each | contentsStream nextPut: each]. ^contentsStream contents
errorBlock: aBlock errorBlock := aBlock
flush
getComments | oldComments | comments isEmpty ifTrue: [^nil]. oldComments := comments. comments := OrderedCollection new: 1. ^oldComments
next | token | buffer reset. tokenStart := stream position. token := characterType == #eof ifTrue: [RBToken start: tokenStart + 1 "The EOF token should occur after the end of input"] ifFalse: [self scanToken]. self stripSeparators. token comments: self getComments. ^token
nextPut: anObject "Provide an error notification that the receiver does not implement this message." self shouldNotImplement
position: aPosition "Use this very sparingly and very carefully. We need to reset any intermediate state." stream position: aPosition
scanToken "fast-n-ugly. Don't write stuff like this. Has been found to cause cancer in laboratory rats. Basically a case statement. Didn't use Dictionary because lookup is pretty slow." characterType == #alphabetic ifTrue: [^self scanIdentifierOrKeyword]. (characterType == #digit or: [currentCharacter == $- and: [(self classify: stream peek) == #digit]]) ifTrue: [^self scanNumber]. characterType == #binary ifTrue: [^self scanBinary: RBBinarySelectorToken]. characterType == #special ifTrue: [^self scanSpecialCharacter]. currentCharacter == $' ifTrue: [^self scanLiteralString]. currentCharacter == $# ifTrue: [^self scanLiteral]. currentCharacter == $$ ifTrue: [^self scanLiteralCharacter]. ^self scannerError: (#UnknownCharacter << #browser >> 'Unknown character')
skipUntil: aCharacter | position | (stream skipThrough: aCharacter) isNil ifTrue: [self scannerError: ((#x1sNotFound << #browser >> '<1s> not found') expandMacrosWith: (String with: aCharacter))]. position := stream position. self step. self stripSeparators. ^position
sourceStream ^stream
</methods> <methods> Refactory.Browser.RBScanner <category>private</category>
classify: aCharacter | index | aCharacter isNil ifTrue: [^nil]. index := aCharacter asInteger. index == 0 ifTrue: [^#separator]. index > 255 ifTrue: [^aCharacter isLetter ifTrue: [#alphabetic] ifFalse: [aCharacter isSeparator ifTrue: [#separator] ifFalse: [nil]]]. ^classificationTable at: index
previousStepPosition ^characterType == #eof ifTrue: [stream position] ifFalse: [stream position - 1]
step stream atEnd ifTrue: [characterType := #eof. ^currentCharacter := nil]. currentCharacter := stream next. characterType := self classify: currentCharacter. ^currentCharacter
</methods> <methods> Refactory.Browser.RBScanner <category>error handling</category>
errorBlock ^errorBlock isNil ifTrue: [[:message :position | ]] ifFalse: [errorBlock]
errorPosition ^stream position
scannerError: aString "Evaluate the block. If it returns raise an error" self errorBlock value: aString value: self errorPosition. self error: aString
</methods> <methods> Refactory.Browser.RBScanner <category>initialize-release</category>
on: aStream buffer := WriteStream on: (String new: 60). stream := aStream. classificationTable := self class classificationTable. comments := OrderedCollection new
</methods> <methods> Refactory.Browser.RBScanner <category>private-scanning</category>
scanAnySymbol characterType == #alphabetic ifTrue: [^self scanSymbol]. characterType == #binary ifTrue: [^self scanBinary: RBLiteralToken]. ^RBToken new
scanBinary: aClass "This doesn't parse according to the ANSI draft. It only parses 1 or 2 letter binary tokens." | val | buffer nextPut: currentCharacter. self step. (characterType == #binary and: [currentCharacter ~~ $-]) ifTrue: [buffer nextPut: currentCharacter. self step]. val := buffer contents. val := val asSymbol. ^aClass value: val start: tokenStart
scanIdentifierOrKeyword | token name | self scanName. currentCharacter == $. ifTrue: [token := self scanNameSpaceName. token notNil ifTrue: [^token]]. (currentCharacter == $: and: [stream peek ~~ $=]) ifTrue: [^self scanKeyword]. name := buffer contents. name = 'true' ifTrue: [^RBLiteralToken value: true start: tokenStart stop: self previousStepPosition]. name = 'false' ifTrue: [^RBLiteralToken value: false start: tokenStart stop: self previousStepPosition]. name = 'nil' ifTrue: [^RBLiteralToken value: nil start: tokenStart stop: self previousStepPosition]. ^RBIdentifierToken value: name start: tokenStart
scanKeyword | outputPosition inputPosition name | [currentCharacter == $:] whileTrue: [buffer nextPut: currentCharacter. outputPosition := buffer position. inputPosition := stream position. self step. ":" [characterType == #alphabetic] whileTrue: [self scanName]]. buffer position: outputPosition. stream position: inputPosition. self step. name := buffer contents. ^(name occurrencesOf: $:) == 1 ifTrue: [RBKeywordToken value: name start: tokenStart] ifFalse: [RBMultiKeywordLiteralToken value: name asSymbol start: tokenStart stop: tokenStart + name size - 1]
scanLiteral self step. self stripSeparators. characterType == #alphabetic ifTrue: [^self scanSymbol]. characterType == #binary ifTrue: [^(self scanBinary: RBLiteralToken) stop: self previousStepPosition]. currentCharacter == $' ifTrue: [^self scanStringSymbol]. (currentCharacter == $( or: [currentCharacter == $[]) ifTrue: [^self scanLiteralArrayToken]. currentCharacter == ${ ifTrue: [^self scanQualifiedReference]. self scannerError: #ExpectingALiteralType << #browser >> 'Expecting a literal type'
scanLiteralArrayToken | token | token := RBLiteralArrayToken value: (String with: $# with: currentCharacter) start: tokenStart. self step. ^token
scanLiteralCharacter | token | self step. "$" token := RBLiteralToken value: currentCharacter start: tokenStart stop: stream position. self step. "char" ^token
scanLiteralString self step. [currentCharacter isNil ifTrue: [self scannerError: (#UnmatchedQuoteInString << #browser >> 'Unmatched '' in string literal.')]. currentCharacter == $' and: [self step ~~ $']] whileFalse: [buffer nextPut: currentCharacter. self step]. ^RBLiteralToken value: buffer contents start: tokenStart stop: self previousStepPosition
scanName [characterType == #alphabetic or: [characterType == #digit]] whileTrue: [buffer nextPut: currentCharacter. self step]
scanNameSpaceName (stream atEnd or: [(self classify: stream peek) ~~ #alphabetic]) ifTrue: [^nil]. buffer nextPut: $.. self step. self scanName. currentCharacter == $. ifTrue: [self scanNameSpaceName]. ^RBIdentifierToken value: buffer contents start: tokenStart
scanNumber | start number stop string currentPosition | start := stream position. stream skip: -1. number := Number readSmalltalkSyntaxFrom: stream. self step. currentPosition := stream position. stop := self atEnd ifTrue: [currentPosition] ifFalse: [currentPosition - 1]. stream position: start - 1. string := stream next: stop - start + 1. stream position: currentPosition. ^RBNumberLiteralToken value: number start: start stop: stop source: string
scanPatternVariable buffer nextPut: currentCharacter. self step. currentCharacter == ${ ifTrue: [self step. ^RBPatternBlockToken value: '`{' start: tokenStart]. [characterType == #alphabetic] whileFalse: [characterType == #eof ifTrue: [self scannerError: (#MetaVariableExpected << #browser >> 'Meta variable expected')]. buffer nextPut: currentCharacter. self step]. ^self scanIdentifierOrKeyword
scanQualifiedReference | nameToken | self step. "{" self stripSeparators. nameToken := self scanIdentifierOrKeyword. (nameToken isIdentifier and: [nameToken value notEmpty]) ifFalse: [self scannerError: (#InvalidNameInQRef << #browser >> 'Invalid name in qualified reference')]. self stripSeparators. currentCharacter == $} ifFalse: [self scannerError: (#CloseBraceExpected << #browser >> '} expected')]. self step. "}" ^RBLiteralToken value: (BindingReference pathString: nameToken value) start: tokenStart stop: self previousStepPosition
scanSpecialCharacter | character | currentCharacter == $: ifTrue: [self step. ^currentCharacter == $= ifTrue: [self step. RBAssignmentToken start: tokenStart] ifFalse: [RBSpecialCharacterToken value: $: start: tokenStart]]. character := currentCharacter. self step. ^RBSpecialCharacterToken value: character start: tokenStart
scanStringSymbol | literalToken | literalToken := self scanLiteralString. literalToken value: literalToken value asSymbol. ^literalToken
scanSymbol | lastPosition hasColon value startPosition | hasColon := false. startPosition := lastPosition := stream position. [characterType == #alphabetic] whileTrue: [self scanName. currentCharacter == $: ifTrue: [buffer nextPut: $:. hasColon := true. lastPosition := stream position. self step]]. value := buffer contents. (hasColon and: [value last ~~ $:]) ifTrue: [stream position: lastPosition. self step. value := value copyFrom: 1 to: lastPosition - startPosition + 1]. ^RBLiteralToken value: value asSymbol start: tokenStart stop: self previousStepPosition
stripComment | start stop | start := stream position. [self step == $"] whileFalse: [characterType == #eof ifTrue: [self scannerError: (#UnmatchedQuoteInComment << #browser >> 'Unmatched " in comment.')]]. stop := stream position. self step. comments add: (start to: stop)
stripSeparators [[characterType == #separator] whileTrue: [self step]. currentCharacter == $"] whileTrue: [self stripComment]
</methods> <methods> Refactory.Browser.RBScanner class <category>accessing</category>
classificationTable classificationTable isNil ifTrue: [self initializeClassificationTable]. ^classificationTable
patternVariableCharacter ^PatternVariableCharacter
</methods> <methods> Refactory.Browser.RBScanner class <category>class initialization</category>
initialize self initializeClassificationTable
initializeChars: characters to: aSymbol characters do: [:c | classificationTable at: c asInteger put: aSymbol]
initializeClassificationTable | allCharacters | PatternVariableCharacter := $`. classificationTable := Array new: 255. allCharacters := (1 to: 255) collect: [:i | Character value: i]. self initializeChars: (allCharacters select: [:each | each isLetter]) to: #alphabetic. self initializeChars: '_' to: #alphabetic. self initializeChars: '01234567890' to: #digit. self initializeChars: '!%&*+,-/<=>?@\~|' to: #binary. classificationTable at: 177 put: #binary. "plus-or-minus" classificationTable at: 183 put: #binary. "centered dot" classificationTable at: 215 put: #binary. "times" classificationTable at: 247 put: #binary. "divide" self initializeChars: '().:;[]^' to: #special. self initializeChars: (allCharacters select: [:each | each isSeparator]) to: #separator
</methods> <methods> Refactory.Browser.RBScanner class <category>testing</category>
isSelector: aSymbol | scanner token | scanner := self basicNew. scanner on: (ReadStream on: aSymbol asString). scanner step. token := scanner scanAnySymbol. token isLiteralToken ifFalse: [^false]. token value isEmpty ifTrue: [^false]. ^scanner atEnd
isVariable: aString | scanner token | scanner := self on: (ReadStream on: aString) errorBlock: [:s :p | ^false]. token := scanner next. token isIdentifier ifFalse: [^false]. (token start = 1 and: [token stop = aString size]) ifFalse: [^false]. ^(aString includes: $.) not
</methods> <methods> Refactory.Browser.RBScanner class <category>instance creation</category>
on: aStream | str | str := self basicNew on: aStream. str step; stripSeparators. ^str
on: aStream errorBlock: aBlock | str | str := self basicNew on: aStream. str errorBlock: aBlock; step; stripSeparators. ^str
</methods> <methods> Refactory.Browser.RBPatternScanner <category>accessing</category>
scanToken currentCharacter == PatternVariableCharacter ifTrue: [^self scanPatternVariable]. currentCharacter == $} ifTrue: [^self scanSpecialCharacter]. ^super scanToken
</methods> <methods> Refactory.Browser.RBSequenceNode <category>comparing</category>
= anObject "Can't send = to the temporaries and statements collection since they might change from arrays to OCs" self == anObject ifTrue: [^true]. self class = anObject class ifFalse: [^false]. self temporaries size = anObject temporaries size ifFalse: [^false]. 1 to: self temporaries size do: [:i | (self temporaries at: i) = (anObject temporaries at: i) ifFalse: [^false]]. self statements size = anObject statements size ifFalse: [^false]. 1 to: self statements size do: [:i | (self statements at: i) = (anObject statements at: i) ifFalse: [^false]]. ^true
equalTo: anObject withMapping: aDictionary self class = anObject class ifFalse: [^false]. self statements size == anObject statements size ifFalse: [^false]. 1 to: self statements size do: [:i | ((self statements at: i) equalTo: (anObject statements at: i) withMapping: aDictionary) ifFalse: [^false]]. aDictionary values asSet size = aDictionary size ifFalse: [^false]. "Not a one-to-one mapping" self temporaries do: [:each | aDictionary removeKey: each name ifAbsent: []]. ^true
hash ^self temporaries hash bitXor: (self statements isEmpty ifTrue: [0] ifFalse: [self statements first hash])
</methods> <methods> Refactory.Browser.RBSequenceNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptSequenceNode: self
</methods> <methods> Refactory.Browser.RBSequenceNode <category>adding nodes</category>
addNode: aNode aNode parent: self. (statements notEmpty and: [statements last isReturn]) ifTrue: [self error: (#CannotAddStmtAfterReturn << #browser >> 'Cannot add statement after return node')]. statements := (statements asOrderedCollection) add: aNode; yourself
addNode: aNode before: anotherNode | index | index := self indexOfNode: anotherNode. index = 0 ifTrue: [^self addNode: aNode]. statements := (statements asOrderedCollection) add: aNode beforeIndex: index; yourself. aNode parent: self
addNodeFirst: aNode aNode parent: self. statements := (statements asOrderedCollection) addFirst: aNode; yourself
addNodes: aCollection aCollection do: [:each | each parent: self]. (statements notEmpty and: [statements last isReturn]) ifTrue: [self error: (#CannotAddStmtAfterReturn << #browser >> 'Cannot add statement after return node')]. statements := (statements asOrderedCollection) addAll: aCollection; yourself
addNodes: aCollection before: anotherNode aCollection do: [:each | self addNode: each before: anotherNode]
addNodesFirst: aCollection aCollection do: [:each | each parent: self]. statements := (statements asOrderedCollection) addAllFirst: aCollection; yourself
addSelfReturn | node | self lastIsReturn ifTrue: [^self]. node := RBReturnNode value: (RBVariableNode named: 'self'). self addNode: node
addTemporariesNamed: aCollection aCollection do: [:each | self addTemporaryNamed: each]
addTemporaryNamed: aString | variableNode | variableNode := RBVariableNode named: aString. variableNode parent: self. temporaries := temporaries copyWith: variableNode
</methods> <methods> Refactory.Browser.RBSequenceNode <category>accessing</category>
addReturn | node | statements isEmpty ifTrue: [^nil]. statements last isReturn ifTrue: [^statements last]. node := RBReturnNode value: statements last. statements at: statements size put: node. node parent: self. ^node
allDefinedVariables ^(self temporaryNames asOrderedCollection) addAll: super allDefinedVariables; yourself
allTemporaryVariables ^(self temporaryNames asOrderedCollection) addAll: super allTemporaryVariables; yourself
children ^(OrderedCollection new) addAll: self temporaries; addAll: self statements; yourself
methodComments | methodComments | methodComments := OrderedCollection withAll: self comments. temporaries do: [:each | methodComments addAll: each comments]. (parent notNil and: [parent isBlock]) ifTrue: [parent arguments do: [:each | methodComments addAll: each comments]]. ^methodComments asSortedCollection: [:a :b | a first < b first]
periods: anObject periods := anObject
removeTemporaryNamed: aName temporaries := temporaries reject: [:each | each name = aName]
start ^leftBar isNil ifTrue: [statements isEmpty ifTrue: [1] ifFalse: [statements first start]] ifFalse: [leftBar]
statements ^statements
statements: stmtCollection statements := stmtCollection. statements do: [:each | each parent: self]
stop ^(periods isEmpty ifTrue: [0] ifFalse: [periods last]) max: (statements isEmpty ifTrue: [0] ifFalse: [statements last stop])
temporaries ^temporaries
temporaries: tempCollection temporaries := tempCollection. temporaries do: [:each | each parent: self]
temporaryNames ^temporaries collect: [:each | each name]
temporaryVariables ^(super temporaryVariables asOrderedCollection) addAll: self temporaryNames; yourself
</methods> <methods> Refactory.Browser.RBSequenceNode <category>querying</category>
bestNodeFor: anInterval | node | node := super bestNodeFor: anInterval. node == self ifTrue: [(temporaries isEmpty and: [statements size == 1]) ifTrue: [^statements first]]. ^node
whichNodeIsContainedBy: anInterval | node | node := super whichNodeIsContainedBy: anInterval. node == self ifTrue: [(temporaries isEmpty and: [statements size == 1]) ifTrue: [^statements first]]. ^node
</methods> <methods> Refactory.Browser.RBSequenceNode <category>matching</category>
copyInContext: aDictionary ^(self class new) temporaries: (self copyList: temporaries inContext: aDictionary); statements: (self copyList: statements inContext: aDictionary); yourself
match: aNode inContext: aDictionary self class == aNode class ifFalse: [^false]. ^(self matchList: temporaries against: aNode temporaries inContext: aDictionary) and: [self matchList: statements against: aNode statements inContext: aDictionary]
</methods> <methods> Refactory.Browser.RBSequenceNode <category>testing</category>
defines: aName ^temporaries anySatisfy: [:each | each name = aName]
directlyUses: aNode ^false
isLast: aNode | last | statements isEmpty ifTrue: [^false]. last := statements last. ^last == aNode or: [last isMessage and: [(#(#ifTrue:ifFalse: #ifFalse:ifTrue:) includes: last selector) and: [last arguments anySatisfy: [:each | each isLast: aNode]]]]
isSequence ^true
lastIsReturn ^statements notEmpty and: [statements last lastIsReturn]
references: aVariableName ^statements anySatisfy: [:each | each references: aVariableName]
uses: aNode statements isEmpty ifTrue: [^false]. aNode == statements last ifFalse: [^false]. ^self isUsed
</methods> <methods> Refactory.Browser.RBSequenceNode <category>private</category>
indexOfNode: aNode "Try to find the node by first looking for ==, and then for =" ^(1 to: statements size) detect: [:each | (statements at: each) == aNode] ifNone: [statements indexOf: aNode]
</methods> <methods> Refactory.Browser.RBSequenceNode <category>initialize-release</category>
leftBar: leftInteger temporaries: variableNodes rightBar: rightInteger leftBar := leftInteger. self temporaries: variableNodes. rightBar := rightInteger
</methods> <methods> Refactory.Browser.RBSequenceNode <category>copying</category>
postCopy super postCopy. temporaries := temporaries collect: [:each | each copy]. statements := statements collect: [:each | each copy]
</methods> <methods> Refactory.Browser.RBSequenceNode <category>replacing</category>
removeDeadCode (self isUsed ifTrue: [statements size - 1] ifFalse: [statements size]) to: 1 by: -1 do: [:i | (statements at: i) isImmediateNode ifTrue: [self clearReplacements. statements removeAtIndex: i]]. super removeDeadCode
removeNode: aNode self replaceNode: aNode withNodes: #()
replaceNode: aNode withNode: anotherNode self statements: (statements collect: [:each | each == aNode ifTrue: [anotherNode] ifFalse: [each]]). self temporaries: (temporaries collect: [:each | each == aNode ifTrue: [anotherNode] ifFalse: [each]])
replaceNode: aNode withNodes: aCollection | index newStatements | self clearReplacements. index := self indexOfNode: aNode. newStatements := OrderedCollection new: statements size + aCollection size. 1 to: index - 1 do: [:i | newStatements add: (statements at: i)]. newStatements addAll: aCollection. index + 1 to: statements size do: [:i | newStatements add: (statements at: i)]. aCollection do: [:each | each parent: self]. statements := newStatements
</methods> <methods> Refactory.Browser.RBSequenceNode class <category>instance creation</category>
leftBar: leftInteger temporaries: variableNodes rightBar: rightInteger ^(self new) leftBar: leftInteger temporaries: variableNodes rightBar: rightInteger; yourself
statements: statementNodes ^self temporaries: #() statements: statementNodes
temporaries: variableNodes statements: statementNodes ^(self new) temporaries: variableNodes; statements: statementNodes; yourself
</methods> <methods> Refactory.Browser.ParseTreeSearcher <category>accessing</category>
addArgumentRule: aParseTreeRule argumentSearches add: aParseTreeRule. aParseTreeRule owner: self
addArgumentRules: ruleCollection ruleCollection do: [:each | self addArgumentRule: each]
addRule: aParseTreeRule searches add: aParseTreeRule. aParseTreeRule owner: self
addRules: ruleCollection ruleCollection do: [:each | self addRule: each]
answer ^answer
context ^context
executeMethod: aParseTree initialAnswer: anObject answer := anObject. searches detect: [:each | (each performOn: aParseTree) notNil] ifNone: []. ^answer
executeTree: aParseTree "Save our current context, in case someone is performing another search inside a match." | oldContext | oldContext := context. context := RBSmallDictionary new. self visitNode: aParseTree. context := oldContext. ^answer
executeTree: aParseTree initialAnswer: aValue answer := aValue. ^self executeTree: aParseTree
messages messages notNil ifTrue: [^messages]. argumentSearches notEmpty ifTrue: [^messages := #()]. messages := Set new. searches do: [:each | | searchMessages | searchMessages := each sentMessages. RBProgramNode optimizedSelectors do: [:sel | searchMessages remove: sel ifAbsent: []]. searchMessages isEmpty ifTrue: [^messages := #()]. messages addAll: searchMessages]. ^messages := messages asArray
</methods> <methods> Refactory.Browser.ParseTreeSearcher <category>initialize-release</category>
answer: anObject answer := anObject
initialize super initialize. context := RBSmallDictionary new. searches := OrderedCollection new. argumentSearches := OrderedCollection new: 0. answer := nil
</methods> <methods> Refactory.Browser.ParseTreeSearcher <category>testing</category>
canMatchMethod: aCompiledMethod ^self messages isEmpty or: [self messages anySatisfy: [:each | aCompiledMethod sendsSelector: each]]
</methods> <methods> Refactory.Browser.ParseTreeSearcher <category>private</category>
foundMatch
lookForMoreMatchesInContext: oldContext oldContext keysAndValuesDo: [:key :value | (key isString not and: [key recurseInto]) ifTrue: [value do: [:each | self visitNode: each]]]
performSearches: aSearchCollection on: aNode | value | 1 to: aSearchCollection size do: [:i | value := (aSearchCollection at: i) performOn: aNode. value notNil ifTrue: [self foundMatch. ^value]]. ^nil
recursivelySearchInContext "We need to save the matched context since the other searches might overwrite it." | oldContext | oldContext := context. context := RBSmallDictionary new. self lookForMoreMatchesInContext: oldContext. context := oldContext
</methods> <methods> Refactory.Browser.ParseTreeSearcher <category>searching</category>
matches: aString do: aBlock self addRule: (RBSearchRule searchFor: aString thenDo: aBlock)
matchesAnyArgumentOf: stringCollection do: aBlock stringCollection do: [:each | self matchesArgument: each do: aBlock]
matchesAnyMethodOf: aStringCollection do: aBlock aStringCollection do: [:each | self matchesMethod: each do: aBlock]
matchesAnyOf: aStringCollection do: aBlock aStringCollection do: [:each | self matches: each do: aBlock]
matchesAnyTreeOf: treeCollection do: aBlock treeCollection do: [:each | self matchesTree: each do: aBlock]
matchesArgument: aString do: aBlock self addArgumentRule: (RBSearchRule searchFor: aString thenDo: aBlock)
matchesArgumentTree: aBRProgramNode do: aBlock self addArgumentRule: (RBSearchRule searchForTree: aBRProgramNode thenDo: aBlock)
matchesMethod: aString do: aBlock self addRule: (RBSearchRule searchForMethod: aString thenDo: aBlock)
matchesTree: aBRProgramNode do: aBlock self addRule: (RBSearchRule searchForTree: aBRProgramNode thenDo: aBlock)
</methods> <methods> Refactory.Browser.ParseTreeSearcher <category>visiting</category>
visitArgument: aNode | value | value := self performSearches: argumentSearches on: aNode. ^value isNil ifTrue: [aNode acceptVisitor: self. aNode] ifFalse: [value]
visitNode: aNode | value | value := self performSearches: searches on: aNode. ^value isNil ifTrue: [aNode acceptVisitor: self. aNode] ifFalse: [value]
</methods> <methods> Refactory.Browser.ParseTreeSearcher class <category>private</category>
buildSelectorString: aSelector | stream keywords | aSelector numArgs = 0 ifTrue: [^aSelector]. stream := WriteStream on: String new. keywords := aSelector keywords. 1 to: keywords size do: [:i | stream nextPutAll: (keywords at: i); nextPutAll: ' ``@arg'; nextPutAll: i printString; nextPut: $ ]. ^stream contents
buildSelectorTree: aSelector aSelector isEmpty ifTrue: [^nil]. ^RBParser parseRewriteExpression: '``@receiver ' , (self buildSelectorString: aSelector) onError: [:err :pos | ^nil]
buildTree: aString method: aBoolean ^aBoolean ifTrue: [RBParser parseRewriteMethod: aString] ifFalse: [RBParser parseRewriteExpression: aString]
</methods> <methods> Refactory.Browser.ParseTreeSearcher class <category>instance creation</category>
getterMethod: aVarName ^(self new) matchesMethod: '`method ^' , aVarName do: [:aNode :ans | aNode selector]; yourself
justSendsSuper ^(self new) matchesAnyMethodOf: #('`@method: `@Args ^super `@method: `@Args' '`@method: `@Args super `@method: `@Args') do: [:aNode :ans | true]; yourself
returnSetterMethod: aVarName ^(self new) matchesMethod: '`method: `Arg ^' , aVarName , ' := `Arg' do: [:aNode :ans | aNode selector]; yourself
setterMethod: aVarName ^(self new) matchesAnyMethodOf: (Array with: '`method: `Arg ' , aVarName , ' := `Arg' with: '`method: `Arg ^' , aVarName , ' := `Arg') do: [:aNode :ans | aNode selector]; yourself
</methods> <methods> Refactory.Browser.ParseTreeSearcher class <category>accessing</category>
treeMatching: aString in: aParseTree (self new) matches: aString do: [:aNode :answer | ^aNode]; executeTree: aParseTree. ^nil
treeMatchingStatements: aString in: aParseTree | notifier tree | notifier := self new. tree := RBParser parseExpression: aString. tree isSequence ifFalse: [tree := RBSequenceNode statements: (Array with: tree)]. tree temporaries: (Array with: (RBPatternVariableNode named: '`@temps')). tree addNodeFirst: (RBPatternVariableNode named: '`@.S1'). tree lastIsReturn ifFalse: [tree addNode: (RBPatternVariableNode named: '`@.S2')]. notifier matchesTree: tree do: [:aNode :answer | ^RBParser parseExpression: aString]. notifier executeTree: aParseTree. ^nil
</methods> <methods> Refactory.Browser.RBIdentifierToken <category>testing</category>
isIdentifier ^true
isPatternVariable ^value first == RBScanner patternVariableCharacter
</methods> <methods> Refactory.Browser.RBTagNode <category>accessing</category>
arguments ^arguments isNil ifTrue: [#()] ifFalse: [arguments]
arguments: argCollection arguments := argCollection. arguments do: [:each | each parent: self]
brackets ^brackets
brackets: anInterval brackets := anInterval
children ^self arguments
numArgs ^self selector numArgs
selector ^selector == nil ifTrue: [selector := self composeSelector: selectorParts] ifFalse: [selector]
sentMessages ^self selector
start ^brackets first
stop ^brackets last
</methods> <methods> Refactory.Browser.RBTagNode <category>testing</category>
isKeyword ^self isUnary not
isUnary ^arguments isEmpty
</methods> <methods> Refactory.Browser.RBTagNode <category>private</category>
buildSelector | selectorStream | selectorStream := WriteStream on: (String new: 50). selectorParts do: [:each | selectorStream nextPutAll: each value]. ^selectorStream contents asSymbol
selectorParts ^selectorParts
selectorParts: tokenCollection selectorParts := tokenCollection
</methods> <methods> Refactory.Browser.RBTagNode <category>copying</category>
postCopy super postCopy. arguments := arguments collect: [:each | each copy]
</methods> <methods> Refactory.Browser.RBTagNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor aProgramNodeVisitor acceptTagNode: self
</methods> <methods> Refactory.Browser.RBTagNode <category>comparing</category>
= anObject self == anObject ifTrue: [^true]. self class = anObject class ifFalse: [^false]. self selector = anObject selector ifFalse: [^false]. arguments keysAndValuesDo: [:i :each | each = (anObject arguments at: i) ifFalse: [^false]]. ^true
hash ^self selector hash bitXor: (self arguments isEmpty ifTrue: [0] ifFalse: [self arguments first hash])
</methods> <methods> Refactory.Browser.RBTagNode <category>initialize-release</category>
selectorParts: keywordTokens arguments: valueNodes self selectorParts: keywordTokens. self arguments: valueNodes
</methods> <methods> Refactory.Browser.RBTagNode class <category>instance creation</category>
selectorParts: keywordTokens arguments: valueNodes ^(self new) selectorParts: keywordTokens arguments: valueNodes; yourself
</methods> <methods> Refactory.Browser.RBCDeclarationNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor aProgramNodeVisitor acceptCDeclarationNode: self
</methods> <methods> Refactory.Browser.RBCDeclarationNode <category>accessing</category>
cDelcarationText ^self arguments first value
</methods> <methods> Refactory.Browser.RBPatternWrapperBlockNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptPatternWrapperBlockNode: self
</methods> <methods> Refactory.Browser.RBPatternWrapperBlockNode <category>matching</category>
copyInContext: aDictionary "I don't know what this would mean, so ignore it." ^wrappedNode copyInContext: aDictionary
match: aNode inContext: aDictionary (wrappedNode match: aNode inContext: aDictionary) ifFalse: [^false]. ^super match: aNode inContext: aDictionary
</methods> <methods> Refactory.Browser.RBPatternWrapperBlockNode <category>accessing</category>
precedence ^1
wrappedNode ^wrappedNode
wrappedNode: aRBProgramNode wrappedNode := aRBProgramNode. aRBProgramNode parent: self
</methods> <methods> Refactory.Browser.RBLiteralNode <category>comparing</category>
= anObject self == anObject ifTrue: [^true]. ^self class == anObject class
hash ^self value hash
</methods> <methods> Refactory.Browser.RBLiteralNode <category>testing</category>
isImmediateNode ^true
isLiteralNode ^true
needsParenthesis ^false
</methods> <methods> Refactory.Browser.RBLiteralNode <category>accessing</category>
precedence ^0
value ^self subclassResponsibility
</methods> <methods> Refactory.Browser.RBLiteralNode <category>private-replacing</category>
replaceSourceFrom: aNode self addReplacement: (RBStringReplacement replaceFrom: aNode start to: aNode stop with: self formattedCode)
replaceSourceWith: aNode self addReplacement: (RBStringReplacement replaceFrom: self start to: self stop with: aNode formattedCode)
</methods> <methods> Refactory.Browser.RBLiteralNode class <category>instance creation</category>
literalToken: aLiteralToken ^(aLiteralToken realValue class == Array or: [aLiteralToken realValue class == ByteArray]) ifTrue: [RBLiteralArrayNode startPosition: aLiteralToken start contents: (aLiteralToken value asArray collect: [:each | RBLiteralNode literalToken: each]) stopPosition: aLiteralToken stop isByteArray: aLiteralToken value class ~~ Array] ifFalse: [RBLiteralValueNode literalToken: aLiteralToken]
value: aValue ^((aValue class == Array or: [aValue class == ByteArray]) ifTrue: [RBLiteralArrayNode] ifFalse: [RBLiteralValueNode]) value: aValue
</methods> <methods> Refactory.Browser.RBLiteralArrayNode <category>copying</category>
postCopy super postCopy. contents := contents collect: [:each | each copy]
</methods> <methods> Refactory.Browser.RBLiteralArrayNode <category>accessing</category>
children ^contents
contents ^contents
startWithoutParentheses ^start
stopWithoutParentheses ^stop
value | array | array := (isByteArray ifTrue: [ByteArray] ifFalse: [Array]) new: contents size. 1 to: contents size do: [:each | array at: each put: (contents at: each) value]. ^array
</methods> <methods> Refactory.Browser.RBLiteralArrayNode <category>initialize-release</category>
contents: aRBLiteralNodeCollection contents := aRBLiteralNodeCollection. contents do: [:each | each parent: self]
startPosition: startInteger contents: anArray stopPosition: stopInteger isByteArray: aBoolean start := startInteger. self contents: anArray. stop := stopInteger. isByteArray := aBoolean
</methods> <methods> Refactory.Browser.RBLiteralArrayNode <category>replacing</category>
replaceNode: aNode withNode: anotherNode self contents: (contents collect: [:each | each == aNode ifTrue: [anotherNode] ifFalse: [each]])
</methods> <methods> Refactory.Browser.RBLiteralArrayNode <category>comparing</category>
= anObject super = anObject ifFalse: [^false]. self isForByteArray = anObject isForByteArray ifFalse: [^false]. self contents size = anObject contents size ifFalse: [^false]. 1 to: self contents size do: [:i | (self contents at: i) = (anObject contents at: i) ifFalse: [^false]]. ^true
equalTo: anObject withMapping: aDictionary self class = anObject class ifFalse: [^false]. self isForByteArray = anObject isForByteArray ifFalse: [^false]. self contents size = anObject contents size ifFalse: [^false]. 1 to: self contents size do: [:i | ((self contents at: i) equalTo: (anObject contents at: i) withMapping: aDictionary) ifFalse: [^false]]. ^true
</methods> <methods> Refactory.Browser.RBLiteralArrayNode <category>testing</category>
isForByteArray ^isByteArray
isLiteralArray ^true
looksLikeStructuredArrayEncoding "This is a guess, but pretty good. Basically it looks structured when every other symbol looks like a keyword message send. Also to skip something like a tag array (e.g. #(#pragma1: #pragma2: #pragma3:), we make sure that the odd elements includes at least some objects that are not symbols." ^self isForByteArray not and: [self children size > 2 and: [((2 to: self children size by: 2) allSatisfy: [:n | | each | each := self children at: n. each value isSymbol and: [each value isKeyword]]) and: [(1 to: self children size by: 2) anySatisfy: [:n | | each | each := self children at: n. each value isSymbol not]]]]
</methods> <methods> Refactory.Browser.RBLiteralArrayNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptLiteralArrayNode: self
</methods> <methods> Refactory.Browser.RBLiteralArrayNode <category>matching</category>
copyInContext: aDictionary ^self class startPosition: nil contents: (self copyList: contents inContext: aDictionary) stopPosition: nil isByteArray: isByteArray
match: aNode inContext: aDictionary aNode class == self class ifFalse: [^false]. self isForByteArray = aNode isForByteArray ifFalse: [^false]. ^self matchList: contents against: aNode contents inContext: aDictionary
</methods> <methods> Refactory.Browser.RBLiteralArrayNode <category>private-replacing</category>
replaceSourceWith: aNode (self class = aNode class and: [self isForByteArray = aNode isForByteArray and: [self contents size = aNode contents size]]) ifFalse: [^super replaceSourceWith: aNode]. 1 to: self contents size do: [:i | (self contents at: i) = (aNode contents at: i) ifFalse: [(self contents at: i) replaceSourceWith: (aNode contents at: i)]]
</methods> <methods> Refactory.Browser.RBLiteralArrayNode class <category>instance creation</category>
startPosition: startInteger contents: anArray stopPosition: stopInteger isByteArray: aBoolean ^(self new) startPosition: startInteger contents: anArray stopPosition: stopInteger isByteArray: aBoolean; yourself
value: aValue ^(self new) startPosition: nil contents: (aValue asArray collect: [:each | RBLiteralNode value: each]) stopPosition: nil isByteArray: aValue class ~~ Array; yourself
</methods> <methods> Refactory.Browser.RBReturnNode <category>comparing</category>
= anObject self == anObject ifTrue: [^true]. self class = anObject class ifFalse: [^false]. ^self value = anObject value
equalTo: anObject withMapping: aDictionary ^self class = anObject class and: [self value equalTo: anObject value withMapping: aDictionary]
hash ^self value hash
</methods> <methods> Refactory.Browser.RBReturnNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptReturnNode: self
</methods> <methods> Refactory.Browser.RBReturnNode <category>accessing</category>
children ^Array with: value
start ^return
stop ^value stop
value ^value
value: valueNode value := valueNode. value parent: self
</methods> <methods> Refactory.Browser.RBReturnNode <category>testing</category>
containsReturn ^true
isReturn ^true
</methods> <methods> Refactory.Browser.RBReturnNode <category>matching</category>
copyInContext: aDictionary ^(self class new) value: (value copyInContext: aDictionary); yourself
match: aNode inContext: aDictionary aNode class == self class ifFalse: [^false]. ^value match: aNode value inContext: aDictionary
</methods> <methods> Refactory.Browser.RBReturnNode <category>copying</category>
postCopy super postCopy. value := value copy
</methods> <methods> Refactory.Browser.RBReturnNode <category>replacing</category>
replaceNode: aNode withNode: anotherNode value == aNode ifTrue: [self value: anotherNode]
</methods> <methods> Refactory.Browser.RBReturnNode <category>initialize-release</category>
return: returnInteger value: aValueNode return := returnInteger. self value: aValueNode
</methods> <methods> Refactory.Browser.RBReturnNode class <category>instance creation</category>
return: returnInteger value: aValueNode ^self new return: returnInteger value: aValueNode
value: aNode ^self return: nil value: aNode
</methods> <methods> Refactory.Browser.RBBinarySelectorToken <category>testing</category>
isBinary ^true
</methods> <methods> Refactory.Browser.RBAssignmentToken <category>testing</category>
isAssignment ^true
</methods> <methods> Refactory.Browser.RBAssignmentToken <category>private</category>
length ^2
</methods> <methods> Refactory.Browser.RBLiteralArrayToken <category>testing</category>
isForByteArray ^value last = $[
isLiteralArrayToken ^true
</methods> <methods> Refactory.Browser.RBKeywordToken <category>testing</category>
isKeyword ^true
isPatternVariable ^value first == RBScanner patternVariableCharacter
</methods> <methods> Refactory.Browser.RBAssignmentNode <category>comparing</category>
= anObject self == anObject ifTrue: [^true]. self class = anObject class ifFalse: [^false]. ^self variable = anObject variable and: [self value = anObject value]
equalTo: anObject withMapping: aDictionary ^self class = anObject class and: [(self variable equalTo: anObject variable withMapping: aDictionary) and: [self value equalTo: anObject value withMapping: aDictionary]]
hash ^self variable hash bitXor: self value hash
</methods> <methods> Refactory.Browser.RBAssignmentNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptAssignmentNode: self
</methods> <methods> Refactory.Browser.RBAssignmentNode <category>testing</category>
assigns: aVariableName ^variable name = aVariableName or: [value assigns: aVariableName]
directlyUses: aNode ^aNode = value ifTrue: [true] ifFalse: [self isDirectlyUsed]
isAssignment ^true
needsParenthesis ^parent isNil ifTrue: [false] ifFalse: [self precedence > parent precedence]
uses: aNode ^aNode = value ifTrue: [true] ifFalse: [self isUsed]
</methods> <methods> Refactory.Browser.RBAssignmentNode <category>querying</category>
bestNodeFor: anInterval (self intersectsInterval: anInterval) ifFalse: [^nil]. (self containedBy: anInterval) ifTrue: [^self]. assignment isNil ifTrue: [^super bestNodeFor: anInterval]. ((anInterval first between: assignment and: assignment + 1) or: [assignment between: anInterval first and: anInterval last]) ifTrue: [^self]. self children do: [:each | | node | node := each bestNodeFor: anInterval. node notNil ifTrue: [^node]]
</methods> <methods> Refactory.Browser.RBAssignmentNode <category>accessing</category>
assignmentPosition ^assignment
children ^Array with: value with: variable
precedence ^5
startWithoutParentheses ^variable start
stopWithoutParentheses ^value stop
value ^value
value: aValueNode value := aValueNode. value parent: self
variable ^variable
variable: varNode variable := varNode. variable parent: self
</methods> <methods> Refactory.Browser.RBAssignmentNode <category>matching</category>
copyInContext: aDictionary ^(self class new) variable: (variable copyInContext: aDictionary); value: (value copyInContext: aDictionary); yourself
match: aNode inContext: aDictionary aNode class == self class ifFalse: [^false]. ^(variable match: aNode variable inContext: aDictionary) and: [value match: aNode value inContext: aDictionary]
</methods> <methods> Refactory.Browser.RBAssignmentNode <category>copying</category>
postCopy super postCopy. variable := variable postCopy. value := value postCopy
</methods> <methods> Refactory.Browser.RBAssignmentNode <category>replacing</category>
replaceNode: aNode withNode: anotherNode value == aNode ifTrue: [self value: anotherNode]. variable == aNode ifTrue: [self variable: anotherNode]
replaceSourceWith: aNode "Check if we are being replaced with a setter message send. If so, create the replacements to edit the original source." aNode isMessage ifFalse: [^super replaceSourceWith: aNode]. aNode receiver isVariable ifFalse: [^super replaceSourceWith: aNode]. aNode numArgs = 1 ifFalse: [^super replaceSourceWith: aNode]. (self mappingFor: self value) = aNode arguments first ifFalse: [^super replaceSourceWith: aNode]. (self value hasParentheses not and: [aNode arguments first precedence >= aNode precedence]) ifTrue: [self addReplacement: (RBStringReplacement replaceFrom: self value start to: self value start - 1 with: '('); addReplacement: (RBStringReplacement replaceFrom: self value stop + 1 to: self value stop with: ')')]. self addReplacement: (RBStringReplacement replaceFrom: self variable start to: self assignmentPosition + 1 with: aNode receiver name , ' ' , aNode selector)
</methods> <methods> Refactory.Browser.RBAssignmentNode <category>initialize-release</category>
variable: aVariableNode value: aValueNode position: anInteger self variable: aVariableNode. self value: aValueNode. assignment := anInteger
</methods> <methods> Refactory.Browser.RBAssignmentNode class <category>instance creation</category>
variable: aVariableNode value: aValueNode ^self variable: aVariableNode value: aValueNode position: nil
variable: aVariableNode value: aValueNode position: anInteger ^(self new) variable: aVariableNode value: aValueNode position: anInteger; yourself
</methods> <methods> Refactory.Browser.RBLiteralValueNode <category>accessing</category>
startWithoutParentheses ^token start
stopWithoutParentheses ^token stop
token ^token
value ^token realValue
</methods> <methods> Refactory.Browser.RBLiteralValueNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptLiteralNode: self
</methods> <methods> Refactory.Browser.RBLiteralValueNode <category>initialize-release</category>
literalToken: aLiteralToken token := aLiteralToken
</methods> <methods> Refactory.Browser.RBLiteralValueNode <category>matching</category>
copyInContext: aDictionary ^self class literalToken: token removePositions
</methods> <methods> Refactory.Browser.RBLiteralValueNode <category>comparing</category>
= anObject ^super = anObject and: [self value = anObject value and: [self value species == anObject value species]]
</methods> <methods> Refactory.Browser.RBLiteralValueNode class <category>instance creation</category>
literalToken: aLiteralToken ^(self new) literalToken: aLiteralToken; yourself
value: aValue ^self literalToken: (RBLiteralToken value: aValue)
</methods> <methods> Refactory.Browser.RBVariableNode <category>comparing</category>
= anObject self == anObject ifTrue: [^true]. self class = anObject class ifFalse: [^false]. ^self name = anObject name
equalTo: anObject withMapping: aDictionary ^self class = anObject class and: [(aDictionary at: self name ifAbsentPut: [anObject name]) = anObject name]
hash ^self name hash
</methods> <methods> Refactory.Browser.RBVariableNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptVariableNode: self
</methods> <methods> Refactory.Browser.RBVariableNode <category>matching</category>
copyInContext: aDictionary ^self class identifierToken: token removePositions
</methods> <methods> Refactory.Browser.RBVariableNode <category>initialize-release</category>
identifierToken: anIdentifierToken token := anIdentifierToken
</methods> <methods> Refactory.Browser.RBVariableNode <category>testing</category>
isImmediateNode ^true
isLocalVariable "Do I represent a variable that is bound tighter than the instance variable scope? Special variables, temps, and args qualifiy." ^'self' = self name or: ['super' = self name or: ['thisContext' = self name or: [(self whoDefines: self name) notNil]]]
isVariable ^true
needsParenthesis ^false
references: aVariableName ^self name = aVariableName
</methods> <methods> Refactory.Browser.RBVariableNode <category>accessing</category>
name ^token value
precedence ^0
startWithoutParentheses ^token start
stopWithoutParentheses ^token stop
</methods> <methods> Refactory.Browser.RBVariableNode <category>replacing</category>
replaceSourceFrom: aNode self addReplacement: (RBStringReplacement replaceFrom: aNode start to: aNode stop with: self name)
replaceSourceWith: aNode self addReplacement: (RBStringReplacement replaceFrom: self start to: self stop with: aNode formattedCode)
</methods> <methods> Refactory.Browser.RBVariableNode class <category>instance creation</category>
identifierToken: anIdentifierToken ^(self new) identifierToken: anIdentifierToken; yourself
named: aString ^self identifierToken: (RBIdentifierToken value: aString start: 0)
</methods> <methods> Refactory.Browser.RBPatternVariableNode <category>initialize-release</category>
identifierToken: anIdentifierToken super identifierToken: anIdentifierToken. self initializePatternVariables
initializePatternVariables | name | name := self name. isAnything := isList := isLiteral := isStatement := recurseInto := false. 2 to: name size do: [:i | | character | character := name at: i. character == self listCharacter ifTrue: [isAnything := isList := true] ifFalse: [character == self literalCharacter ifTrue: [isLiteral := true] ifFalse: [character == self statementCharacter ifTrue: [isStatement := true] ifFalse: [character == self recurseIntoCharacter ifTrue: [recurseInto := true] ifFalse: [^self]]]]]
</methods> <methods> Refactory.Browser.RBPatternVariableNode <category>testing-matching</category>
isAnything ^isAnything
isList ^isList
isLiteralNode ^isLiteral
isPatternNode ^true
isStatement ^isStatement
recurseInto ^recurseInto
</methods> <methods> Refactory.Browser.RBPatternVariableNode <category>private</category>
matchingClass ^RBVariableNode
</methods> <methods> Refactory.Browser.RBPatternVariableNode <category>matching</category>
copyInContext: aDictionary ^(aDictionary at: self) copy
match: aNode inContext: aDictionary self isAnything ifTrue: [^(aDictionary at: self ifAbsentPut: [aNode]) = aNode]. self isLiteralNode ifTrue: [^self matchLiteral: aNode inContext: aDictionary]. self isStatement ifTrue: [^self matchStatement: aNode inContext: aDictionary]. aNode class == self matchingClass ifFalse: [^false]. ^(aDictionary at: self ifAbsentPut: [aNode]) = aNode
matchLiteral: aNode inContext: aDictionary ^aNode isLiteralNode and: [(aDictionary at: self ifAbsentPut: [aNode]) = aNode]
matchStatement: aNode inContext: aDictionary (aNode parent notNil and: [aNode parent isSequence]) ifFalse: [^false]. ^(aDictionary at: self ifAbsentPut: [aNode]) = aNode
</methods> <methods> Refactory.Browser.RBPatternVariableNode <category>accessing</category>
parent: aBRProgramNode "Fix the case where '``@node' should match a single node, not a sequence node." super parent: aBRProgramNode. parent isSequence ifTrue: [(self isStatement or: [parent temporaries includes: self]) ifFalse: [isList := false]]
</methods> <methods> Refactory.Browser.RBPatternVariableNode class <category>instance creation</category>
identifierToken: anIdentifierToken ^anIdentifierToken isPatternVariable ifTrue: [super identifierToken: anIdentifierToken] ifFalse: [RBVariableNode identifierToken: anIdentifierToken]
</methods> <methods> Refactory.Browser.RBReplaceRule <category>matching</category>
canMatch: aProgramNode ^verificationBlock value: aProgramNode
foundMatchFor: aProgramNode self subclassResponsibility
replace: aProgramNode with: newNode aProgramNode replaceMethodSource: newNode
</methods> <methods> Refactory.Browser.RBReplaceRule <category>initialize-release</category>
initialize super initialize. verificationBlock := [:aNode | true]
</methods> <methods> Refactory.Browser.RBBlockReplaceRule <category>initialize-release</category>
initialize super initialize. replaceBlock := [:aNode | aNode]
searchFor: searchString replaceWith: aBlock self searchString: searchString. replaceBlock := aBlock
searchFor: searchString replaceWith: replBlock when: verifyBlock self searchFor: searchString replaceWith: replBlock. verificationBlock := verifyBlock
searchForMethod: searchString replaceWith: aBlock self methodSearchString: searchString. replaceBlock := aBlock
searchForMethod: searchString replaceWith: replBlock when: verifyBlock self searchForMethod: searchString replaceWith: replBlock. verificationBlock := verifyBlock
searchForTree: aBRProgramNode replaceWith: aBlock searchTree := aBRProgramNode. replaceBlock := aBlock
searchForTree: aBRProgramNode replaceWith: replBlock when: verifyBlock self searchForTree: aBRProgramNode replaceWith: replBlock. verificationBlock := verifyBlock
</methods> <methods> Refactory.Browser.RBBlockReplaceRule <category>matching</category>
foundMatchFor: aProgramNode | newNode | newNode := replaceBlock value: aProgramNode. aProgramNode replaceMethodSource: newNode. ^newNode
</methods> <methods> Refactory.Browser.RBBlockReplaceRule class <category>instance creation</category>
searchFor: searchString replaceWith: replaceBlock ^self new searchFor: searchString replaceWith: replaceBlock
searchFor: searchString replaceWith: replaceBlock when: aBlock ^self new searchFor: searchString replaceWith: replaceBlock when: aBlock
searchForMethod: searchString replaceWith: replaceBlock ^self new searchForMethod: searchString replaceWith: replaceBlock
searchForMethod: searchString replaceWith: replaceBlock when: aBlock ^self new searchForMethod: searchString replaceWith: replaceBlock when: aBlock
searchForTree: aRBProgramNode replaceWith: replaceBlock ^self new searchForTree: aRBProgramNode replaceWith: replaceBlock
searchForTree: aRBProgramNode replaceWith: replaceBlock when: aBlock ^self new searchForTree: aRBProgramNode replaceWith: replaceBlock when: aBlock
</methods> <methods> Refactory.Browser.RBPatternBlockToken <category>testing</category>
isPatternBlock ^true
</methods> <methods> Refactory.Browser.RBMethodNode <category>comparing</category>
= anObject self == anObject ifTrue: [^true]. self class = anObject class ifFalse: [^false]. (self selector = anObject selector and: [self body = anObject body]) ifFalse: [^false]. 1 to: self arguments size do: [:i | (self arguments at: i) = (anObject arguments at: i) ifFalse: [^false]]. ^true
equalTo: anObject withMapping: aDictionary self class = anObject class ifFalse: [^false]. (self selector = anObject selector and: [self body equalTo: anObject body withMapping: aDictionary]) ifFalse: [^false]. 1 to: self arguments size do: [:i | ((self arguments at: i) equalTo: (anObject arguments at: i) withMapping: aDictionary) ifFalse: [^false]. aDictionary removeKey: (self arguments at: i) name]. ^self primitiveSources = anObject primitiveSources
hash ^(self selector hash bitXor: self body hash) bitXor: self arguments hash
</methods> <methods> Refactory.Browser.RBMethodNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptMethodNode: self
</methods> <methods> Refactory.Browser.RBMethodNode <category>accessing</category>
addNode: aNode ^body addNode: aNode
addReturn body addReturn
addSelfReturn ^body addSelfReturn
allArgumentVariables ^(self argumentNames asOrderedCollection) addAll: super allArgumentVariables; yourself
allDefinedVariables ^(self argumentNames asOrderedCollection) addAll: super allDefinedVariables; yourself
argumentNames ^self arguments collect: [:each | each name]
arguments ^arguments
arguments: variableNodes arguments := variableNodes. arguments do: [:each | each parent: self]
body ^body
body: stmtsNode body := stmtsNode. body parent: self
children ^self arguments , self tags copyWith: self body
methodComments | methodComments | methodComments := OrderedCollection withAll: self comments. arguments do: [:each | methodComments addAll: each comments]. ^methodComments asSortedCollection: [:a :b | a first < b first]
methodNode ^self
newSource replacements isNil ifTrue: [^self formattedCode]. ^[self reformatSource] on: Error do: [:ex | ex return: self formattedCode]
numArgs ^self selector numArgs
primitiveSources ^self tags collect: [:each | self source copyFrom: each start to: each stop]
renameSelector: newSelector andArguments: varNodeCollection | oldSelectorParts oldArguments | oldSelectorParts := selectorParts. oldArguments := arguments. self arguments: varNodeCollection; selector: newSelector. self changeSourceSelectors: oldSelectorParts arguments: oldArguments
selector ^selector == nil ifTrue: [selector := self composeSelector: selectorParts] ifFalse: [selector]
selector: aSelector | keywords numArgs | keywords := aSelector keywords. numArgs := aSelector numArgs. numArgs == arguments size ifFalse: [self error: (#AssignmentWithWrongArgNumber << #browser >> 'Attempting to assign selector with wrong number of arguments.')]. selectorParts := numArgs == 0 ifTrue: [Array with: (RBIdentifierToken value: keywords first start: nil)] ifFalse: [keywords first last == $: ifTrue: [keywords collect: [:each | RBKeywordToken value: each start: nil]] ifFalse: [Array with: (RBBinarySelectorToken value: aSelector start: nil)]]. selector := aSelector
source ^source
source: anObject source := anObject
start ^1
stop ^source size
tagCount ^tags size
tags ^tags isNil ifTrue: [#()] ifFalse: [tags]
tags: aCollectionOfIntervals tags := aCollectionOfIntervals. self tagsDo: [:each | each parent: self]
tagsDo: aBlock "Shortcut for tags do:. A preponderance of methods have no tags, so we can shortcircuit this with a nil check" tags == nil ifTrue: [^self]. tags do: aBlock
</methods> <methods> Refactory.Browser.RBMethodNode <category>private</category>
buildSelector | selectorStream | selectorStream := WriteStream on: (String new: 50). selectorParts do: [:each | selectorStream nextPutAll: each value]. ^selectorStream contents asSymbol
reformatSource | newSource stream | stream := WriteStream on: (String new: source size + 100). stream nextPutAll: (source copyFrom: (replacements inject: 1 into: [:sum :each | stream nextPutAll: (source copyFrom: sum to: each startPosition - 1); nextPutAll: each string. each stopPosition + 1]) to: source size). newSource := stream contents. self = (RBParser parseMethod: newSource onError: [:s :p | ^self formattedCode]) ifFalse: [^self formattedCode]. "Sanity check -- make sure the formatted code is = self" ^newSource
selectorParts ^selectorParts
selectorParts: tokenCollection selectorParts := tokenCollection
</methods> <methods> Refactory.Browser.RBMethodNode <category>matching</category>
copyInContext: aDictionary ^(self class new) selectorParts: (selectorParts collect: [:each | each removePositions]); arguments: (arguments collect: [:each | each copyInContext: aDictionary]); body: (body copyInContext: aDictionary); source: (aDictionary at: '-source-'); yourself
match: aNode inContext: aDictionary self class == aNode class ifFalse: [^false]. aDictionary at: '-source-' put: aNode source. self selector == aNode selector ifFalse: [^false]. ^(self matchList: arguments against: aNode arguments inContext: aDictionary) and: [body match: aNode body inContext: aDictionary]
</methods> <methods> Refactory.Browser.RBMethodNode <category>testing</category>
defines: aName ^arguments anySatisfy: [:each | each name = aName]
isLast: aNode ^body isLast: aNode
isMethod ^true
isPrimitive self tagsDo: [:each | each selector = #primitive: ifTrue: [^true]]. ^false
lastIsReturn ^body lastIsReturn
references: aVariableName ^body references: aVariableName
uses: aNode ^body == aNode and: [aNode lastIsReturn]
</methods> <methods> Refactory.Browser.RBMethodNode <category>copying</category>
postCopy super postCopy. body := body copy. arguments := arguments collect: [:each | each copy]
</methods> <methods> Refactory.Browser.RBMethodNode <category>replacing</category>
addReplacement: aStringReplacement replacements isNil ifTrue: [^self]. replacements add: aStringReplacement
clearReplacements replacements := nil
map: oldNode to: newNode nodeReplacements at: oldNode put: newNode
mappingFor: oldNode ^nodeReplacements at: oldNode ifAbsent: [oldNode]
replaceNode: aNode withNode: anotherNode aNode == body ifTrue: [self body: anotherNode]. self arguments: (arguments collect: [:each | each == aNode ifTrue: [anotherNode] ifFalse: [each]])
</methods> <methods> Refactory.Browser.RBMethodNode <category>initialize-release</category>
initialize replacements := SortedCollection sortBlock: [:a :b | a startPosition < b startPosition or: [a startPosition = b startPosition and: [a stopPosition < b stopPosition]]]. nodeReplacements := IdentityDictionary new
selectorParts: tokenCollection arguments: variableNodes selectorParts := tokenCollection. self arguments: variableNodes
</methods> <methods> Refactory.Browser.RBMethodNode <category>printing</category>
printOn: aStream aStream nextPutAll: self formattedCode
</methods> <methods> Refactory.Browser.RBMethodNode <category>private-replacing</category>
changeSourceSelectors: oldSelectorParts arguments: oldArguments [oldSelectorParts size = selectorParts size ifFalse: [^self]. oldArguments size = arguments size ifFalse: [^self]. oldSelectorParts with: selectorParts do: [:old :new | self addReplacement: (RBStringReplacement replaceFrom: old start to: old stop with: new value)]. oldArguments with: arguments do: [:old :new | self addReplacement: (RBStringReplacement replaceFrom: old start to: old stop with: new name)]] on: Error do: [:ex | ex return]
</methods> <methods> Refactory.Browser.RBMethodNode class <category>instance creation</category>
new ^(super new) initialize; yourself
selector: aSymbol arguments: variableNodes body: aSequenceNode ^(self new) arguments: variableNodes; selector: aSymbol; body: aSequenceNode; yourself
selector: aSymbol body: aSequenceNode ^self selector: aSymbol arguments: #() body: aSequenceNode
selectorParts: tokenCollection arguments: variableNodes ^(self new) selectorParts: tokenCollection arguments: variableNodes; yourself
</methods> <methods> Refactory.Browser.RBPatternMethodNode <category>matching</category>
copyInContext: aDictionary | selectors | selectors := self isSelectorList ifTrue: [(aDictionary at: selectorParts first value) keywords] ifFalse: [selectorParts collect: [:each | aDictionary at: each value]]. ^(RBMethodNode new) selectorParts: (selectors collect: [:each | (each last == $: ifTrue: [RBKeywordToken] ifFalse: [RBIdentifierToken]) value: each start: nil]); arguments: (self copyList: arguments inContext: aDictionary); body: (body copyInContext: aDictionary); source: (aDictionary at: '-source-'); yourself
match: aNode inContext: aDictionary aNode class == self matchingClass ifFalse: [^false]. aDictionary at: '-source-' put: aNode source. self isSelectorList ifTrue: [^(aDictionary at: selectorParts first value ifAbsentPut: [aNode selector]) = aNode selector and: [(aDictionary at: arguments first ifAbsentPut: [aNode arguments]) = aNode arguments and: [body match: aNode body inContext: aDictionary]]]. ^(self matchArgumentsAgainst: aNode inContext: aDictionary) and: [body match: aNode body inContext: aDictionary]
matchArgumentsAgainst: aNode inContext: aDictionary self arguments size == aNode arguments size ifFalse: [^false]. (self matchSelectorAgainst: aNode inContext: aDictionary) ifFalse: [^false]. 1 to: arguments size do: [:i | ((arguments at: i) match: (aNode arguments at: i) inContext: aDictionary) ifFalse: [^false]]. ^true
matchSelectorAgainst: aNode inContext: aDictionary | keyword | 1 to: selectorParts size do: [:i | keyword := selectorParts at: i. (aDictionary at: keyword value ifAbsentPut: [keyword isPatternVariable ifTrue: [(aNode selectorParts at: i) value] ifFalse: [keyword value]]) = (aNode selectorParts at: i) value ifFalse: [^false]]. ^true
</methods> <methods> Refactory.Browser.RBPatternMethodNode <category>testing-matching</category>
isPatternNode ^true
</methods> <methods> Refactory.Browser.RBPatternMethodNode <category>testing</category>
isSelectorList ^isList
</methods> <methods> Refactory.Browser.RBPatternMethodNode <category>private</category>
matchingClass ^RBMethodNode
</methods> <methods> Refactory.Browser.RBPatternMethodNode <category>initialize-release</category>
selectorParts: tokenCollection arguments: variableNodes super selectorParts: tokenCollection arguments: variableNodes. isList := (tokenCollection first value at: 2) == self listCharacter
</methods> <methods> Refactory.Browser.RBPatternMethodNode class <category>instance creation</category>
selectorParts: tokenCollection arguments: variableNodes ^(tokenCollection anySatisfy: [:each | each isPatternVariable]) ifTrue: [super selectorParts: tokenCollection arguments: variableNodes] ifFalse: [RBMethodNode selectorParts: tokenCollection arguments: variableNodes]
</methods> <methods> Refactory.Browser.RBStringReplaceRule <category>initialize-release</category>
methodReplaceString: replaceString replaceTree := RBParser parseRewriteMethod: replaceString
replaceString: replaceString replaceTree := RBParser parseRewriteExpression: replaceString. searchTree isSequence = replaceTree isSequence ifFalse: [searchTree isSequence ifTrue: [replaceTree := RBSequenceNode statements: (Array with: replaceTree)] ifFalse: [searchTree := RBSequenceNode statements: (Array with: searchTree)]]
searchFor: searchString replaceWith: replaceString self searchString: searchString. self replaceString: replaceString
searchFor: searchString replaceWith: replaceString when: aBlock self searchFor: searchString replaceWith: replaceString. verificationBlock := aBlock
searchForMethod: searchString replaceWith: replaceString self methodSearchString: searchString. self methodReplaceString: replaceString
searchForMethod: searchString replaceWith: replaceString when: aBlock self searchForMethod: searchString replaceWith: replaceString. verificationBlock := aBlock
searchForTree: aBRProgramNode replaceWith: replaceNode searchTree := aBRProgramNode. replaceTree := replaceNode
searchForTree: aBRProgramNode replaceWith: replaceString when: aBlock self searchForTree: aBRProgramNode replaceWith: replaceString. verificationBlock := aBlock
</methods> <methods> Refactory.Browser.RBStringReplaceRule <category>matching</category>
foundMatchFor: aProgramNode | newNode | newNode := replaceTree copyInContext: self context. aProgramNode replaceMethodSource: newNode. newNode copyCommentsFrom: aProgramNode. ^newNode
</methods> <methods> Refactory.Browser.RBStringReplaceRule class <category>instance creation</category>
searchFor: searchString replaceWith: replaceString ^self new searchFor: searchString replaceWith: replaceString
searchFor: searchString replaceWith: replaceString when: aBlock ^self new searchFor: searchString replaceWith: replaceString when: aBlock
searchForMethod: searchString replaceWith: replaceString ^(self new) searchForMethod: searchString replaceWith: replaceString; yourself
searchForMethod: searchString replaceWith: replaceString when: aBlock ^self new searchForMethod: searchString replaceWith: replaceString when: aBlock
searchForTree: aRBProgramNode replaceWith: replaceString ^self new searchForTree: aRBProgramNode replaceWith: replaceString
searchForTree: aRBProgramNode replaceWith: replaceString when: aBlock ^self new searchForTree: aRBProgramNode replaceWith: replaceString when: aBlock
</methods> <methods> Refactory.Browser.RBSmallDictionary <category>adding</category>
add: anAssociation self at: anAssociation key put: anAssociation value. ^anAssociation
at: key put: value | index | index := self findIndexFor: key. ^index == 0 ifTrue: [self privateAt: key put: value] ifFalse: [values at: index put: value]
</methods> <methods> Refactory.Browser.RBSmallDictionary <category>enumerating</category>
associationsDo: aBlock self keysAndValuesDo: [:key :value | aBlock value: key -> value]
do: aBlock 1 to: size do: [:i | aBlock value: (values at: i)]
keysAndValuesDo: aBlock 1 to: size do: [:i | aBlock value: (keys at: i) value: (values at: i)]
keysDo: aBlock 1 to: size do: [:i | aBlock value: (keys at: i)]
</methods> <methods> Refactory.Browser.RBSmallDictionary <category>accessing</category>
at: key ifAbsent: aBlock | index | index := self findIndexFor: key. ^index == 0 ifTrue: [aBlock value] ifFalse: [values at: index]
at: key ifAbsentPut: aBlock | index | index := self findIndexFor: key. ^index == 0 ifTrue: [self privateAt: key put: aBlock value] ifFalse: [values at: index]
empty size := 0
size ^size
</methods> <methods> Refactory.Browser.RBSmallDictionary <category>private</category>
findIndexFor: aKey 1 to: size do: [:i | (keys at: i) = aKey ifTrue: [^i]]. ^0
growKeysAndValues self growTo: size * 2
growTo: aSize | newKeys newValues | newKeys := Array new: aSize. newValues := Array new: aSize. 1 to: size do: [:i | newKeys at: i put: (keys at: i). newValues at: i put: (values at: i)]. keys := newKeys. values := newValues
privateAt: key put: value size == keys size ifTrue: [self growKeysAndValues]. size := size + 1. keys at: size put: key. ^values at: size put: value
</methods> <methods> Refactory.Browser.RBSmallDictionary <category>testing</category>
includesKey: aKey ^(self findIndexFor: aKey) ~~ 0
</methods> <methods> Refactory.Browser.RBSmallDictionary <category>initialize-release</category>
initialize keys := Array new: 2. values := Array new: 2. size := 0
</methods> <methods> Refactory.Browser.RBSmallDictionary <category>copying</category>
postCopy super postCopy. keys := keys copy. values := values copy
</methods> <methods> Refactory.Browser.RBSmallDictionary <category>removing</category>
remove: oldObject ifAbsent: anExceptionBlock self removeKey: oldObject key ifAbsent: anExceptionBlock. ^oldObject
removeKey: key ifAbsent: aBlock | index value | index := self findIndexFor: key. index == 0 ifTrue: [^aBlock value]. value := values at: index. index to: size - 1 do: [:i | keys at: i put: (keys at: i + 1). values at: i put: (values at: i + 1)]. keys at: size put: nil. values at: size put: nil. size := size - 1. ^value
</methods> <methods> Refactory.Browser.RBSmallDictionary class <category>instance creation</category>
new ^self basicNew initialize
new: aSize "Ignore the size" ^self basicNew initialize
</methods> <methods> Refactory.Browser.ParseTreeRewriter <category>visitor-double dispatching</category>
acceptAssignmentNode: anAssignmentNode anAssignmentNode variable: (self visitNode: anAssignmentNode variable). anAssignmentNode value: (self visitNode: anAssignmentNode value)
acceptBlockNode: aBlockNode aBlockNode arguments: (self visitArguments: aBlockNode arguments). aBlockNode body: (self visitNode: aBlockNode body)
acceptCascadeNode: aCascadeNode | newMessages notFound | newMessages := OrderedCollection new: aCascadeNode messages size. notFound := OrderedCollection new: aCascadeNode messages size. aCascadeNode messages do: [:each | | newNode | newNode := self performSearches: searches on: each. newNode isNil ifTrue: [newNode := each. notFound add: newNode]. newNode isMessage ifTrue: [newMessages add: newNode] ifFalse: [newNode isCascade ifTrue: [newMessages addAll: newNode messages] ifFalse: [Transcript cr; show: (#CannotReplaceMsgInCascade << #browser >> 'Cannot replace message node inside of cascaded node with non-message node.'). newMessages add: each]]]. notFound size == aCascadeNode messages size ifTrue: [| receiver | receiver := self visitNode: aCascadeNode messages first receiver. newMessages do: [:each | each receiver: receiver]]. notFound do: [:each | each arguments: (each arguments collect: [:arg | self visitNode: arg])]. aCascadeNode messages: newMessages
acceptLiteralArrayNode: aRBArrayLiteralNode aRBArrayLiteralNode contents: (aRBArrayLiteralNode contents collect: [:each | self visitNode: each])
acceptMessageNode: aMessageNode aMessageNode receiver: (self visitNode: aMessageNode receiver). aMessageNode arguments: (aMessageNode arguments collect: [:each | self visitNode: each])
acceptMethodNode: aMethodNode aMethodNode tags: (self visitArguments: aMethodNode tags). aMethodNode arguments: (self visitArguments: aMethodNode arguments). aMethodNode body: (self visitNode: aMethodNode body)
acceptOptimizedNode: anOptimizedNode anOptimizedNode body: (self visitNode: anOptimizedNode body)
acceptReturnNode: aReturnNode aReturnNode value: (self visitNode: aReturnNode value)
acceptSequenceNode: aSequenceNode aSequenceNode temporaries: (self visitArguments: aSequenceNode temporaries). aSequenceNode statements: (aSequenceNode statements collect: [:each | self visitNode: each])
acceptTagNodeNode: aTagNode aTagNode arguments: (aTagNode arguments collect: [:each | self visitNode: each])
</methods> <methods> Refactory.Browser.ParseTreeRewriter <category>accessing</category>
executeTree: aParseTree | oldContext | oldContext := context. context := RBSmallDictionary new. answer := false. tree := self visitNode: aParseTree. context := oldContext. ^answer
tree ^tree
</methods> <methods> Refactory.Browser.ParseTreeRewriter <category>private</category>
foundMatch answer := true
lookForMoreMatchesInContext: oldContext oldContext keysAndValuesDo: [:key :value | (key isString not and: [key recurseInto]) ifTrue: [oldContext at: key put: (value collect: [:each | self visitNode: each])]]
</methods> <methods> Refactory.Browser.ParseTreeRewriter <category>replacing</category>
replace: searchString with: replaceString self addRule: (RBStringReplaceRule searchFor: searchString replaceWith: replaceString)
replace: searchString with: replaceString when: aBlock self addRule: (RBStringReplaceRule searchFor: searchString replaceWith: replaceString when: aBlock)
replace: searchString withValueFrom: replaceBlock self addRule: (RBBlockReplaceRule searchFor: searchString replaceWith: replaceBlock)
replace: searchString withValueFrom: replaceBlock when: conditionBlock self addRule: (RBBlockReplaceRule searchFor: searchString replaceWith: replaceBlock when: conditionBlock)
replaceArgument: searchString with: replaceString self addArgumentRule: (RBStringReplaceRule searchFor: searchString replaceWith: replaceString)
replaceArgument: searchString with: replaceString when: aBlock self addArgumentRule: (RBStringReplaceRule searchFor: searchString replaceWith: replaceString when: aBlock)
replaceArgument: searchString withValueFrom: replaceBlock self addArgumentRule: (RBBlockReplaceRule searchFor: searchString replaceWith: replaceBlock)
replaceArgument: searchString withValueFrom: replaceBlock when: conditionBlock self addArgumentRule: (RBBlockReplaceRule searchFor: searchString replaceWith: replaceBlock when: conditionBlock)
replaceMethod: searchString with: replaceString self addRule: (RBStringReplaceRule searchForMethod: searchString replaceWith: replaceString)
replaceMethod: searchString with: replaceString when: aBlock self addRule: (RBStringReplaceRule searchForMethod: searchString replaceWith: replaceString when: aBlock)
replaceMethod: searchString withValueFrom: replaceBlock self addRule: (RBBlockReplaceRule searchForMethod: searchString replaceWith: replaceBlock)
replaceMethod: searchString withValueFrom: replaceBlock when: conditionBlock self addRule: (RBBlockReplaceRule searchForMethod: searchString replaceWith: replaceBlock when: conditionBlock)
replaceTree: searchTree withTree: replaceTree self addRule: (RBStringReplaceRule searchForTree: searchTree replaceWith: replaceTree)
replaceTree: searchTree withTree: replaceTree when: aBlock self addRule: (RBStringReplaceRule searchForTree: searchTree replaceWith: replaceTree when: aBlock)
</methods> <methods> Refactory.Browser.ParseTreeRewriter <category>visiting</category>
visitArguments: aNodeCollection ^aNodeCollection collect: [:each | self visitArgument: each]
</methods> <methods> Refactory.Browser.ParseTreeRewriter class <category>instance creation</category>
removeTemporaryNamed: aName | rewriteRule | rewriteRule := self new. rewriteRule replace: '| `@temps1 ' , aName , ' `@temps2 | ``@.Statements' with: '| `@temps1 `@temps2 | ``@.Statements'. ^rewriteRule
rename: varName to: newVarName | rewriteRule | rewriteRule := self new. rewriteRule replace: varName with: newVarName; replaceArgument: varName with: newVarName. ^rewriteRule
rename: varName to: newVarName handler: aBlock "Rename varName to newVarName, evaluating aBlock if there is a temporary variable with the same name as newVarName. This does not change temporary variables with varName." | rewriteRule | rewriteRule := self new. rewriteRule replace: varName with: newVarName; replaceArgument: newVarName withValueFrom: [:aNode | aBlock value. aNode]. ^rewriteRule
replace: code with: newCode method: aBoolean | rewriteRule | rewriteRule := self new. aBoolean ifTrue: [rewriteRule replaceMethod: code with: newCode] ifFalse: [rewriteRule replace: code with: newCode]. ^rewriteRule
replaceLiteral: literal with: newLiteral | rewriteRule | rewriteRule := self new. rewriteRule replaceTree: (RBLiteralNode value: literal) withTree: (RBLiteralNode value: newLiteral). ^rewriteRule
variable: aVarName getter: getMethod setter: setMethod | rewriteRule | rewriteRule := self new. rewriteRule replace: aVarName , ' := ``@object' with: 'self ' , setMethod , ' ``@object'; replace: aVarName with: 'self ' , getMethod. ^rewriteRule
</methods> <methods> Refactory.Browser.ParseTreeRewriter class <category>accessing</category>
replace: code with: newCode in: aParseTree ^(self replace: code with: newCode method: false) executeTree: aParseTree; tree
replace: code with: newCode in: aParseTree onInterval: anInterval | rewriteRule | rewriteRule := self new. ^rewriteRule replace: code with: newCode when: [:aNode | aNode intersectsInterval: anInterval]; executeTree: aParseTree; tree
replaceStatements: code with: newCode in: aParseTree onInterval: anInterval | tree replaceStmt | tree := self buildTree: code method: false. tree isSequence ifFalse: [tree := RBSequenceNode statements: (Array with: tree)]. tree temporaries: (Array with: (RBPatternVariableNode named: '`@temps')). tree addNodeFirst: (RBPatternVariableNode named: '`@.S1'). tree lastIsReturn ifTrue: [replaceStmt := '| `@temps | `@.S1. ^' , newCode] ifFalse: [tree addNode: (RBPatternVariableNode named: '`@.S2'). replaceStmt := '| `@temps | `@.S1. ' , newCode , '. `@.S2']. ^self replace: tree formattedCode with: replaceStmt in: aParseTree onInterval: anInterval
</methods> <methods> Refactory.Browser.RBNumberLiteralToken <category>accessing</category>
source ^source
</methods> <methods> Refactory.Browser.RBNumberLiteralToken <category>initialize-release</category>
source: aString source := aString
</methods> <methods> Refactory.Browser.RBNumberLiteralToken <category>printing</category>
storeOn: aStream aStream nextPutAll: source
</methods> <methods> Refactory.Browser.RBNumberLiteralToken class <category>instance creation</category>
value: aNumber start: anInteger stop: stopInteger source: sourceString ^(self value: aNumber start: anInteger stop: stopInteger) source: sourceString; yourself
</methods> <methods> Refactory.Browser.RBCascadeNode <category>comparing</category>
= anObject self == anObject ifTrue: [^true]. self class = anObject class ifFalse: [^false]. self messages size = anObject messages size ifFalse: [^false]. 1 to: self messages size do: [:i | (self messages at: i) = (anObject messages at: i) ifFalse: [^false]]. ^true
equalTo: anObject withMapping: aDictionary self class = anObject class ifFalse: [^false]. self messages size == anObject messages size ifFalse: [^false]. 1 to: self messages size do: [:i | ((self messages at: i) equalTo: (anObject messages at: i) withMapping: aDictionary) ifFalse: [^false]]. ^true
hash ^self messages hash
</methods> <methods> Refactory.Browser.RBCascadeNode <category>visitor</category>
acceptVisitor: aProgramNodeVisitor ^aProgramNodeVisitor acceptCascadeNode: self
</methods> <methods> Refactory.Browser.RBCascadeNode <category>querying</category>
bestNodeFor: anInterval | selectedChildren | (self intersectsInterval: anInterval) ifFalse: [^nil]. (self containedBy: anInterval) ifTrue: [^self]. messages reverseDo: [:each | (each containedBy: anInterval) ifTrue: [^each]]. selectedChildren := (messages collect: [:each | each bestNodeFor: anInterval]) reject: [:each | each isNil]. ^selectedChildren detect: [:each | true] ifNone: [nil]
whichNodeIsContainedBy: anInterval | selectedChildren | (self intersectsInterval: anInterval) ifFalse: [^nil]. (self containedBy: anInterval) ifTrue: [^self]. messages reverseDo: [:each | (each containedBy: anInterval) ifTrue: [^each]]. selectedChildren := (messages collect: [:each | each whichNodeIsContainedBy: anInterval]) reject: [:each | each isNil]. ^selectedChildren detect: [:each | true] ifNone: [nil]
</methods> <methods> Refactory.Browser.RBCascadeNode <category>accessing</category>
children ^self messages
messages ^messages
messages: messageNodeCollection messages := messageNodeCollection. messages do: [:each | each parent: self]
precedence ^4
receiver ^self messages first receiver
startWithoutParentheses ^messages first start
statementComments | statementComments | statementComments := OrderedCollection withAll: self comments. statementComments addAll: messages first receiver statementComments. messages do: [:each | each arguments do: [:arg | statementComments addAll: arg statementComments]]. ^statementComments asSortedCollection: [:a :b | a first < b first]
stopWithoutParentheses ^messages last stop
</methods> <methods> Refactory.Browser.RBCascadeNode <category>testing</category>
directlyUses: aNode ^messages last = aNode and: [self isDirectlyUsed]
isCascade ^true
needsParenthesis ^parent isNil ifTrue: [false] ifFalse: [self precedence > parent precedence]
uses: aNode ^messages last = aNode and: [self isUsed]
</methods> <methods> Refactory.Browser.RBCascadeNode <category>initialize-release</category>
messages: messageNodes semicolons: integerCollection self messages: messageNodes. semicolons := integerCollection
</methods> <methods> Refactory.Browser.RBCascadeNode <category>copying</category>
postCopy super postCopy. messages := messages collect: [:each | each copy]
</methods> <methods> Refactory.Browser.RBCascadeNode <category>replacing</category>
replaceNode: aNode withNode: anotherNode self messages: (messages collect: [:each | each == aNode ifTrue: [anotherNode] ifFalse: [each]])
</methods> <methods> Refactory.Browser.RBCascadeNode <category>matching</category>
copyInContext: aDictionary ^(self class new) messages: (self copyList: messages inContext: aDictionary); yourself
match: aNode inContext: aDictionary aNode class == self class ifFalse: [^false]. ^self matchList: messages against: aNode messages inContext: aDictionary
</methods> <methods> Refactory.Browser.RBCascadeNode class <category>instance creation</category>
messages: messageNodes ^self new messages: messageNodes
messages: messageNodes semicolons: integerCollection ^self new messages: messageNodes semicolons: integerCollection
</methods> <methods> Refactory.Browser.RBStringReplacement <category>accessing</category>
startPosition ^startPosition
stopPosition ^stopPosition
string ^string
</methods> <methods> Refactory.Browser.RBStringReplacement <category>initialize-release</category>
startPosition: anInteger startPosition := anInteger
stopPosition: anInteger stopPosition := anInteger
string: aString string := aString
</methods> <methods> Refactory.Browser.RBStringReplacement class <category>instance creation</category>
replaceFrom: startInteger to: stopInteger with: aString ^(self new) startPosition: startInteger; stopPosition: stopInteger; string: aString; yourself
</methods> <methods> Refactory.Browser.RBParser <category>private</category>
addCommentsTo: aNode aNode comments: aNode comments , comments. comments := OrderedCollection new
nextToken ^nextToken isNil ifTrue: [nextToken := scanner next] ifFalse: [nextToken]
patchLiteralArrayDottedNameToken "VW allows for non-standard literals such as #(Foo.bar) #('Foo.bar')" (currentToken isIdentifier and: [currentToken value includes: $.]) ifTrue: [currentToken := RBLiteralToken value: currentToken value start: currentToken start stop: currentToken stop. ^true]. ^false
patchLiteralArrayEmbeddedAssignmentToken "VW allows for non-standard literals such as #(a:= :=) which is equivalent to #(#a: #= #':' #=)" (currentToken isIdentifier and: [self nextToken isAssignment and: [currentToken stop + 1 = self nextToken start]]) ifTrue: [currentToken := RBLiteralToken value: (currentToken value , ':') asSymbol start: currentToken start stop: self nextToken start. nextToken := RBLiteralToken value: #= start: nextToken stop stop: nextToken stop. ^true]. currentToken isAssignment ifTrue: [currentToken := RBLiteralToken value: #':' start: currentToken start stop: currentToken start. nextToken := RBLiteralToken value: #= start: currentToken stop stop: currentToken stop. ^true]. ^false
patchLiteralArraySpecialToken "VW allows for non-standard literals such as #(: ;|{},) which is equivalent to #(#':', .... #',')" currentToken isSpecial ifTrue: [currentToken := RBLiteralToken value: (String with: currentToken value) asSymbol start: currentToken start stop: currentToken stop. ^true]. ^false
patchLiteralArraySymbolToken "this is the standard expansion. e.g: #(foo) -> #(#foo)" (currentToken isIdentifier or: [currentToken isBinary or: [currentToken isKeyword]]) ifFalse: [^false]. currentToken := RBLiteralToken value: currentToken value asSymbol start: currentToken start stop: currentToken stop. ^true
patchLiteralArrayToken (self patchLiteralArrayEmbeddedAssignmentToken or: [self patchLiteralArraySpecialToken or: [self patchLiteralArrayDottedNameToken ifFalse: [self patchLiteralArraySymbolToken]]]) ifFalse: [^self parserError: #InvalidToken << #browser >> 'Invalid token']
patchLiteralMessage currentToken value == true ifTrue: [^currentToken := RBIdentifierToken value: 'true' start: currentToken start]. currentToken value == false ifTrue: [^currentToken := RBIdentifierToken value: 'false' start: currentToken start]. currentToken value == nil ifTrue: [^currentToken := RBIdentifierToken value: 'nil' start: currentToken start]
patchNegativeLiteral "Handle the special negative number case for binary message sends." (currentToken value isKindOf: Number) ifFalse: [^self]. currentToken value <= 0 ifFalse: [^self]. currentToken value = 0 ifTrue: [(source notNil and: [source notEmpty and: [(source at: (currentToken start min: source size)) == $-]]) ifFalse: [^self]]. nextToken := currentToken. currentToken := RBBinarySelectorToken value: #- start: nextToken start. nextToken value: nextToken value negated. (nextToken isKindOf: RBNumberLiteralToken) ifTrue: [nextToken source: (nextToken source copyFrom: 2 to: nextToken source size)]. nextToken start: nextToken start + 1
reposition: aNewPosition "Meant for the case where we use another parser to consume subtexts, state needs to be cleared when we do this." scanner sourceStream position: aNewPosition. scanner step; stripSeparators. nextToken := currentToken := nil. self step
step (currentToken notNil and: [currentToken comments notNil]) ifTrue: [comments addAll: currentToken comments]. nextToken notNil ifTrue: [currentToken := nextToken. nextToken := nil] ifFalse: [currentToken := scanner next]
</methods> <methods> Refactory.Browser.RBParser <category>private-classes</category>
assignmentNodeClass ^RBAssignmentNode
blockNodeClass ^RBBlockNode
cascadeNodeClass ^RBCascadeNode
literalArrayNodeClass ^RBLiteralArrayNode
messageNodeClass ^RBMessageNode
methodNodeClass ^RBMethodNode
returnNodeClass ^RBReturnNode
sequenceNodeClass ^RBSequenceNode
variableNodeClass ^RBVariableNode
</methods> <methods> Refactory.Browser.RBParser <category>testing</category>
atEnd ^currentToken class == RBToken
canHaveStatementsAfterReturn ^false
</methods> <methods> Refactory.Browser.RBParser <category>accessing</category>
errorBlock: aBlock errorBlock := aBlock. scanner notNil ifTrue: [scanner errorBlock: aBlock]
initializeParserWith: aString source := aString. self scanner: (self scannerClass on: (ReadStream on: aString) errorBlock: self errorBlock)
parseExpression: aString | node | node := self parseStatements: false. (RBMethodNode selector: #noMethod body: node) source: aString. "Make the sequence node have a method node as its parent" self atEnd ifFalse: [self parserError: (#UnknownInputAtEnd << #browser >> 'Unknown input at end')]. ^node
parseMethod: aString | node | node := self parseMethod. self atEnd ifFalse: [self parserError: (#UnknownInputAtEnd << #browser >> 'Unknown input at end')]. node source: aString. ^node
scannerClass ^RBScanner
</methods> <methods> Refactory.Browser.RBParser <category>error handling</category>
errorBlock ^errorBlock isNil ifTrue: [[:message :position | ]] ifFalse: [errorBlock]
errorPosition ^currentToken start
parserError: aString "Evaluate the block. If it returns raise an error" self errorBlock value: aString value: self errorPosition. self error: aString
</methods> <methods> Refactory.Browser.RBParser <category>initialize-release</category>
scanner: aScanner scanner := aScanner. comments := OrderedCollection new. self step
</methods> <methods> Refactory.Browser.RBParser <category>private-parsing</category>
parseArgs | args | args := OrderedCollection new. [currentToken isIdentifier] whileTrue: [args add: self parseVariableNode]. ^args
parseAssignment "Need one token lookahead to see if we have a ':='. This method could make it possible to assign the literals true, false and nil." | node position | (currentToken isIdentifier and: [self nextToken isAssignment]) ifFalse: [^self parseCascadeMessage]. node := self parseVariableNode. position := currentToken start. self step. ^self assignmentNodeClass variable: node value: self parseAssignment position: position
parseBinaryMessage | node | node := self parseUnaryMessage. [currentToken isLiteralToken ifTrue: [self patchNegativeLiteral]. currentToken isBinary] whileTrue: [node := self parseBinaryMessageWith: node]. ^node
parseBinaryMessageWith: aNode | binaryToken | binaryToken := currentToken. self step. ^self messageNodeClass receiver: aNode selectorParts: (Array with: binaryToken) arguments: (Array with: self parseUnaryMessage)
parseBinaryPattern | binaryToken node args | currentToken isBinary ifFalse: [self parserError: (#MessagePatternExpected << #browser >> 'Message pattern expected')]. binaryToken := currentToken. self step. args := Array with: self parseVariableNode. node := self methodNodeClass selectorParts: (Array with: binaryToken) arguments: args. node comments: node comments , args last comments. args last comments: nil. ^node
parseBlock | position node | position := currentToken start. self step. node := self blockNodeClass new. self parseBlockArgsInto: node. node left: position. node body: (self parseStatements: false). (currentToken isSpecial and: [currentToken value == $]]) ifFalse: [self parserError: (#CloseBracketExpected << #browser >> ''']'' expected')]. node right: currentToken start. self step. ^node
parseBlockArgsInto: node | verticalBar args colons | args := OrderedCollection new: 2. colons := OrderedCollection new: 2. verticalBar := false. [currentToken isSpecial and: [currentToken value == $:]] whileTrue: [colons add: currentToken start. self step. ":" verticalBar := true. args add: self parseVariableNode]. verticalBar ifTrue: [currentToken isBinary ifTrue: [node bar: currentToken start. currentToken value == #| ifTrue: [self step] ifFalse: [currentToken value == #'||' ifTrue: ["Hack the current token to be the start of temps bar" currentToken value: #|; start: currentToken start + 1] ifFalse: [self parserError: (#BarExpected << #browser >> '''|'' expected')]]] ifFalse: [(currentToken isSpecial and: [currentToken value == $]]) ifFalse: [self parserError: (#BarExpected << #browser >> '''|'' expected')]]]. node arguments: args; colons: colons. ^node
parseCascadeMessage | node receiver messages semicolons | node := self parseKeywordMessage. (currentToken isSpecial and: [currentToken value == $; and: [node isMessage]]) ifFalse: [^node]. receiver := node receiver. messages := OrderedCollection new: 3. semicolons := OrderedCollection new: 3. messages add: node. [currentToken isSpecial and: [currentToken value == $;]] whileTrue: [semicolons add: currentToken start. self step. messages add: (currentToken isIdentifier ifTrue: [self parseUnaryMessageWith: receiver] ifFalse: [currentToken isKeyword ifTrue: [self parseKeywordMessageWith: receiver] ifFalse: [| temp | currentToken isLiteralToken ifTrue: [self patchNegativeLiteral]. currentToken isBinary ifFalse: [self parserError: (#MessageExpected << #browser >> 'Message expected')]. temp := self parseBinaryMessageWith: receiver. temp == receiver ifTrue: [self parserError: (#MessageExpected << #browser >> 'Message expected')]. temp]])]. ^self cascadeNodeClass messages: messages semicolons: semicolons
parseCDeclarationTag "The idea here is to use the CPreprocessor/CDeclarationParser processor to simply consume the characters on the source stream, we know at this point that we've seen a <C: pattern. We end up having to reach around the parser's normal mode of operations. For one, we have to transform the error mechanism into one we like, and then we have to inline our version so we can use a different source position. We also have to 'reposition:' ourselves which basically means jumping ahead to where the CParsers left off and resyncing the scan from that point." | subStream selectorToken start stop | selectorToken := currentToken. subStream := source readStream. start := selectorToken stop + 1. [(source at: start) isSeparator] whileTrue: [start := start + 1]. subStream position: start - 1. [(#{CPreprocessor} value parseWithNoPreprocess: subStream as: #defineOrSingleDeclaration declarations: ExternalDictionary new requestor: (SignallingCompilerErrorHandler handler: SilentCompilerErrorHandler new)) lastDefine ifNil: [subStream position: start - 1. #{CDeclarationParser} value parseWithNoPreprocess: subStream as: #defineOrSingleDeclaration declarations: ExternalDictionary new requestor: (SignallingCompilerErrorHandler handler: SilentCompilerErrorHandler new)]] on: CompilerError do: [:ex | self errorBlock value: ex parameter value: ex sourcePosition. self error: ex parameter]. stop := subStream position - 1. [(source at: stop) isSeparator] whileTrue: [stop := stop - 1]. self reposition: stop. ^RBCDeclarationNode selectorParts: (Array with: selectorToken) arguments: (Array with: (RBLiteralNode literalToken: (RBLiteralToken value: (source copyFrom: start to: stop) asString start: start stop: stop)))
parseKeywordMessage ^self parseKeywordMessageWith: self parseBinaryMessage
parseKeywordMessageWith: node | args isKeyword keywords | args := OrderedCollection new: 3. keywords := OrderedCollection new: 3. isKeyword := false. [currentToken isKeyword] whileTrue: [keywords add: currentToken. self step. args add: self parseBinaryMessage. isKeyword := true]. ^isKeyword ifTrue: [self messageNodeClass receiver: node selectorParts: keywords arguments: args] ifFalse: [node]
parseKeywordPattern | keywords args node | keywords := OrderedCollection new: 2. args := OrderedCollection new: 2. [currentToken isKeyword] whileTrue: [keywords add: currentToken. self step. args add: self parseVariableNode]. node := self methodNodeClass selectorParts: keywords arguments: args. node comments: (node comments, args last comments). args last comments: nil. ^node
parseKeywordTag | selectorParts arguments | selectorParts := OrderedCollection new. arguments := OrderedCollection new. [currentToken isKeyword] whileTrue: [| literalNode | selectorParts addLast: currentToken. self step. self patchLiteralArraySymbolToken. literalNode := self parsePrimitiveObject. literalNode isLiteralNode ifFalse: [self parserError: #TagLiteralExpected << #browser >> 'Literal constant expected']. arguments addLast: literalNode]. ^RBTagNode selectorParts: selectorParts arguments: arguments
parseLiteralArray | stream start stop | start := currentToken start. stream := WriteStream on: (Array new: 5). self step. [self atEnd or: [currentToken isSpecial and: [currentToken value = $)]]] whileFalse: [stream nextPut: self parseLiteralArrayObject]. (currentToken isSpecial and: [currentToken value == $)]) ifFalse: [self parserError: (#CloseParenExpected << #browser >> ''')'' expected')]. stop := currentToken stop. self step. ^self literalArrayNodeClass startPosition: start contents: stream contents stopPosition: stop isByteArray: false
parseLiteralArrayObject currentToken isSpecial ifTrue: [currentToken value == $( ifTrue: [^self parseLiteralArray]. currentToken value == $[ ifTrue: [^self parseLiteralByteArray]]. currentToken isLiteralArrayToken ifTrue: [^currentToken isForByteArray ifTrue: [self parseLiteralByteArray] ifFalse: [self parseLiteralArray]]. currentToken isLiteralToken ifFalse: [self patchLiteralArrayToken]. ^self parsePrimitiveLiteral
parseLiteralByteArray | stream start stop | start := currentToken start. stream := WriteStream on: (Array new: 5). self step. [self atEnd or: [currentToken isSpecial and: [currentToken value = $]]]] whileFalse: [stream nextPut: self parseLiteralByteArrayObject]. (currentToken isSpecial and: [currentToken value == $]]) ifFalse: [self parserError: (#CloseBracketExpected << #browser >> ''']'' expected')]. stop := currentToken stop. self step. ^self literalArrayNodeClass startPosition: start contents: stream contents stopPosition: stop isByteArray: true
parseLiteralByteArrayObject (currentToken isLiteralToken and: [currentToken value isInteger and: [currentToken value between: 0 and: 255]]) ifFalse: [self parserError: (#Expecting8bitInteger << #browser >> 'Expecting 8-bit integer')]. ^self parsePrimitiveLiteral
parseMessagePattern currentToken isLiteralToken ifTrue: [self patchLiteralMessage]. ^currentToken isIdentifier ifTrue: [self parseUnaryPattern] ifFalse: [currentToken isKeyword ifTrue: [self parseKeywordPattern] ifFalse: [self parseBinaryPattern]]
parseMethod | methodNode | methodNode := self parseMessagePattern. methodNode tags: self parseTags. self addCommentsTo: methodNode. methodNode body: (self parseStatements: true). ^methodNode
parseParenthesizedExpression | leftParen node | leftParen := currentToken start. self step. node := self parseAssignment. ^(currentToken isSpecial and: [currentToken value == $)]) ifTrue: [node addParenthesis: (leftParen to: currentToken start). self step. node] ifFalse: [self parserError: (#CloseParenExpected << #browser >> ''')'' expected')]
parsePrimitiveIdentifier | token node | token := currentToken. self step. node := self variableNodeClass identifierToken: token. self addCommentsTo: node. ^node
parsePrimitiveLiteral | token | token := currentToken. self step. ^RBLiteralNode literalToken: token
parsePrimitiveObject currentToken isIdentifier ifTrue: [^self parsePrimitiveIdentifier]. (currentToken isLiteralToken and: [currentToken isMultiKeyword not]) ifTrue: [^self parsePrimitiveLiteral]. currentToken isLiteralArrayToken ifTrue: [^currentToken isForByteArray ifTrue: [self parseLiteralByteArray] ifFalse: [self parseLiteralArray]]. currentToken isSpecial ifTrue: [currentToken value == $[ ifTrue: [^self parseBlock]. currentToken value == $( ifTrue: [^self parseParenthesizedExpression]]. self parserError: #VariableExpected << #browser >> 'Variable expected'
parseStatementListInto: sequenceNode | statements return periods returnPosition node | return := false. statements := OrderedCollection new. periods := OrderedCollection new. self addCommentsTo: sequenceNode. "tagBoolean ifTrue: [self parseResourceTag]." [self atEnd or: [currentToken isSpecial and: ['])}' includes: currentToken value]]] whileFalse: [return ifTrue: [self parserError: #EndOfStmtList << #browser >> 'End of statement list encountered']. (currentToken isSpecial and: [currentToken value == $^]) ifTrue: [returnPosition := currentToken start. self step. node := self returnNodeClass return: returnPosition value: self parseAssignment. statements add: node. return := self canHaveStatementsAfterReturn not] ifFalse: [node := self parseAssignment. statements add: node]. (currentToken isSpecial and: [currentToken value == $.]) ifTrue: [periods add: currentToken start. self step. self addCommentsTo: node] ifFalse: [return := true]]. statements notEmpty ifTrue: [self addCommentsTo: statements last]. sequenceNode statements: statements; periods: periods. ^sequenceNode
parseStatements: tagBoolean | args leftBar rightBar | args := #(). leftBar := rightBar := nil. currentToken isBinary ifTrue: [currentToken value == #| ifTrue: [leftBar := currentToken start. self step. args := self parseArgs. (currentToken isBinary and: [currentToken value = #|]) ifFalse: [self parserError: #BarExpected << #browser >> '''|'' expected']. rightBar := currentToken start. self step] ifFalse: [currentToken value == #'||' ifTrue: [rightBar := (leftBar := currentToken start) + 1. self step]]]. ^self parseStatementListInto: (self sequenceNodeClass leftBar: leftBar temporaries: args rightBar: rightBar)
parseTag | start tagNode | start := currentToken start. self step. start := currentToken start - 1. (currentToken isIdentifier or: [currentToken isKeyword]) ifFalse: [self parserError: #TagTokenExpected << #browser >> 'Unary or keword expected']. tagNode := currentToken isIdentifier ifTrue: [self parseUnaryTag] ifFalse: [(currentToken value = 'C:' and: [#{CPreprocessor} isDefined]) ifTrue: [self parseCDeclarationTag] ifFalse: [self parseKeywordTag]]. (currentToken isBinary and: [currentToken value == #>]) ifFalse: [self parserError: #TagCloseExpected << #browser >> 'expected >']. tagNode brackets: (start to: currentToken start). self step. ^tagNode
parseTags | ws | (currentToken isBinary and: [currentToken value == #<]) ifFalse: [^nil]. ws := (Array new: 1) writeStream. [currentToken isBinary and: [currentToken value == #<]] whileTrue: [ws nextPut: self parseTag]. ^ws contents
parseUnaryMessage | node | node := self parsePrimitiveObject. self addCommentsTo: node. [currentToken isLiteralToken ifTrue: [self patchLiteralMessage]. currentToken isIdentifier] whileTrue: [node := self parseUnaryMessageWith: node]. self addCommentsTo: node. ^node
parseUnaryMessageWith: aNode | selector | selector := currentToken. self step. ^self messageNodeClass receiver: aNode selectorParts: (Array with: selector) arguments: #()
parseUnaryPattern | selector | selector := currentToken. self step. ^self methodNodeClass selectorParts: (Array with: selector) arguments: #()
parseUnaryTag | tagNode | tagNode := RBTagNode selectorParts: (Array with: currentToken) arguments: #(). self step. ^tagNode
parseVariableNode currentToken isIdentifier ifFalse: [self parserError: (#VariableNameExpected << #browser >> 'Variable name expected')]. ^self parsePrimitiveIdentifier
</methods> <methods> Refactory.Browser.RBParser class <category>accessing</category>
parseExpression: aString ^self parseExpression: aString onError: nil
parseExpression: aString onError: aBlock | node parser | parser := self new. parser errorBlock: aBlock. parser initializeParserWith: aString. node := parser parseExpression: aString. ^(node statements size == 1 and: [node temporaries isEmpty]) ifTrue: [node statements first] ifFalse: [node]
parseMethod: aString ^self parseMethod: aString onError: nil
parseMethod: aString onError: aBlock "Error block takes two arguments: 1) the error string describing the parser error 2) the position the error took place at." | parser | parser := self new. parser errorBlock: aBlock. parser initializeParserWith: aString. ^parser parseMethod: aString
parseRewriteExpression: aString ^self parseRewriteExpression: aString onError: nil
parseRewriteExpression: aString onError: aBlock ^RBPatternParser parseExpression: aString onError: aBlock
parseRewriteMethod: aString ^self parseRewriteMethod: aString onError: nil
parseRewriteMethod: aString onError: aBlock ^RBPatternParser parseMethod: aString onError: aBlock
</methods> <methods> Refactory.Browser.RBParser class <category>parsing</category>
parseMethodPattern: aString | parser | parser := self new. parser errorBlock: [:error :position | ^nil]. parser initializeParserWith: aString. ^parser parseMessagePattern selector
</methods> <methods> Refactory.Browser.RBPatternParser <category>private-classes</category>
messageNodeClass ^RBPatternMessageNode
methodNodeClass ^RBPatternMethodNode
variableNodeClass ^RBPatternVariableNode
</methods> <methods> Refactory.Browser.RBPatternParser <category>private-parsing</category>
parseLiteralByteArrayObject | node | (currentToken isIdentifier and: [currentToken isPatternVariable]) ifTrue: [node := self variableNodeClass identifierToken: currentToken. node isLiteralNode ifTrue: [self step. ^node]]. ^super parseLiteralByteArrayObject
parsePatternBlock: aClass | position node | position := currentToken start. self step. node := self parseBlockArgsInto: aClass new. node left: position. node body: (self parseStatements: false). (currentToken isSpecial and: [currentToken value == $}]) ifFalse: [self parserError: (#CloseBraceExpected << #browser >> '} expected')]. node right: currentToken start. self step. ^node
parsePrimitiveLiteral | node | (currentToken isIdentifier and: [currentToken isPatternVariable]) ifTrue: [node := self variableNodeClass identifierToken: currentToken. node isLiteralNode ifTrue: [self step. ^node]. currentToken := RBLiteralToken value: currentToken value asSymbol start: currentToken start stop: currentToken stop]. ^super parsePrimitiveLiteral
parsePrimitiveObject currentToken isPatternBlock ifTrue: [^self parsePatternBlock: RBPatternBlockNode]. ^super parsePrimitiveObject
parseUnaryMessage | node | node := self parsePrimitiveObject. self addCommentsTo: node. [currentToken isLiteralToken ifTrue: [self patchLiteralMessage]. currentToken isPatternBlock ifTrue: [node := (self parsePatternBlock: RBPatternWrapperBlockNode) wrappedNode: node; yourself]. currentToken isIdentifier] whileTrue: [node := self parseUnaryMessageWith: node]. self addCommentsTo: node. ^node
</methods> <methods> Refactory.Browser.RBPatternParser <category>accessing</category>
scannerClass ^RBPatternScanner
</methods> <methods> Refactory.Browser.RBPatternParser <category>private</category>
patchLiteralArrayToken (currentToken isIdentifier and: [currentToken isPatternVariable]) ifTrue: [^self]. super patchLiteralArrayToken
</methods> <methods> Refactory.Browser.RBReadBeforeWrittenTester <category>visitor-double dispatching</category>
acceptAssignmentNode: anAssignmentNode self visitNode: anAssignmentNode value. self variableWritten: anAssignmentNode
acceptBlockNode: aBlockNode self processBlock: aBlockNode
acceptMessageNode: aMessageNode ((#(#whileTrue: #whileFalse: #whileTrue #whileFalse) includes: aMessageNode selector) and: [aMessageNode receiver isBlock]) ifTrue: [self executeTree: aMessageNode receiver body] ifFalse: [(aMessageNode isCascaded not or: [aMessageNode isFirstCascaded]) ifTrue: [self visitNode: aMessageNode receiver]]. ((#(#ifTrue:ifFalse: #ifFalse:ifTrue:) includes: aMessageNode selector) and: [aMessageNode arguments allSatisfy: [:each | each isBlock]]) ifTrue: [^self processIfTrueIfFalse: aMessageNode]. aMessageNode arguments do: [:each | self visitNode: each]
acceptSequenceNode: aSequenceNode self processStatementNode: aSequenceNode
acceptVariableNode: aVariableNode self variableRead: aVariableNode
</methods> <methods> Refactory.Browser.RBReadBeforeWrittenTester <category>initialize-release</category>
checkNewTemps: aBoolean checkNewTemps := aBoolean
initialize super initialize. scopeStack := OrderedCollection with: Dictionary new. read := Set new. checkNewTemps := true
initializeVars: varNames varNames do: [:each | self currentScope at: each put: nil]
</methods> <methods> Refactory.Browser.RBReadBeforeWrittenTester <category>private</category>
copyDictionary: aDictionary "We could send aDictionary the copy message, but that doesn't copy the associations." | newDictionary | newDictionary := Dictionary new: aDictionary size. aDictionary keysAndValuesDo: [:key :value | newDictionary at: key put: value]. ^newDictionary
createScope scopeStack add: (self copyDictionary: scopeStack last)
currentScope ^scopeStack last
processBlock: aNode | newScope | self createScope. self executeTree: aNode body. newScope := self removeScope. newScope keysAndValuesDo: [:key :value | (value == true and: [(self currentScope at: key) isNil]) ifTrue: [self currentScope at: key put: value]]
processIfTrueIfFalse: aNode | trueScope falseScope | self createScope. self executeTree: aNode arguments first body. trueScope := self removeScope. self createScope. self executeTree: aNode arguments last body. falseScope := self removeScope. self currentScope keysAndValuesDo: [:key :value | value isNil ifTrue: [(trueScope at: key) == (falseScope at: key) ifTrue: [self currentScope at: key put: (trueScope at: key)] ifFalse: [((trueScope at: key) == true or: [(falseScope at: key) == true]) ifTrue: [self currentScope at: key put: true]]]]
processStatementNode: aNode | temps | (checkNewTemps not or: [aNode temporaries isEmpty]) ifTrue: [aNode statements do: [:each | self executeTree: each]. ^self]. self createScope. temps := aNode temporaries collect: [:each | each name]. self initializeVars: temps. aNode statements do: [:each | self executeTree: each]. self removeScope keysAndValuesDo: [:key :value | (temps includes: key) ifTrue: [value == true ifTrue: [read add: key]] ifFalse: [(self currentScope at: key) isNil ifTrue: [self currentScope at: key put: value]]]
removeScope ^scopeStack removeLast
variableRead: aNode (self currentScope includesKey: aNode name) ifTrue: [(self currentScope at: aNode name) isNil ifTrue: [self currentScope at: aNode name put: true]]
variableWritten: aNode (self currentScope includesKey: aNode variable name) ifTrue: [(self currentScope at: aNode variable name) isNil ifTrue: [self currentScope at: aNode variable name put: false]]
</methods> <methods> Refactory.Browser.RBReadBeforeWrittenTester <category>accessing</category>
executeTree: aParseTree ^self visitNode: aParseTree
read self currentScope keysAndValuesDo: [:key :value | value == true ifTrue: [read add: key]]. ^read
</methods> <methods> Refactory.Browser.RBReadBeforeWrittenTester class <category>accessing</category>
isVariable: aString readBeforeWrittenIn: aBRProgramNode ^(self isVariable: aString writtenBeforeReadIn: aBRProgramNode) not
isVariable: aString writtenBeforeReadIn: aBRProgramNode ^(self readBeforeWritten: (Array with: aString) in: aBRProgramNode) isEmpty
readBeforeWritten: varNames in: aParseTree ^(self new) checkNewTemps: false; initializeVars: varNames; executeTree: aParseTree; read
variablesReadBeforeWrittenIn: aParseTree ^(self new) executeTree: aParseTree; read
</methods> <methods> Core.Behavior <category>RefactoringBrowser</category>
parseTreeFor: aSymbol ^Refactory.Browser.RBParser parseMethod: (self sourceCodeAt: aSymbol) onError: [:aString :pos | ^nil]
</methods> <initialize> Refactory.Browser.RBScanner </initialize> "Imported Classes:" self error: 'Attempting to file-in parcel imports. Choose terminate or close' <class> <name>Object</name> <environment>Core</environment> <super></super> <private>false</private> none <imports></imports> <category>Kernel-Objects</category> <attributes> <package>Kernel-Objects</package> </attributes> </class> <class> <name>KeyedCollection</name> <environment>Core</environment> <super>Core.Collection</super> <private>false</private> none <imports></imports> <category>Collections-Abstract</category> <attributes> <package>Collections-Abstract</package> </attributes> </class> <class> <name>Behavior</name> <environment>Core</environment> <super>Core.Object</super> <private>false</private> none superclass methodDict format subclasses <imports></imports> <category>Kernel-Classes</category> <attributes> <package>Kernel-Classes</package> </attributes> </class> <class> <name>Stream</name> <environment>Core</environment> <super>Core.Object</super> <private>false</private> none <imports> private IOConstants.* </imports> <category>Collections-Streams</category> <attributes> <package>Collections-Streams</package> </attributes> </class>