calabash-android 0.4.0.pre1 → 0.4.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/calabash-android-build.rb +6 -0
- data/bin/calabash-android-setup.rb +2 -3
- data/lib/calabash-android/canned_steps.md +1 -1
- data/lib/calabash-android/helpers.rb +35 -2
- data/lib/calabash-android/lib/TestServer.apk +0 -0
- data/lib/calabash-android/operations.rb +13 -6
- data/lib/calabash-android/version.rb +1 -1
- data/test-server/instrumentation-backend/.classpath +2 -1
- data/test-server/instrumentation-backend/antlr.sh +2 -0
- data/test-server/instrumentation-backend/antlr/UIQuery.g +70 -0
- data/test-server/instrumentation-backend/antlr/UIQuery.tokens +12 -0
- data/test-server/instrumentation-backend/build-libs/antlr-3.4-complete.jar +0 -0
- data/test-server/instrumentation-backend/build-libs/junit.jar +0 -0
- data/test-server/instrumentation-backend/build.xml +56 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRFileStream.java +78 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRInputStream.java +70 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRReaderStream.java +95 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ANTLRStringStream.java +230 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/BaseRecognizer.java +894 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/BitSet.java +325 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/BufferedTokenStream.java +272 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/CharStream.java +57 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/CharStreamState.java +45 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ClassicToken.java +141 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/CommonToken.java +191 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/CommonTokenStream.java +153 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/DFA.java +250 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/EarlyExitException.java +41 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/FailedPredicateException.java +54 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/IntStream.java +122 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/LegacyCommonTokenStream.java +394 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/Lexer.java +340 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedNotSetException.java +41 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedRangeException.java +45 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedSetException.java +44 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedTokenException.java +45 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MismatchedTreeNodeException.java +49 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/MissingTokenException.java +56 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/NoViableAltException.java +57 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/Parser.java +98 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/ParserRuleReturnScope.java +52 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/RecognitionException.java +180 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/RecognizerSharedState.java +144 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/RuleReturnScope.java +42 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/SerializedGrammar.java +204 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/Token.java +92 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/TokenRewriteStream.java +569 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/TokenSource.java +54 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/TokenStream.java +75 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/UnbufferedTokenStream.java +82 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/UnwantedTokenException.java +53 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/BlankDebugEventListener.java +77 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventHub.java +292 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventListener.java +323 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventRepeater.java +88 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugEventSocketProxy.java +358 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugParser.java +101 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTokenStream.java +156 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTreeAdaptor.java +250 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTreeNodeStream.java +155 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/DebugTreeParser.java +112 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/ParseTreeBuilder.java +109 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/Profiler.java +772 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/RemoteDebugEventSocketListener.java +541 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/TraceDebugEventListener.java +108 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/debug/Tracer.java +69 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/DoubleKeyMap.java +62 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/FastQueue.java +100 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/IntArray.java +87 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/LookaheadStream.java +161 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/misc/Stats.java +189 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/BaseTree.java +349 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/BaseTreeAdaptor.java +279 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/BufferedTreeNodeStream.java +489 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonErrorNode.java +108 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonTree.java +185 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonTreeAdaptor.java +168 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/CommonTreeNodeStream.java +171 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/ParseTree.java +119 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteCardinalityException.java +47 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteEarlyExitException.java +39 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteEmptyStreamException.java +35 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleElementStream.java +210 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleNodeStream.java +70 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleSubtreeStream.java +86 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/RewriteRuleTokenStream.java +76 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/Tree.java +127 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeAdaptor.java +263 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeFilter.java +135 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeIterator.java +132 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeNodeStream.java +106 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeParser.java +169 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreePatternLexer.java +135 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreePatternParser.java +154 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeRewriter.java +124 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeRuleReturnScope.java +41 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeVisitor.java +69 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeVisitorAction.java +47 -0
- data/test-server/instrumentation-backend/src/org/antlr/runtime/tree/TreeWizard.java +531 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/ClearAppData.java +22 -7
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/InstrumentationBackend.java +4 -4
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/Result.java +0 -1
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/HttpServer.java +161 -129
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/activity/SetActivityOrientation.java +5 -7
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/view/GetViewProperty.java +1 -7
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/Query.java +70 -61
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/UIQuery.tokens +12 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ViewMapper.java +63 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/antlr/UIQuery.tokens +10 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/antlr/UIQueryLexer.java +945 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/antlr/UIQueryParser.java +463 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/InvalidUIQueryException.java +10 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryAST.java +8 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryASTClassName.java +115 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryASTWith.java +157 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryDirection.java +5 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryEvaluator.java +205 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryUtils.java +135 -0
- data/test-server/instrumentation-backend/tests/sh/calaba/instrumentationbackend/query/tests/UIQueryTest.java +134 -0
- metadata +106 -3
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/activity/SetOrientation.java +0 -39
@@ -0,0 +1,92 @@
|
|
1
|
+
/*
|
2
|
+
[The "BSD license"]
|
3
|
+
Copyright (c) 2005-2009 Terence Parr
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
7
|
+
modification, are permitted provided that the following conditions
|
8
|
+
are met:
|
9
|
+
1. Redistributions of source code must retain the above copyright
|
10
|
+
notice, this list of conditions and the following disclaimer.
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright
|
12
|
+
notice, this list of conditions and the following disclaimer in the
|
13
|
+
documentation and/or other materials provided with the distribution.
|
14
|
+
3. The name of the author may not be used to endorse or promote products
|
15
|
+
derived from this software without specific prior written permission.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
18
|
+
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
19
|
+
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
20
|
+
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
21
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
22
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
23
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
24
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
25
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
26
|
+
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
*/
|
28
|
+
package org.antlr.runtime;
|
29
|
+
|
30
|
+
public interface Token {
|
31
|
+
public static final int EOR_TOKEN_TYPE = 1;
|
32
|
+
|
33
|
+
/** imaginary tree navigation type; traverse "get child" link */
|
34
|
+
public static final int DOWN = 2;
|
35
|
+
/** imaginary tree navigation type; finish with a child list */
|
36
|
+
public static final int UP = 3;
|
37
|
+
|
38
|
+
public static final int MIN_TOKEN_TYPE = UP+1;
|
39
|
+
|
40
|
+
public static final int EOF = CharStream.EOF;
|
41
|
+
// TODO: remove once we go ANTLR v3.3
|
42
|
+
public static final Token EOF_TOKEN = new CommonToken(EOF);
|
43
|
+
|
44
|
+
public static final int INVALID_TOKEN_TYPE = 0;
|
45
|
+
public static final Token INVALID_TOKEN = new CommonToken(INVALID_TOKEN_TYPE);
|
46
|
+
|
47
|
+
/** In an action, a lexer rule can set token to this SKIP_TOKEN and ANTLR
|
48
|
+
* will avoid creating a token for this symbol and try to fetch another.
|
49
|
+
*/
|
50
|
+
public static final Token SKIP_TOKEN = new CommonToken(INVALID_TOKEN_TYPE);
|
51
|
+
|
52
|
+
/** All tokens go to the parser (unless skip() is called in that rule)
|
53
|
+
* on a particular "channel". The parser tunes to a particular channel
|
54
|
+
* so that whitespace etc... can go to the parser on a "hidden" channel.
|
55
|
+
*/
|
56
|
+
public static final int DEFAULT_CHANNEL = 0;
|
57
|
+
|
58
|
+
/** Anything on different channel than DEFAULT_CHANNEL is not parsed
|
59
|
+
* by parser.
|
60
|
+
*/
|
61
|
+
public static final int HIDDEN_CHANNEL = 99;
|
62
|
+
|
63
|
+
/** Get the text of the token */
|
64
|
+
public String getText();
|
65
|
+
public void setText(String text);
|
66
|
+
|
67
|
+
public int getType();
|
68
|
+
public void setType(int ttype);
|
69
|
+
/** The line number on which this token was matched; line=1..n */
|
70
|
+
public int getLine();
|
71
|
+
public void setLine(int line);
|
72
|
+
|
73
|
+
/** The index of the first character relative to the beginning of the line 0..n-1 */
|
74
|
+
public int getCharPositionInLine();
|
75
|
+
public void setCharPositionInLine(int pos);
|
76
|
+
|
77
|
+
public int getChannel();
|
78
|
+
public void setChannel(int channel);
|
79
|
+
|
80
|
+
/** An index from 0..n-1 of the token object in the input stream.
|
81
|
+
* This must be valid in order to use the ANTLRWorks debugger.
|
82
|
+
*/
|
83
|
+
public int getTokenIndex();
|
84
|
+
public void setTokenIndex(int index);
|
85
|
+
|
86
|
+
/** From what character stream was this token created? You don't have to
|
87
|
+
* implement but it's nice to know where a Token comes from if you have
|
88
|
+
* include files etc... on the input.
|
89
|
+
*/
|
90
|
+
public CharStream getInputStream();
|
91
|
+
public void setInputStream(CharStream input);
|
92
|
+
}
|
@@ -0,0 +1,569 @@
|
|
1
|
+
/*
|
2
|
+
[The "BSD license"]
|
3
|
+
Copyright (c) 2005-2009 Terence Parr
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
7
|
+
modification, are permitted provided that the following conditions
|
8
|
+
are met:
|
9
|
+
1. Redistributions of source code must retain the above copyright
|
10
|
+
notice, this list of conditions and the following disclaimer.
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright
|
12
|
+
notice, this list of conditions and the following disclaimer in the
|
13
|
+
documentation and/or other materials provided with the distribution.
|
14
|
+
3. The name of the author may not be used to endorse or promote products
|
15
|
+
derived from this software without specific prior written permission.
|
16
|
+
|
17
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
18
|
+
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
19
|
+
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
20
|
+
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
21
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
22
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
23
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
24
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
25
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
26
|
+
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
*/
|
28
|
+
package org.antlr.runtime;
|
29
|
+
|
30
|
+
import java.util.*;
|
31
|
+
|
32
|
+
/** Useful for dumping out the input stream after doing some
|
33
|
+
* augmentation or other manipulations.
|
34
|
+
*
|
35
|
+
* You can insert stuff, replace, and delete chunks. Note that the
|
36
|
+
* operations are done lazily--only if you convert the buffer to a
|
37
|
+
* String. This is very efficient because you are not moving data around
|
38
|
+
* all the time. As the buffer of tokens is converted to strings, the
|
39
|
+
* toString() method(s) check to see if there is an operation at the
|
40
|
+
* current index. If so, the operation is done and then normal String
|
41
|
+
* rendering continues on the buffer. This is like having multiple Turing
|
42
|
+
* machine instruction streams (programs) operating on a single input tape. :)
|
43
|
+
*
|
44
|
+
* Since the operations are done lazily at toString-time, operations do not
|
45
|
+
* screw up the token index values. That is, an insert operation at token
|
46
|
+
* index i does not change the index values for tokens i+1..n-1.
|
47
|
+
*
|
48
|
+
* Because operations never actually alter the buffer, you may always get
|
49
|
+
* the original token stream back without undoing anything. Since
|
50
|
+
* the instructions are queued up, you can easily simulate transactions and
|
51
|
+
* roll back any changes if there is an error just by removing instructions.
|
52
|
+
* For example,
|
53
|
+
*
|
54
|
+
* CharStream input = new ANTLRFileStream("input");
|
55
|
+
* TLexer lex = new TLexer(input);
|
56
|
+
* TokenRewriteStream tokens = new TokenRewriteStream(lex);
|
57
|
+
* T parser = new T(tokens);
|
58
|
+
* parser.startRule();
|
59
|
+
*
|
60
|
+
* Then in the rules, you can execute
|
61
|
+
* Token t,u;
|
62
|
+
* ...
|
63
|
+
* input.insertAfter(t, "text to put after t");}
|
64
|
+
* input.insertAfter(u, "text after u");}
|
65
|
+
* System.out.println(tokens.toString());
|
66
|
+
*
|
67
|
+
* Actually, you have to cast the 'input' to a TokenRewriteStream. :(
|
68
|
+
*
|
69
|
+
* You can also have multiple "instruction streams" and get multiple
|
70
|
+
* rewrites from a single pass over the input. Just name the instruction
|
71
|
+
* streams and use that name again when printing the buffer. This could be
|
72
|
+
* useful for generating a C file and also its header file--all from the
|
73
|
+
* same buffer:
|
74
|
+
*
|
75
|
+
* tokens.insertAfter("pass1", t, "text to put after t");}
|
76
|
+
* tokens.insertAfter("pass2", u, "text after u");}
|
77
|
+
* System.out.println(tokens.toString("pass1"));
|
78
|
+
* System.out.println(tokens.toString("pass2"));
|
79
|
+
*
|
80
|
+
* If you don't use named rewrite streams, a "default" stream is used as
|
81
|
+
* the first example shows.
|
82
|
+
*/
|
83
|
+
public class TokenRewriteStream extends CommonTokenStream {
|
84
|
+
public static final String DEFAULT_PROGRAM_NAME = "default";
|
85
|
+
public static final int PROGRAM_INIT_SIZE = 100;
|
86
|
+
public static final int MIN_TOKEN_INDEX = 0;
|
87
|
+
|
88
|
+
// Define the rewrite operation hierarchy
|
89
|
+
|
90
|
+
class RewriteOperation {
|
91
|
+
/** What index into rewrites List are we? */
|
92
|
+
protected int instructionIndex;
|
93
|
+
/** Token buffer index. */
|
94
|
+
protected int index;
|
95
|
+
protected Object text;
|
96
|
+
protected RewriteOperation(int index, Object text) {
|
97
|
+
this.index = index;
|
98
|
+
this.text = text;
|
99
|
+
}
|
100
|
+
/** Execute the rewrite operation by possibly adding to the buffer.
|
101
|
+
* Return the index of the next token to operate on.
|
102
|
+
*/
|
103
|
+
public int execute(StringBuffer buf) {
|
104
|
+
return index;
|
105
|
+
}
|
106
|
+
public String toString() {
|
107
|
+
String opName = getClass().getName();
|
108
|
+
int $index = opName.indexOf('$');
|
109
|
+
opName = opName.substring($index+1, opName.length());
|
110
|
+
return "<"+opName+"@"+index+":\""+text+"\">";
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
class InsertBeforeOp extends RewriteOperation {
|
115
|
+
public InsertBeforeOp(int index, Object text) {
|
116
|
+
super(index,text);
|
117
|
+
}
|
118
|
+
public int execute(StringBuffer buf) {
|
119
|
+
buf.append(text);
|
120
|
+
if ( tokens.get(index).getType()!=Token.EOF ) buf.append(tokens.get(index).getText());
|
121
|
+
return index+1;
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
/** I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp
|
126
|
+
* instructions.
|
127
|
+
*/
|
128
|
+
class ReplaceOp extends RewriteOperation {
|
129
|
+
protected int lastIndex;
|
130
|
+
public ReplaceOp(int from, int to, Object text) {
|
131
|
+
super(from,text);
|
132
|
+
lastIndex = to;
|
133
|
+
}
|
134
|
+
public int execute(StringBuffer buf) {
|
135
|
+
if ( text!=null ) {
|
136
|
+
buf.append(text);
|
137
|
+
}
|
138
|
+
return lastIndex+1;
|
139
|
+
}
|
140
|
+
public String toString() {
|
141
|
+
return "<ReplaceOp@"+index+".."+lastIndex+":\""+text+"\">";
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
class DeleteOp extends ReplaceOp {
|
146
|
+
public DeleteOp(int from, int to) {
|
147
|
+
super(from, to, null);
|
148
|
+
}
|
149
|
+
public String toString() {
|
150
|
+
return "<DeleteOp@"+index+".."+lastIndex+">";
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
/** You may have multiple, named streams of rewrite operations.
|
155
|
+
* I'm calling these things "programs."
|
156
|
+
* Maps String (name) -> rewrite (List)
|
157
|
+
*/
|
158
|
+
protected Map programs = null;
|
159
|
+
|
160
|
+
/** Map String (program name) -> Integer index */
|
161
|
+
protected Map lastRewriteTokenIndexes = null;
|
162
|
+
|
163
|
+
public TokenRewriteStream() {
|
164
|
+
init();
|
165
|
+
}
|
166
|
+
|
167
|
+
protected void init() {
|
168
|
+
programs = new HashMap();
|
169
|
+
programs.put(DEFAULT_PROGRAM_NAME, new ArrayList(PROGRAM_INIT_SIZE));
|
170
|
+
lastRewriteTokenIndexes = new HashMap();
|
171
|
+
}
|
172
|
+
|
173
|
+
public TokenRewriteStream(TokenSource tokenSource) {
|
174
|
+
super(tokenSource);
|
175
|
+
init();
|
176
|
+
}
|
177
|
+
|
178
|
+
public TokenRewriteStream(TokenSource tokenSource, int channel) {
|
179
|
+
super(tokenSource, channel);
|
180
|
+
init();
|
181
|
+
}
|
182
|
+
|
183
|
+
public void rollback(int instructionIndex) {
|
184
|
+
rollback(DEFAULT_PROGRAM_NAME, instructionIndex);
|
185
|
+
}
|
186
|
+
|
187
|
+
/** Rollback the instruction stream for a program so that
|
188
|
+
* the indicated instruction (via instructionIndex) is no
|
189
|
+
* longer in the stream. UNTESTED!
|
190
|
+
*/
|
191
|
+
public void rollback(String programName, int instructionIndex) {
|
192
|
+
List is = (List)programs.get(programName);
|
193
|
+
if ( is!=null ) {
|
194
|
+
programs.put(programName, is.subList(MIN_TOKEN_INDEX,instructionIndex));
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
public void deleteProgram() {
|
199
|
+
deleteProgram(DEFAULT_PROGRAM_NAME);
|
200
|
+
}
|
201
|
+
|
202
|
+
/** Reset the program so that no instructions exist */
|
203
|
+
public void deleteProgram(String programName) {
|
204
|
+
rollback(programName, MIN_TOKEN_INDEX);
|
205
|
+
}
|
206
|
+
|
207
|
+
public void insertAfter(Token t, Object text) {
|
208
|
+
insertAfter(DEFAULT_PROGRAM_NAME, t, text);
|
209
|
+
}
|
210
|
+
|
211
|
+
public void insertAfter(int index, Object text) {
|
212
|
+
insertAfter(DEFAULT_PROGRAM_NAME, index, text);
|
213
|
+
}
|
214
|
+
|
215
|
+
public void insertAfter(String programName, Token t, Object text) {
|
216
|
+
insertAfter(programName,t.getTokenIndex(), text);
|
217
|
+
}
|
218
|
+
|
219
|
+
public void insertAfter(String programName, int index, Object text) {
|
220
|
+
// to insert after, just insert before next index (even if past end)
|
221
|
+
insertBefore(programName,index+1, text);
|
222
|
+
//addToSortedRewriteList(programName, new InsertAfterOp(index,text));
|
223
|
+
}
|
224
|
+
|
225
|
+
public void insertBefore(Token t, Object text) {
|
226
|
+
insertBefore(DEFAULT_PROGRAM_NAME, t, text);
|
227
|
+
}
|
228
|
+
|
229
|
+
public void insertBefore(int index, Object text) {
|
230
|
+
insertBefore(DEFAULT_PROGRAM_NAME, index, text);
|
231
|
+
}
|
232
|
+
|
233
|
+
public void insertBefore(String programName, Token t, Object text) {
|
234
|
+
insertBefore(programName, t.getTokenIndex(), text);
|
235
|
+
}
|
236
|
+
|
237
|
+
public void insertBefore(String programName, int index, Object text) {
|
238
|
+
//addToSortedRewriteList(programName, new InsertBeforeOp(index,text));
|
239
|
+
RewriteOperation op = new InsertBeforeOp(index,text);
|
240
|
+
List rewrites = getProgram(programName);
|
241
|
+
op.instructionIndex = rewrites.size();
|
242
|
+
rewrites.add(op);
|
243
|
+
}
|
244
|
+
|
245
|
+
public void replace(int index, Object text) {
|
246
|
+
replace(DEFAULT_PROGRAM_NAME, index, index, text);
|
247
|
+
}
|
248
|
+
|
249
|
+
public void replace(int from, int to, Object text) {
|
250
|
+
replace(DEFAULT_PROGRAM_NAME, from, to, text);
|
251
|
+
}
|
252
|
+
|
253
|
+
public void replace(Token indexT, Object text) {
|
254
|
+
replace(DEFAULT_PROGRAM_NAME, indexT, indexT, text);
|
255
|
+
}
|
256
|
+
|
257
|
+
public void replace(Token from, Token to, Object text) {
|
258
|
+
replace(DEFAULT_PROGRAM_NAME, from, to, text);
|
259
|
+
}
|
260
|
+
|
261
|
+
public void replace(String programName, int from, int to, Object text) {
|
262
|
+
if ( from > to || from<0 || to<0 || to >= tokens.size() ) {
|
263
|
+
throw new IllegalArgumentException("replace: range invalid: "+from+".."+to+"(size="+tokens.size()+")");
|
264
|
+
}
|
265
|
+
RewriteOperation op = new ReplaceOp(from, to, text);
|
266
|
+
List rewrites = getProgram(programName);
|
267
|
+
op.instructionIndex = rewrites.size();
|
268
|
+
rewrites.add(op);
|
269
|
+
}
|
270
|
+
|
271
|
+
public void replace(String programName, Token from, Token to, Object text) {
|
272
|
+
replace(programName,
|
273
|
+
from.getTokenIndex(),
|
274
|
+
to.getTokenIndex(),
|
275
|
+
text);
|
276
|
+
}
|
277
|
+
|
278
|
+
public void delete(int index) {
|
279
|
+
delete(DEFAULT_PROGRAM_NAME, index, index);
|
280
|
+
}
|
281
|
+
|
282
|
+
public void delete(int from, int to) {
|
283
|
+
delete(DEFAULT_PROGRAM_NAME, from, to);
|
284
|
+
}
|
285
|
+
|
286
|
+
public void delete(Token indexT) {
|
287
|
+
delete(DEFAULT_PROGRAM_NAME, indexT, indexT);
|
288
|
+
}
|
289
|
+
|
290
|
+
public void delete(Token from, Token to) {
|
291
|
+
delete(DEFAULT_PROGRAM_NAME, from, to);
|
292
|
+
}
|
293
|
+
|
294
|
+
public void delete(String programName, int from, int to) {
|
295
|
+
replace(programName,from,to,null);
|
296
|
+
}
|
297
|
+
|
298
|
+
public void delete(String programName, Token from, Token to) {
|
299
|
+
replace(programName,from,to,null);
|
300
|
+
}
|
301
|
+
|
302
|
+
public int getLastRewriteTokenIndex() {
|
303
|
+
return getLastRewriteTokenIndex(DEFAULT_PROGRAM_NAME);
|
304
|
+
}
|
305
|
+
|
306
|
+
protected int getLastRewriteTokenIndex(String programName) {
|
307
|
+
Integer I = (Integer)lastRewriteTokenIndexes.get(programName);
|
308
|
+
if ( I==null ) {
|
309
|
+
return -1;
|
310
|
+
}
|
311
|
+
return I.intValue();
|
312
|
+
}
|
313
|
+
|
314
|
+
protected void setLastRewriteTokenIndex(String programName, int i) {
|
315
|
+
lastRewriteTokenIndexes.put(programName, new Integer(i));
|
316
|
+
}
|
317
|
+
|
318
|
+
protected List getProgram(String name) {
|
319
|
+
List is = (List)programs.get(name);
|
320
|
+
if ( is==null ) {
|
321
|
+
is = initializeProgram(name);
|
322
|
+
}
|
323
|
+
return is;
|
324
|
+
}
|
325
|
+
|
326
|
+
private List initializeProgram(String name) {
|
327
|
+
List is = new ArrayList(PROGRAM_INIT_SIZE);
|
328
|
+
programs.put(name, is);
|
329
|
+
return is;
|
330
|
+
}
|
331
|
+
|
332
|
+
public String toOriginalString() {
|
333
|
+
fill();
|
334
|
+
return toOriginalString(MIN_TOKEN_INDEX, size()-1);
|
335
|
+
}
|
336
|
+
|
337
|
+
public String toOriginalString(int start, int end) {
|
338
|
+
StringBuffer buf = new StringBuffer();
|
339
|
+
for (int i=start; i>=MIN_TOKEN_INDEX && i<=end && i<tokens.size(); i++) {
|
340
|
+
if ( get(i).getType()!=Token.EOF ) buf.append(get(i).getText());
|
341
|
+
}
|
342
|
+
return buf.toString();
|
343
|
+
}
|
344
|
+
|
345
|
+
public String toString() {
|
346
|
+
fill();
|
347
|
+
return toString(MIN_TOKEN_INDEX, size()-1);
|
348
|
+
}
|
349
|
+
|
350
|
+
public String toString(String programName) {
|
351
|
+
fill();
|
352
|
+
return toString(programName, MIN_TOKEN_INDEX, size()-1);
|
353
|
+
}
|
354
|
+
|
355
|
+
public String toString(int start, int end) {
|
356
|
+
return toString(DEFAULT_PROGRAM_NAME, start, end);
|
357
|
+
}
|
358
|
+
|
359
|
+
public String toString(String programName, int start, int end) {
|
360
|
+
List rewrites = (List)programs.get(programName);
|
361
|
+
|
362
|
+
// ensure start/end are in range
|
363
|
+
if ( end>tokens.size()-1 ) end = tokens.size()-1;
|
364
|
+
if ( start<0 ) start = 0;
|
365
|
+
|
366
|
+
if ( rewrites==null || rewrites.size()==0 ) {
|
367
|
+
return toOriginalString(start,end); // no instructions to execute
|
368
|
+
}
|
369
|
+
StringBuffer buf = new StringBuffer();
|
370
|
+
|
371
|
+
// First, optimize instruction stream
|
372
|
+
Map indexToOp = reduceToSingleOperationPerIndex(rewrites);
|
373
|
+
|
374
|
+
// Walk buffer, executing instructions and emitting tokens
|
375
|
+
int i = start;
|
376
|
+
while ( i <= end && i < tokens.size() ) {
|
377
|
+
RewriteOperation op = (RewriteOperation)indexToOp.get(new Integer(i));
|
378
|
+
indexToOp.remove(new Integer(i)); // remove so any left have index size-1
|
379
|
+
Token t = (Token) tokens.get(i);
|
380
|
+
if ( op==null ) {
|
381
|
+
// no operation at that index, just dump token
|
382
|
+
if ( t.getType()!=Token.EOF ) buf.append(t.getText());
|
383
|
+
i++; // move to next token
|
384
|
+
}
|
385
|
+
else {
|
386
|
+
i = op.execute(buf); // execute operation and skip
|
387
|
+
}
|
388
|
+
}
|
389
|
+
|
390
|
+
// include stuff after end if it's last index in buffer
|
391
|
+
// So, if they did an insertAfter(lastValidIndex, "foo"), include
|
392
|
+
// foo if end==lastValidIndex.
|
393
|
+
if ( end==tokens.size()-1 ) {
|
394
|
+
// Scan any remaining operations after last token
|
395
|
+
// should be included (they will be inserts).
|
396
|
+
Iterator it = indexToOp.values().iterator();
|
397
|
+
while (it.hasNext()) {
|
398
|
+
RewriteOperation op = (RewriteOperation)it.next();
|
399
|
+
if ( op.index >= tokens.size()-1 ) buf.append(op.text);
|
400
|
+
}
|
401
|
+
}
|
402
|
+
return buf.toString();
|
403
|
+
}
|
404
|
+
|
405
|
+
/** We need to combine operations and report invalid operations (like
|
406
|
+
* overlapping replaces that are not completed nested). Inserts to
|
407
|
+
* same index need to be combined etc... Here are the cases:
|
408
|
+
*
|
409
|
+
* I.i.u I.j.v leave alone, nonoverlapping
|
410
|
+
* I.i.u I.i.v combine: Iivu
|
411
|
+
*
|
412
|
+
* R.i-j.u R.x-y.v | i-j in x-y delete first R
|
413
|
+
* R.i-j.u R.i-j.v delete first R
|
414
|
+
* R.i-j.u R.x-y.v | x-y in i-j ERROR
|
415
|
+
* R.i-j.u R.x-y.v | boundaries overlap ERROR
|
416
|
+
*
|
417
|
+
* I.i.u R.x-y.v | i in x-y delete I
|
418
|
+
* I.i.u R.x-y.v | i not in x-y leave alone, nonoverlapping
|
419
|
+
* R.x-y.v I.i.u | i in x-y ERROR
|
420
|
+
* R.x-y.v I.x.u R.x-y.uv (combine, delete I)
|
421
|
+
* R.x-y.v I.i.u | i not in x-y leave alone, nonoverlapping
|
422
|
+
*
|
423
|
+
* I.i.u = insert u before op @ index i
|
424
|
+
* R.x-y.u = replace x-y indexed tokens with u
|
425
|
+
*
|
426
|
+
* First we need to examine replaces. For any replace op:
|
427
|
+
*
|
428
|
+
* 1. wipe out any insertions before op within that range.
|
429
|
+
* 2. Drop any replace op before that is contained completely within
|
430
|
+
* that range.
|
431
|
+
* 3. Throw exception upon boundary overlap with any previous replace.
|
432
|
+
*
|
433
|
+
* Then we can deal with inserts:
|
434
|
+
*
|
435
|
+
* 1. for any inserts to same index, combine even if not adjacent.
|
436
|
+
* 2. for any prior replace with same left boundary, combine this
|
437
|
+
* insert with replace and delete this replace.
|
438
|
+
* 3. throw exception if index in same range as previous replace
|
439
|
+
*
|
440
|
+
* Don't actually delete; make op null in list. Easier to walk list.
|
441
|
+
* Later we can throw as we add to index -> op map.
|
442
|
+
*
|
443
|
+
* Note that I.2 R.2-2 will wipe out I.2 even though, technically, the
|
444
|
+
* inserted stuff would be before the replace range. But, if you
|
445
|
+
* add tokens in front of a method body '{' and then delete the method
|
446
|
+
* body, I think the stuff before the '{' you added should disappear too.
|
447
|
+
*
|
448
|
+
* Return a map from token index to operation.
|
449
|
+
*/
|
450
|
+
protected Map reduceToSingleOperationPerIndex(List rewrites) {
|
451
|
+
//System.out.println("rewrites="+rewrites);
|
452
|
+
|
453
|
+
// WALK REPLACES
|
454
|
+
for (int i = 0; i < rewrites.size(); i++) {
|
455
|
+
RewriteOperation op = (RewriteOperation)rewrites.get(i);
|
456
|
+
if ( op==null ) continue;
|
457
|
+
if ( !(op instanceof ReplaceOp) ) continue;
|
458
|
+
ReplaceOp rop = (ReplaceOp)rewrites.get(i);
|
459
|
+
// Wipe prior inserts within range
|
460
|
+
List inserts = getKindOfOps(rewrites, InsertBeforeOp.class, i);
|
461
|
+
for (int j = 0; j < inserts.size(); j++) {
|
462
|
+
InsertBeforeOp iop = (InsertBeforeOp) inserts.get(j);
|
463
|
+
if ( iop.index >= rop.index && iop.index <= rop.lastIndex ) {
|
464
|
+
// delete insert as it's a no-op.
|
465
|
+
rewrites.set(iop.instructionIndex, null);
|
466
|
+
}
|
467
|
+
}
|
468
|
+
// Drop any prior replaces contained within
|
469
|
+
List prevReplaces = getKindOfOps(rewrites, ReplaceOp.class, i);
|
470
|
+
for (int j = 0; j < prevReplaces.size(); j++) {
|
471
|
+
ReplaceOp prevRop = (ReplaceOp) prevReplaces.get(j);
|
472
|
+
if ( prevRop.index>=rop.index && prevRop.lastIndex <= rop.lastIndex ) {
|
473
|
+
// delete replace as it's a no-op.
|
474
|
+
rewrites.set(prevRop.instructionIndex, null);
|
475
|
+
continue;
|
476
|
+
}
|
477
|
+
// throw exception unless disjoint or identical
|
478
|
+
boolean disjoint =
|
479
|
+
prevRop.lastIndex<rop.index || prevRop.index > rop.lastIndex;
|
480
|
+
boolean same =
|
481
|
+
prevRop.index==rop.index && prevRop.lastIndex==rop.lastIndex;
|
482
|
+
if ( !disjoint && !same ) {
|
483
|
+
throw new IllegalArgumentException("replace op boundaries of "+rop+
|
484
|
+
" overlap with previous "+prevRop);
|
485
|
+
}
|
486
|
+
}
|
487
|
+
}
|
488
|
+
|
489
|
+
// WALK INSERTS
|
490
|
+
for (int i = 0; i < rewrites.size(); i++) {
|
491
|
+
RewriteOperation op = (RewriteOperation)rewrites.get(i);
|
492
|
+
if ( op==null ) continue;
|
493
|
+
if ( !(op instanceof InsertBeforeOp) ) continue;
|
494
|
+
InsertBeforeOp iop = (InsertBeforeOp)rewrites.get(i);
|
495
|
+
// combine current insert with prior if any at same index
|
496
|
+
List prevInserts = getKindOfOps(rewrites, InsertBeforeOp.class, i);
|
497
|
+
for (int j = 0; j < prevInserts.size(); j++) {
|
498
|
+
InsertBeforeOp prevIop = (InsertBeforeOp) prevInserts.get(j);
|
499
|
+
if ( prevIop.index == iop.index ) { // combine objects
|
500
|
+
// convert to strings...we're in process of toString'ing
|
501
|
+
// whole token buffer so no lazy eval issue with any templates
|
502
|
+
iop.text = catOpText(iop.text,prevIop.text);
|
503
|
+
// delete redundant prior insert
|
504
|
+
rewrites.set(prevIop.instructionIndex, null);
|
505
|
+
}
|
506
|
+
}
|
507
|
+
// look for replaces where iop.index is in range; error
|
508
|
+
List prevReplaces = getKindOfOps(rewrites, ReplaceOp.class, i);
|
509
|
+
for (int j = 0; j < prevReplaces.size(); j++) {
|
510
|
+
ReplaceOp rop = (ReplaceOp) prevReplaces.get(j);
|
511
|
+
if ( iop.index == rop.index ) {
|
512
|
+
rop.text = catOpText(iop.text,rop.text);
|
513
|
+
rewrites.set(i, null); // delete current insert
|
514
|
+
continue;
|
515
|
+
}
|
516
|
+
if ( iop.index >= rop.index && iop.index <= rop.lastIndex ) {
|
517
|
+
throw new IllegalArgumentException("insert op "+iop+
|
518
|
+
" within boundaries of previous "+rop);
|
519
|
+
}
|
520
|
+
}
|
521
|
+
}
|
522
|
+
// System.out.println("rewrites after="+rewrites);
|
523
|
+
Map m = new HashMap();
|
524
|
+
for (int i = 0; i < rewrites.size(); i++) {
|
525
|
+
RewriteOperation op = (RewriteOperation)rewrites.get(i);
|
526
|
+
if ( op==null ) continue; // ignore deleted ops
|
527
|
+
if ( m.get(new Integer(op.index))!=null ) {
|
528
|
+
throw new Error("should only be one op per index");
|
529
|
+
}
|
530
|
+
m.put(new Integer(op.index), op);
|
531
|
+
}
|
532
|
+
//System.out.println("index to op: "+m);
|
533
|
+
return m;
|
534
|
+
}
|
535
|
+
|
536
|
+
protected String catOpText(Object a, Object b) {
|
537
|
+
String x = "";
|
538
|
+
String y = "";
|
539
|
+
if ( a!=null ) x = a.toString();
|
540
|
+
if ( b!=null ) y = b.toString();
|
541
|
+
return x+y;
|
542
|
+
}
|
543
|
+
protected List getKindOfOps(List rewrites, Class kind) {
|
544
|
+
return getKindOfOps(rewrites, kind, rewrites.size());
|
545
|
+
}
|
546
|
+
|
547
|
+
/** Get all operations before an index of a particular kind */
|
548
|
+
protected List getKindOfOps(List rewrites, Class kind, int before) {
|
549
|
+
List ops = new ArrayList();
|
550
|
+
for (int i=0; i<before && i<rewrites.size(); i++) {
|
551
|
+
RewriteOperation op = (RewriteOperation)rewrites.get(i);
|
552
|
+
if ( op==null ) continue; // ignore deleted
|
553
|
+
if ( op.getClass() == kind ) ops.add(op);
|
554
|
+
}
|
555
|
+
return ops;
|
556
|
+
}
|
557
|
+
|
558
|
+
public String toDebugString() {
|
559
|
+
return toDebugString(MIN_TOKEN_INDEX, size()-1);
|
560
|
+
}
|
561
|
+
|
562
|
+
public String toDebugString(int start, int end) {
|
563
|
+
StringBuffer buf = new StringBuffer();
|
564
|
+
for (int i=start; i>=MIN_TOKEN_INDEX && i<=end && i<tokens.size(); i++) {
|
565
|
+
buf.append(get(i));
|
566
|
+
}
|
567
|
+
return buf.toString();
|
568
|
+
}
|
569
|
+
}
|