blob: c23763fcce3ca2c94f4e5c08add67ba446b16f17 [file] [log] [blame]
Ben Gruver010b0fb2014-03-20 22:57:32 -07001/*
2 * Copyright 2014, 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
32package org.jf.smalidea.psi.impl;
33
34import com.intellij.lang.ASTNode;
Ben Gruver2ab03ae2014-12-31 14:28:47 -080035import com.intellij.openapi.command.WriteCommandAction;
Ben Gruver3505b352015-02-18 20:04:58 -080036import com.intellij.psi.PsiElement;
Ben Gruver010b0fb2014-03-20 22:57:32 -070037import com.intellij.psi.PsiModifier.ModifierConstant;
38import com.intellij.psi.PsiModifierList;
39import com.intellij.psi.PsiModifierListOwner;
40import com.intellij.psi.StubBasedPsiElement;
41import com.intellij.psi.impl.source.tree.Factory;
42import com.intellij.psi.impl.source.tree.TreeElement;
Ben Gruver010b0fb2014-03-20 22:57:32 -070043import com.intellij.util.IncorrectOperationException;
44import org.jetbrains.annotations.NonNls;
45import org.jetbrains.annotations.NotNull;
46import org.jetbrains.annotations.Nullable;
47import org.jf.dexlib2.AccessFlags;
48import org.jf.smalidea.SmaliTokens;
49import org.jf.smalidea.psi.iface.SmaliModifierListOwner;
50import org.jf.smalidea.psi.stub.SmaliModifierListStub;
51import org.jf.smalidea.psi.stub.element.SmaliModifierListElementType;
52
53import javax.annotation.Nonnull;
54
55public class SmaliModifierList extends SmaliStubBasedPsiElement<SmaliModifierListStub>
56 implements StubBasedPsiElement<SmaliModifierListStub>, PsiModifierList {
57 public SmaliModifierList(@NotNull ASTNode node) {
58 super(node);
59 }
60
61 public SmaliModifierList(@NotNull SmaliModifierListStub stub) {
62 super(stub, SmaliModifierListElementType.INSTANCE);
63 }
64
Ben Gruver010b0fb2014-03-20 22:57:32 -070065 public int getAccessFlags() {
66 SmaliModifierListStub stub = getStub();
67 if (stub != null) {
68 return stub.getAccessFlags();
69 }
70
Ben Gruver010b0fb2014-03-20 22:57:32 -070071 int flags = 0;
Ben Gruver3505b352015-02-18 20:04:58 -080072
73 for (PsiElement accessSpec: findChildrenByType(SmaliTokens.ACCESS_SPEC)) {
74 AccessFlags flag = AccessFlags.getAccessFlag(accessSpec.getText());
Ben Gruver010b0fb2014-03-20 22:57:32 -070075 if (flag != null) {
76 flags |= flag.getValue();
77 }
78 }
79
80 return flags;
81 }
82
83 @Override public boolean hasModifierProperty(@ModifierConstant @NotNull @NonNls String name) {
84 return hasExplicitModifier(name);
85 }
86
87 @Override public boolean hasExplicitModifier(@ModifierConstant @NotNull @NonNls String name) {
88 SmaliModifierListStub stub = getStub();
89 if (stub != null) {
90 AccessFlags flag = AccessFlags.getAccessFlag(name);
91 if (flag == null) {
92 return false;
93 }
94 return (stub.getAccessFlags() & flag.getValue()) != 0;
95 }
96
Ben Gruver3505b352015-02-18 20:04:58 -080097 for (PsiElement accessSpec: findChildrenByType(SmaliTokens.ACCESS_SPEC)) {
98 if (accessSpec.getText().equals(name)) {
Ben Gruver010b0fb2014-03-20 22:57:32 -070099 return true;
100 }
101 }
102
103 return false;
104 }
105
106 @Override
107 public void setModifierProperty(@ModifierConstant @NotNull @NonNls String name, boolean addModifier)
108 throws IncorrectOperationException {
109 if (addModifier) {
Ben Gruver3505b352015-02-18 20:04:58 -0800110
Ben Gruver2ab03ae2014-12-31 14:28:47 -0800111 final TreeElement leaf = Factory.createSingleLeafElement(SmaliTokens.ACCESS_SPEC, name, null, getManager());
112
113 new WriteCommandAction.Simple(getProject(), getContainingFile()) {
114 @Override protected void run() throws Throwable {
Ben Gruver3505b352015-02-18 20:04:58 -0800115 addInternal(leaf, leaf, null, null);
Ben Gruver2ab03ae2014-12-31 14:28:47 -0800116 }
117 }.execute();
Ben Gruver010b0fb2014-03-20 22:57:32 -0700118 } else {
Ben Gruver3505b352015-02-18 20:04:58 -0800119 final PsiElement accessSpec = getAccessFlagElement(name);
Ben Gruver010b0fb2014-03-20 22:57:32 -0700120 if (accessSpec != null) {
Ben Gruver2ab03ae2014-12-31 14:28:47 -0800121 new WriteCommandAction.Simple(getProject(), getContainingFile()) {
122 @Override protected void run() throws Throwable {
Ben Gruver3505b352015-02-18 20:04:58 -0800123 accessSpec.delete();
Ben Gruver2ab03ae2014-12-31 14:28:47 -0800124 }
125 }.execute();
Ben Gruver010b0fb2014-03-20 22:57:32 -0700126 }
127 }
128 }
129
130 @Override
131 public void checkSetModifierProperty(@ModifierConstant @NotNull @NonNls String name, boolean addModifier)
132 throws IncorrectOperationException {
133 }
134
135 @Nonnull
136 private SmaliModifierListOwner getParentForAnnotations() {
137 SmaliModifierListOwner parent = (SmaliModifierListOwner)getStubOrPsiParentOfType(PsiModifierListOwner.class);
138 assert parent != null;
139 return parent;
140 }
141
142 @NotNull @Override public SmaliAnnotation[] getAnnotations() {
143 return getParentForAnnotations().getAnnotations();
144 }
145
146 @NotNull @Override public SmaliAnnotation[] getApplicableAnnotations() {
147 return getParentForAnnotations().getApplicableAnnotations();
148 }
149
150 @Nullable @Override public SmaliAnnotation findAnnotation(@NotNull @NonNls String qualifiedName) {
151 return getParentForAnnotations().findAnnotation(qualifiedName);
152 }
153
154 @NotNull @Override public SmaliAnnotation addAnnotation(@NotNull @NonNls String qualifiedName) {
155 return getParentForAnnotations().addAnnotation(qualifiedName);
156 }
Ben Gruver3505b352015-02-18 20:04:58 -0800157
158 @Nullable public PsiElement getAccessFlagElement(@NotNull String accessFlag) {
159 for (PsiElement accessSpec: findChildrenByType(SmaliTokens.ACCESS_SPEC)) {
160 if (accessSpec.getText().equals(accessFlag)) {
161 return accessSpec;
162 }
163 }
164 return null;
165 }
Ben Gruver010b0fb2014-03-20 22:57:32 -0700166}