14a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver/*
24a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * Copyright 2014, Google Inc.
34a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * All rights reserved.
44a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver *
54a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * Redistribution and use in source and binary forms, with or without
64a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * modification, are permitted provided that the following conditions are
74a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * met:
84a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver *
94a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver *     * Redistributions of source code must retain the above copyright
104a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * notice, this list of conditions and the following disclaimer.
114a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver *     * Redistributions in binary form must reproduce the above
124a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * copyright notice, this list of conditions and the following disclaimer
134a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * in the documentation and/or other materials provided with the
144a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * distribution.
154a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver *     * Neither the name of Google Inc. nor the names of its
164a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * contributors may be used to endorse or promote products derived from
174a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * this software without specific prior written permission.
184a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver *
194a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
204a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
214a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
224a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
234a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
244a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
254a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
264a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
274a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
284a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
294a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
304a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver */
314a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver
324a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruverpackage org.jf.smalidea.psi.impl;
334a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver
34ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruverimport com.google.common.base.Supplier;
35ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruverimport com.google.common.base.Suppliers;
36ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruverimport com.google.common.collect.Maps;
37a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruverimport com.intellij.debugger.SourcePosition;
384a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruverimport com.intellij.lang.ASTNode;
396513dc012449f94668f2e207642e7763df52b729Ben Gruverimport com.intellij.openapi.editor.Document;
4056d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport com.intellij.psi.*;
4156d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport com.intellij.psi.PsiModifier.ModifierConstant;
4256d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport com.intellij.psi.impl.PsiImplUtil;
4356d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport com.intellij.psi.impl.PsiSuperMethodImplUtil;
4456d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport com.intellij.psi.javadoc.PsiDocComment;
4556d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport com.intellij.psi.util.MethodSignature;
4656d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
47ea04d22ffd6dfba6cb4309550e0cbe445e0fef89Ben Gruverimport com.intellij.psi.util.PsiTreeUtil;
4856d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport com.intellij.util.IncorrectOperationException;
4956d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport org.jetbrains.annotations.NonNls;
504a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruverimport org.jetbrains.annotations.NotNull;
5156d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport org.jetbrains.annotations.Nullable;
527b387e06c546e0b9f7caf4434df943651db32cdeBen Gruverimport org.jf.dexlib2.analysis.AnalysisException;
53cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport org.jf.dexlib2.analysis.ClassPath;
54cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport org.jf.dexlib2.analysis.MethodAnalyzer;
55cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport org.jf.smalidea.dexlib.SmalideaMethod;
56ff4c85c5e4e380607fe1f89dc72db7339f77db8cBen Gruverimport org.jf.smalidea.dexlib.analysis.SmalideaClassProvider;
574a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruverimport org.jf.smalidea.psi.SmaliElementTypes;
5856d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport org.jf.smalidea.psi.iface.SmaliModifierListOwner;
594a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruverimport org.jf.smalidea.psi.stub.SmaliMethodStub;
604a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver
61cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruverimport java.io.IOException;
629b97cfdf4882d4e306e3f81709be4649031cd799Ben Gruverimport java.util.Arrays;
6356d5befed49287e7d77872030e640c34fc887c4aBen Gruverimport java.util.List;
64ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruverimport java.util.Map;
6556d5befed49287e7d77872030e640c34fc887c4aBen Gruver
6656d5befed49287e7d77872030e640c34fc887c4aBen Gruverpublic class SmaliMethod extends SmaliStubBasedPsiElement<SmaliMethodStub>
6744a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver        implements PsiMethod, SmaliModifierListOwner, PsiAnnotationMethod {
684a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver    public SmaliMethod(@NotNull SmaliMethodStub stub) {
694a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver        super(stub, SmaliElementTypes.METHOD);
704a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver    }
714a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver
724a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver    public SmaliMethod(@NotNull ASTNode node) {
734a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver        super(node);
744a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver    }
7512b3579577627fd709d60d016b455f7e309f48acBen Gruver
7656d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public String getName() {
7756d5befed49287e7d77872030e640c34fc887c4aBen Gruver        SmaliMethodStub stub = getStub();
780a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver        String name = null;
7956d5befed49287e7d77872030e640c34fc887c4aBen Gruver        if (stub != null) {
800a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver            name = stub.getName();
810a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver        } else {
820a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver            SmaliMemberName nameIdentifier = getNameIdentifier();
830a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver            if (nameIdentifier != null) {
840a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver                name = nameIdentifier.getText();
850a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver            }
860a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver        }
870a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver        if (name == null || name.isEmpty()) {
880a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver            name = "<unnamed>";
8956d5befed49287e7d77872030e640c34fc887c4aBen Gruver        }
900a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver        return name;
9156d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
9256d5befed49287e7d77872030e640c34fc887c4aBen Gruver
9356d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @Override public boolean hasTypeParameters() {
9456d5befed49287e7d77872030e640c34fc887c4aBen Gruver        // TODO: (generics) implement this
9556d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return false;
9656d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
9756d5befed49287e7d77872030e640c34fc887c4aBen Gruver
9856d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull
9956d5befed49287e7d77872030e640c34fc887c4aBen Gruver    public SmaliMethodPrototype getMethodPrototype() {
10056d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return getRequiredStubOrPsiChild(SmaliElementTypes.METHOD_PROTOTYPE);
10156d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
10256d5befed49287e7d77872030e640c34fc887c4aBen Gruver
1030a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver    @Nullable @Override public PsiType getReturnType() {
1047f6afa6a259cfcc06ce962029401189d080663a0Ben Gruver        if (isConstructor()) return null;
1057f6afa6a259cfcc06ce962029401189d080663a0Ben Gruver        return getMethodPrototype().getReturnType();
10656d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
10756d5befed49287e7d77872030e640c34fc887c4aBen Gruver
1080a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver    @Nullable @Override public PsiTypeElement getReturnTypeElement() {
1097f6afa6a259cfcc06ce962029401189d080663a0Ben Gruver        if (isConstructor()) return null;
1107f6afa6a259cfcc06ce962029401189d080663a0Ben Gruver        return getMethodPrototype().getReturnTypeElement();
11156d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
11256d5befed49287e7d77872030e640c34fc887c4aBen Gruver
11356d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public SmaliMethodParamList getParameterList() {
11456d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return getMethodPrototype().getParameterList();
11556d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
11656d5befed49287e7d77872030e640c34fc887c4aBen Gruver
1176a520231e74c1045e43f4b34182562979fbfc988Ben Gruver    @NotNull @Override public SmaliThrowsList getThrowsList() {
1186a520231e74c1045e43f4b34182562979fbfc988Ben Gruver        return getRequiredStubOrPsiChild(SmaliElementTypes.THROWS_LIST);
11956d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
12056d5befed49287e7d77872030e640c34fc887c4aBen Gruver
12156d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @Nullable @Override public PsiCodeBlock getBody() {
12256d5befed49287e7d77872030e640c34fc887c4aBen Gruver        // not applicable
12356d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return null;
12456d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
12556d5befed49287e7d77872030e640c34fc887c4aBen Gruver
126a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver    @NotNull public List<SmaliInstruction> getInstructions() {
127a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver        return findChildrenByType(SmaliElementTypes.INSTRUCTION);
128a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver    }
129a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver
1309b97cfdf4882d4e306e3f81709be4649031cd799Ben Gruver    @NotNull public List<SmaliCatchStatement> getCatchStatements() {
1319b97cfdf4882d4e306e3f81709be4649031cd799Ben Gruver        return Arrays.asList(findChildrenByClass(SmaliCatchStatement.class));
1329b97cfdf4882d4e306e3f81709be4649031cd799Ben Gruver    }
1339b97cfdf4882d4e306e3f81709be4649031cd799Ben Gruver
134a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver    @Nullable public SourcePosition getSourcePositionForCodeOffset(int offset) {
135a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver        for (SmaliInstruction instruction: getInstructions()) {
136a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver            if (instruction.getOffset() >= offset) {
137a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver                return SourcePosition.createFromElement(instruction);
138a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver            }
139a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver        }
140a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver        return null;
141a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver    }
142a788ab1dc3543ca4470c45a57f80ba8538c50a9cBen Gruver
1436513dc012449f94668f2e207642e7763df52b729Ben Gruver    public int getOffsetForLine(int line) {
1446513dc012449f94668f2e207642e7763df52b729Ben Gruver        PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
1456513dc012449f94668f2e207642e7763df52b729Ben Gruver        final Document document = documentManager.getDocument(getContainingFile());
1466513dc012449f94668f2e207642e7763df52b729Ben Gruver        if (document == null) {
1476513dc012449f94668f2e207642e7763df52b729Ben Gruver            return -1;
1486513dc012449f94668f2e207642e7763df52b729Ben Gruver        }
1496513dc012449f94668f2e207642e7763df52b729Ben Gruver
1506513dc012449f94668f2e207642e7763df52b729Ben Gruver        for (final SmaliInstruction instruction: getInstructions()) {
1516513dc012449f94668f2e207642e7763df52b729Ben Gruver            int curLine = document.getLineNumber(instruction.getTextOffset());
1526513dc012449f94668f2e207642e7763df52b729Ben Gruver            if (curLine >= line) {
1536513dc012449f94668f2e207642e7763df52b729Ben Gruver                return instruction.getOffset();
1546513dc012449f94668f2e207642e7763df52b729Ben Gruver            }
1556513dc012449f94668f2e207642e7763df52b729Ben Gruver        }
1566513dc012449f94668f2e207642e7763df52b729Ben Gruver        return -1;
1576513dc012449f94668f2e207642e7763df52b729Ben Gruver    }
1586513dc012449f94668f2e207642e7763df52b729Ben Gruver
15912b3579577627fd709d60d016b455f7e309f48acBen Gruver    public int getRegisterCount() {
16012b3579577627fd709d60d016b455f7e309f48acBen Gruver        SmaliRegistersStatement registersStatement = findChildByClass(SmaliRegistersStatement.class);
16112b3579577627fd709d60d016b455f7e309f48acBen Gruver        if (registersStatement == null) {
16212b3579577627fd709d60d016b455f7e309f48acBen Gruver            return 0;
16312b3579577627fd709d60d016b455f7e309f48acBen Gruver        }
16412b3579577627fd709d60d016b455f7e309f48acBen Gruver        return registersStatement.getRegisterCount();
16512b3579577627fd709d60d016b455f7e309f48acBen Gruver    }
16612b3579577627fd709d60d016b455f7e309f48acBen Gruver
16712b3579577627fd709d60d016b455f7e309f48acBen Gruver    public int getParameterRegisterCount() {
16856d5befed49287e7d77872030e640c34fc887c4aBen Gruver        int parameterRegisterCount = getMethodPrototype().getParameterList().getParameterRegisterCount();
16916dde79e587da4ea840293e196a02101b1aafc22Ben Gruver        if (!isStatic()) {
17056d5befed49287e7d77872030e640c34fc887c4aBen Gruver            parameterRegisterCount++;
17156d5befed49287e7d77872030e640c34fc887c4aBen Gruver        }
17256d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return parameterRegisterCount;
17356d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
17456d5befed49287e7d77872030e640c34fc887c4aBen Gruver
1759b97cfdf4882d4e306e3f81709be4649031cd799Ben Gruver    @NotNull public SmaliParameterStatement[] getParameterStatements() {
17656d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return findChildrenByClass(SmaliParameterStatement.class);
17756d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
17856d5befed49287e7d77872030e640c34fc887c4aBen Gruver
17956d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @Override public boolean isConstructor() {
180ea04d22ffd6dfba6cb4309550e0cbe445e0fef89Ben Gruver        // TODO: should this return true for the class initializer?
18156d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return hasModifierProperty("constructor") && !hasModifierProperty("static");
18256d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
18356d5befed49287e7d77872030e640c34fc887c4aBen Gruver
18416dde79e587da4ea840293e196a02101b1aafc22Ben Gruver    public boolean isStatic() {
18516dde79e587da4ea840293e196a02101b1aafc22Ben Gruver        return hasModifierProperty("static");
18616dde79e587da4ea840293e196a02101b1aafc22Ben Gruver    }
18716dde79e587da4ea840293e196a02101b1aafc22Ben Gruver
18856d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @Override public boolean isVarArgs() {
18956d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return hasModifierProperty("varargs");
19056d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
19156d5befed49287e7d77872030e640c34fc887c4aBen Gruver
19256d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public MethodSignature getSignature(@NotNull PsiSubstitutor substitutor) {
19356d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return MethodSignatureBackedByPsiMethod.create(this, substitutor);
19456d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
19556d5befed49287e7d77872030e640c34fc887c4aBen Gruver
1960a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver    @Nullable @Override public SmaliMemberName getNameIdentifier() {
1970a5f278d5fc25b8e1d2d644e7eefa2702579dee3Ben Gruver        return findChildByClass(SmaliMemberName.class);
19856d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
19956d5befed49287e7d77872030e640c34fc887c4aBen Gruver
20056d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public PsiMethod[] findSuperMethods() {
20156d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return PsiSuperMethodImplUtil.findSuperMethods(this);
20256d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
20356d5befed49287e7d77872030e640c34fc887c4aBen Gruver
20456d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public PsiMethod[] findSuperMethods(boolean checkAccess) {
20556d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return PsiSuperMethodImplUtil.findSuperMethods(this, checkAccess);
20656d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
20756d5befed49287e7d77872030e640c34fc887c4aBen Gruver
20856d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public PsiMethod[] findSuperMethods(PsiClass parentClass) {
20956d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return PsiSuperMethodImplUtil.findSuperMethods(this, parentClass);
21056d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
21156d5befed49287e7d77872030e640c34fc887c4aBen Gruver
21256d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override
21356d5befed49287e7d77872030e640c34fc887c4aBen Gruver    public List<MethodSignatureBackedByPsiMethod> findSuperMethodSignaturesIncludingStatic(boolean checkAccess) {
21456d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return PsiSuperMethodImplUtil.findSuperMethodSignaturesIncludingStatic(this, checkAccess);
21556d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
21656d5befed49287e7d77872030e640c34fc887c4aBen Gruver
21756d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @Nullable @Override public PsiMethod findDeepestSuperMethod() {
21856d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return PsiSuperMethodImplUtil.findDeepestSuperMethod(this);
21956d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
22056d5befed49287e7d77872030e640c34fc887c4aBen Gruver
22156d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public PsiMethod[] findDeepestSuperMethods() {
22256d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return PsiSuperMethodImplUtil.findDeepestSuperMethods(this);
22356d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
22456d5befed49287e7d77872030e640c34fc887c4aBen Gruver
22556d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public SmaliModifierList getModifierList() {
22656d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return getRequiredStubOrPsiChild(SmaliElementTypes.MODIFIER_LIST);
22756d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
22856d5befed49287e7d77872030e640c34fc887c4aBen Gruver
22956d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @Override public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
23048aacd2c01c116b154ee85df98024f6c6e4cb55aBen Gruver        SmaliMemberName smaliMemberName = getNameIdentifier();
23148aacd2c01c116b154ee85df98024f6c6e4cb55aBen Gruver        if (smaliMemberName == null) {
23248aacd2c01c116b154ee85df98024f6c6e4cb55aBen Gruver            throw new IncorrectOperationException();
23348aacd2c01c116b154ee85df98024f6c6e4cb55aBen Gruver        }
23448aacd2c01c116b154ee85df98024f6c6e4cb55aBen Gruver        smaliMemberName.setName(name);
23548aacd2c01c116b154ee85df98024f6c6e4cb55aBen Gruver        return this;
23656d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
23756d5befed49287e7d77872030e640c34fc887c4aBen Gruver
23856d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public HierarchicalMethodSignature getHierarchicalMethodSignature() {
23956d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return PsiSuperMethodImplUtil.getHierarchicalMethodSignature(this);
24056d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
24156d5befed49287e7d77872030e640c34fc887c4aBen Gruver
24256d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @Nullable @Override public PsiDocComment getDocComment() {
24356d5befed49287e7d77872030e640c34fc887c4aBen Gruver        // not applicable
24456d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return null;
24556d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
24656d5befed49287e7d77872030e640c34fc887c4aBen Gruver
24756d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @Override public boolean isDeprecated() {
24856d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return PsiImplUtil.isDeprecatedByAnnotation(this);
24956d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
25056d5befed49287e7d77872030e640c34fc887c4aBen Gruver
25156d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @Nullable @Override public PsiTypeParameterList getTypeParameterList() {
25256d5befed49287e7d77872030e640c34fc887c4aBen Gruver        // TODO: (generics) implement this
25356d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return null;
25456d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
25556d5befed49287e7d77872030e640c34fc887c4aBen Gruver
25656d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public PsiTypeParameter[] getTypeParameters() {
25756d5befed49287e7d77872030e640c34fc887c4aBen Gruver        // TODO: (generics) implement this
25856d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return new PsiTypeParameter[0];
25956d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
26056d5befed49287e7d77872030e640c34fc887c4aBen Gruver
26144a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver    @Nullable @Override public SmaliClass getContainingClass() {
2621390c6cff68803dd82e4939a8e0cdddc690a6502Ben Gruver        PsiElement parent = getParentByStub();
26348aacd2c01c116b154ee85df98024f6c6e4cb55aBen Gruver        if (parent instanceof SmaliClass) {
26448aacd2c01c116b154ee85df98024f6c6e4cb55aBen Gruver            return (SmaliClass) parent;
26548aacd2c01c116b154ee85df98024f6c6e4cb55aBen Gruver        }
26648aacd2c01c116b154ee85df98024f6c6e4cb55aBen Gruver        return null;
26756d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
26856d5befed49287e7d77872030e640c34fc887c4aBen Gruver
26956d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @Override public boolean hasModifierProperty(@ModifierConstant @NonNls @NotNull String name) {
27056d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return getModifierList().hasModifierProperty(name);
27156d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
27256d5befed49287e7d77872030e640c34fc887c4aBen Gruver
27356d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public SmaliAnnotation[] getAnnotations() {
27456d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return getStubOrPsiChildren(SmaliElementTypes.ANNOTATION, new SmaliAnnotation[0]);
27556d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
27656d5befed49287e7d77872030e640c34fc887c4aBen Gruver
27756d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public SmaliAnnotation[] getApplicableAnnotations() {
27856d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return getAnnotations();
27956d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
28056d5befed49287e7d77872030e640c34fc887c4aBen Gruver
28156d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @Nullable @Override public SmaliAnnotation findAnnotation(@NotNull @NonNls String qualifiedName) {
28256d5befed49287e7d77872030e640c34fc887c4aBen Gruver        for (SmaliAnnotation annotation: getAnnotations()) {
28356d5befed49287e7d77872030e640c34fc887c4aBen Gruver            if (qualifiedName.equals(annotation.getQualifiedName())) {
28456d5befed49287e7d77872030e640c34fc887c4aBen Gruver                return annotation;
28556d5befed49287e7d77872030e640c34fc887c4aBen Gruver            }
28656d5befed49287e7d77872030e640c34fc887c4aBen Gruver        }
28756d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return null;
28856d5befed49287e7d77872030e640c34fc887c4aBen Gruver    }
28956d5befed49287e7d77872030e640c34fc887c4aBen Gruver
29056d5befed49287e7d77872030e640c34fc887c4aBen Gruver    @NotNull @Override public SmaliAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
29112b3579577627fd709d60d016b455f7e309f48acBen Gruver        // TODO: implement this
29256d5befed49287e7d77872030e640c34fc887c4aBen Gruver        return null;
29312b3579577627fd709d60d016b455f7e309f48acBen Gruver    }
294ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver
295ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver    private final Supplier<Map<String, SmaliLabel>> labelMap = Suppliers.memoize(
296ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver            new Supplier<Map<String, SmaliLabel>>() {
297ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver                @Override public Map<String, SmaliLabel> get() {
298ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver                    Map<String, SmaliLabel> labelMap = Maps.newHashMap();
299ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver                    for (SmaliLabel label: findChildrenByClass(SmaliLabel.class)) {
300ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver                        if (!labelMap.containsKey(label.getText())) {
301ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver                            labelMap.put(label.getText(), label);
302ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver                        }
303ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver                    }
304ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver                    return labelMap;
305ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver                }
306ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver            });
307ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver
308ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver    @Nullable public SmaliLabel getLabel(String name) {
309ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver        return labelMap.get().get(name);
310ec63d20bb8cce01d3a07819c1416fac994e77e46Ben Gruver    }
311cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver
312cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver    private MethodAnalyzer methodAnalyzer = null;
313cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver
314ea04d22ffd6dfba6cb4309550e0cbe445e0fef89Ben Gruver    @Nullable
315cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver    public MethodAnalyzer getMethodAnalyzer() {
316cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver        if (methodAnalyzer == null) {
317ea04d22ffd6dfba6cb4309550e0cbe445e0fef89Ben Gruver            if (!PsiTreeUtil.hasErrorElements(this)) {
318ea04d22ffd6dfba6cb4309550e0cbe445e0fef89Ben Gruver                ClassPath classPath;
319ea04d22ffd6dfba6cb4309550e0cbe445e0fef89Ben Gruver                try {
320ff4c85c5e4e380607fe1f89dc72db7339f77db8cBen Gruver                    classPath = new ClassPath(
321ff4c85c5e4e380607fe1f89dc72db7339f77db8cBen Gruver                            new SmalideaClassProvider(getProject(), getContainingFile().getVirtualFile()));
322ea04d22ffd6dfba6cb4309550e0cbe445e0fef89Ben Gruver                } catch (IOException ex) {
323ea04d22ffd6dfba6cb4309550e0cbe445e0fef89Ben Gruver                    throw new RuntimeException(ex);
324ea04d22ffd6dfba6cb4309550e0cbe445e0fef89Ben Gruver                }
325cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver
3267b387e06c546e0b9f7caf4434df943651db32cdeBen Gruver                try {
3277b387e06c546e0b9f7caf4434df943651db32cdeBen Gruver                    methodAnalyzer = new MethodAnalyzer(classPath, new SmalideaMethod(SmaliMethod.this), null, false);
3287b387e06c546e0b9f7caf4434df943651db32cdeBen Gruver                } catch (AnalysisException ex) {
3297b387e06c546e0b9f7caf4434df943651db32cdeBen Gruver                    methodAnalyzer = null;
3307b387e06c546e0b9f7caf4434df943651db32cdeBen Gruver                }
331ea04d22ffd6dfba6cb4309550e0cbe445e0fef89Ben Gruver            }
332cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver        }
333cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver        return methodAnalyzer;
334cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver    }
335cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver
336cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver    @Override public void subtreeChanged() {
337cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver        super.subtreeChanged();
338cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver        methodAnalyzer = null;
339cbd87b904e15c63d06f25b03b0eadf003780ec6cBen Gruver    }
34037d1612e2f272b12d7ee556e05bb92f0e1a940b8Ben Gruver
34137d1612e2f272b12d7ee556e05bb92f0e1a940b8Ben Gruver    @Override public int getTextOffset() {
34237d1612e2f272b12d7ee556e05bb92f0e1a940b8Ben Gruver        SmaliMemberName smaliMemberName = getNameIdentifier();
34337d1612e2f272b12d7ee556e05bb92f0e1a940b8Ben Gruver        if (smaliMemberName != null) {
34437d1612e2f272b12d7ee556e05bb92f0e1a940b8Ben Gruver            return smaliMemberName.getTextOffset();
34537d1612e2f272b12d7ee556e05bb92f0e1a940b8Ben Gruver        }
34637d1612e2f272b12d7ee556e05bb92f0e1a940b8Ben Gruver        return super.getTextOffset();
34737d1612e2f272b12d7ee556e05bb92f0e1a940b8Ben Gruver    }
34844a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver
34944a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver    @Nullable @Override public PsiAnnotationMemberValue getDefaultValue() {
35044a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver        SmaliClass containingClass = getContainingClass();
35144a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver        if (containingClass == null || !containingClass.isAnnotationType()) {
35244a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver            return null;
35344a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver        }
35444a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver
35544a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver        for (SmaliAnnotation annotation: containingClass.getAnnotations()) {
35644a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver            String annotationType = annotation.getQualifiedName();
35744a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver            if (annotationType == null) {
35844a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver                continue;
35944a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver            }
36044a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver            if (annotationType.equals("dalvik.annotation.AnnotationDefault")) {
36144a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver                PsiAnnotationMemberValue value = annotation.findAttributeValue("value");
36244a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver                if (!(value instanceof SmaliAnnotation)) {
36344a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver                    return null;
36444a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver                }
36544a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver                SmaliAnnotation valueSubAnnotation = (SmaliAnnotation)value;
36644a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver                return valueSubAnnotation.findAttributeValue(getName());
36744a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver            }
36844a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver        }
36944a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver        return null;
37044a0c9091ff58228a57bcd5ae5c0eceb8d223f36Ben Gruver    }
3714a75c556bb149d754864c4c0c3ae2a94f3736dd1Ben Gruver}
372