| /* |
| * Copyright 2015, Google Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| package org.jf.smalidea.findUsages; |
| |
| import com.intellij.lang.cacheBuilder.WordOccurrence; |
| import com.intellij.lang.cacheBuilder.WordOccurrence.Kind; |
| import com.intellij.lang.cacheBuilder.WordsScanner; |
| import com.intellij.psi.tree.IElementType; |
| import com.intellij.psi.tree.TokenSet; |
| import com.intellij.util.Processor; |
| import org.jetbrains.annotations.NotNull; |
| import org.jf.smalidea.SmaliLexer; |
| import org.jf.smalidea.SmaliTokens; |
| |
| public class SmaliWordScanner implements WordsScanner { |
| |
| private static final TokenSet MEMBER_NAME_TOKENS = TokenSet.create( |
| SmaliTokens.MEMBER_NAME, |
| SmaliTokens.SIMPLE_NAME, |
| SmaliTokens.ACCESS_SPEC, |
| SmaliTokens.VERIFICATION_ERROR_TYPE, |
| SmaliTokens.POSITIVE_INTEGER_LITERAL, |
| SmaliTokens.NEGATIVE_INTEGER_LITERAL, |
| SmaliTokens.FLOAT_LITERAL_OR_ID, |
| SmaliTokens.DOUBLE_LITERAL_OR_ID, |
| SmaliTokens.BOOL_LITERAL, |
| SmaliTokens.NULL_LITERAL, |
| SmaliTokens.REGISTER, |
| SmaliTokens.PRIMITIVE_TYPE, |
| SmaliTokens.VOID_TYPE, |
| SmaliTokens.ANNOTATION_VISIBILITY, |
| SmaliTokens.INSTRUCTION_FORMAT10t, |
| SmaliTokens.INSTRUCTION_FORMAT10x, |
| SmaliTokens.INSTRUCTION_FORMAT10x_ODEX, |
| SmaliTokens.INSTRUCTION_FORMAT11x, |
| SmaliTokens.INSTRUCTION_FORMAT12x_OR_ID, |
| SmaliTokens.INSTRUCTION_FORMAT21c_FIELD, |
| SmaliTokens.INSTRUCTION_FORMAT21c_FIELD_ODEX, |
| SmaliTokens.INSTRUCTION_FORMAT21c_STRING, |
| SmaliTokens.INSTRUCTION_FORMAT21c_TYPE, |
| SmaliTokens.INSTRUCTION_FORMAT21t, |
| SmaliTokens.INSTRUCTION_FORMAT22c_FIELD, |
| SmaliTokens.INSTRUCTION_FORMAT22c_FIELD_ODEX, |
| SmaliTokens.INSTRUCTION_FORMAT22c_TYPE, |
| SmaliTokens.INSTRUCTION_FORMAT22cs_FIELD, |
| SmaliTokens.INSTRUCTION_FORMAT22s_OR_ID, |
| SmaliTokens.INSTRUCTION_FORMAT22t, |
| SmaliTokens.INSTRUCTION_FORMAT23x, |
| SmaliTokens.INSTRUCTION_FORMAT31i_OR_ID, |
| SmaliTokens.INSTRUCTION_FORMAT31t, |
| SmaliTokens.INSTRUCTION_FORMAT35c_METHOD, |
| SmaliTokens.INSTRUCTION_FORMAT35c_METHOD_ODEX, |
| SmaliTokens.INSTRUCTION_FORMAT35c_TYPE, |
| SmaliTokens.INSTRUCTION_FORMAT35mi_METHOD, |
| SmaliTokens.INSTRUCTION_FORMAT35ms_METHOD, |
| SmaliTokens.INSTRUCTION_FORMAT51l); |
| |
| @Override public void processWords(CharSequence fileText, Processor<WordOccurrence> processor) { |
| SmaliLexer lexer = new SmaliLexer(); |
| lexer.start(fileText); |
| |
| IElementType type = lexer.getTokenType(); |
| while (type != null) { |
| if (type == SmaliTokens.CLASS_DESCRIPTOR) { |
| processClassDescriptor(fileText, lexer.getTokenStart(), lexer.getTokenEnd(), processor); |
| } else if (MEMBER_NAME_TOKENS.contains(type)) { |
| processor.process(new WordOccurrence(fileText, lexer.getTokenStart(), lexer.getTokenEnd(), Kind.CODE)); |
| } else if (type == SmaliTokens.PARAM_LIST_OR_ID_PRIMITIVE_TYPE) { |
| int tokenStart = lexer.getTokenStart(); |
| while (type == SmaliTokens.PARAM_LIST_OR_ID_PRIMITIVE_TYPE) { |
| lexer.advance(); |
| type = lexer.getTokenType(); |
| } |
| int tokenEnd = lexer.getTokenStart(); |
| processor.process(new WordOccurrence(fileText, tokenStart, tokenEnd, Kind.CODE)); |
| } |
| lexer.advance(); |
| type = lexer.getTokenType(); |
| } |
| } |
| |
| private void processClassDescriptor(CharSequence fileText, int tokenStart, int tokenEnd, |
| @NotNull Processor<WordOccurrence> processor) { |
| CharSequence tokenText = fileText.subSequence(tokenStart, tokenEnd); |
| |
| assert tokenText.charAt(0) == 'L' && tokenText.charAt(tokenText.length()-1) == ';'; |
| processor.process(new WordOccurrence(fileText, tokenStart, tokenEnd, Kind.CODE)); |
| } |
| } |