• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015, Google Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 package org.jf.smalidea.findUsages;
33 
34 import com.intellij.lang.cacheBuilder.WordOccurrence;
35 import com.intellij.lang.cacheBuilder.WordOccurrence.Kind;
36 import com.intellij.lang.cacheBuilder.WordsScanner;
37 import com.intellij.psi.tree.IElementType;
38 import com.intellij.psi.tree.TokenSet;
39 import com.intellij.util.Processor;
40 import org.jetbrains.annotations.NotNull;
41 import org.jf.smalidea.SmaliLexer;
42 import org.jf.smalidea.SmaliTokens;
43 
44 public class SmaliWordScanner implements WordsScanner {
45 
46     private static final TokenSet MEMBER_NAME_TOKENS = TokenSet.create(
47             SmaliTokens.MEMBER_NAME,
48             SmaliTokens.SIMPLE_NAME,
49             SmaliTokens.ACCESS_SPEC,
50             SmaliTokens.VERIFICATION_ERROR_TYPE,
51             SmaliTokens.POSITIVE_INTEGER_LITERAL,
52             SmaliTokens.NEGATIVE_INTEGER_LITERAL,
53             SmaliTokens.FLOAT_LITERAL_OR_ID,
54             SmaliTokens.DOUBLE_LITERAL_OR_ID,
55             SmaliTokens.BOOL_LITERAL,
56             SmaliTokens.NULL_LITERAL,
57             SmaliTokens.REGISTER,
58             SmaliTokens.PRIMITIVE_TYPE,
59             SmaliTokens.VOID_TYPE,
60             SmaliTokens.ANNOTATION_VISIBILITY,
61             SmaliTokens.INSTRUCTION_FORMAT10t,
62             SmaliTokens.INSTRUCTION_FORMAT10x,
63             SmaliTokens.INSTRUCTION_FORMAT10x_ODEX,
64             SmaliTokens.INSTRUCTION_FORMAT11x,
65             SmaliTokens.INSTRUCTION_FORMAT12x_OR_ID,
66             SmaliTokens.INSTRUCTION_FORMAT21c_FIELD,
67             SmaliTokens.INSTRUCTION_FORMAT21c_FIELD_ODEX,
68             SmaliTokens.INSTRUCTION_FORMAT21c_STRING,
69             SmaliTokens.INSTRUCTION_FORMAT21c_TYPE,
70             SmaliTokens.INSTRUCTION_FORMAT21t,
71             SmaliTokens.INSTRUCTION_FORMAT22c_FIELD,
72             SmaliTokens.INSTRUCTION_FORMAT22c_FIELD_ODEX,
73             SmaliTokens.INSTRUCTION_FORMAT22c_TYPE,
74             SmaliTokens.INSTRUCTION_FORMAT22cs_FIELD,
75             SmaliTokens.INSTRUCTION_FORMAT22s_OR_ID,
76             SmaliTokens.INSTRUCTION_FORMAT22t,
77             SmaliTokens.INSTRUCTION_FORMAT23x,
78             SmaliTokens.INSTRUCTION_FORMAT31i_OR_ID,
79             SmaliTokens.INSTRUCTION_FORMAT31t,
80             SmaliTokens.INSTRUCTION_FORMAT35c_METHOD,
81             SmaliTokens.INSTRUCTION_FORMAT35c_METHOD_ODEX,
82             SmaliTokens.INSTRUCTION_FORMAT35c_TYPE,
83             SmaliTokens.INSTRUCTION_FORMAT35mi_METHOD,
84             SmaliTokens.INSTRUCTION_FORMAT35ms_METHOD,
85             SmaliTokens.INSTRUCTION_FORMAT51l);
86 
processWords(CharSequence fileText, Processor<WordOccurrence> processor)87     @Override public void processWords(CharSequence fileText, Processor<WordOccurrence> processor) {
88         SmaliLexer lexer = new SmaliLexer();
89         lexer.start(fileText);
90 
91         IElementType type = lexer.getTokenType();
92         while (type != null) {
93             if (type == SmaliTokens.CLASS_DESCRIPTOR) {
94                 processClassDescriptor(fileText, lexer.getTokenStart(), lexer.getTokenEnd(), processor);
95             } else if (MEMBER_NAME_TOKENS.contains(type)) {
96                 processor.process(new WordOccurrence(fileText, lexer.getTokenStart(), lexer.getTokenEnd(), Kind.CODE));
97             } else if (type == SmaliTokens.PARAM_LIST_OR_ID_PRIMITIVE_TYPE) {
98                 int tokenStart = lexer.getTokenStart();
99                 while (type == SmaliTokens.PARAM_LIST_OR_ID_PRIMITIVE_TYPE) {
100                     lexer.advance();
101                     type = lexer.getTokenType();
102                 }
103                 int tokenEnd = lexer.getTokenStart();
104                 processor.process(new WordOccurrence(fileText, tokenStart, tokenEnd, Kind.CODE));
105             }
106             lexer.advance();
107             type = lexer.getTokenType();
108         }
109     }
110 
processClassDescriptor(CharSequence fileText, int tokenStart, int tokenEnd, @NotNull Processor<WordOccurrence> processor)111     private void processClassDescriptor(CharSequence fileText, int tokenStart, int tokenEnd,
112                                         @NotNull Processor<WordOccurrence> processor) {
113         CharSequence tokenText = fileText.subSequence(tokenStart, tokenEnd);
114 
115         assert tokenText.charAt(0) == 'L' && tokenText.charAt(tokenText.length()-1) == ';';
116         processor.process(new WordOccurrence(fileText, tokenStart, tokenEnd, Kind.CODE));
117     }
118 }
119