• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tools.idea.validator;
18 
19 import com.android.tools.layoutlib.annotations.NotNull;
20 import com.android.tools.layoutlib.annotations.Nullable;
21 
22 import java.util.EnumSet;
23 import java.util.HashSet;
24 import java.util.List;
25 
26 import com.google.android.apps.common.testing.accessibility.framework.AccessibilityHierarchyCheck;
27 
28 /**
29  * Data used for layout validation.
30  */
31 public class ValidatorData {
32 
33     /**
34      * Category of validation
35      */
36     public enum Type {
37         ACCESSIBILITY,
38         RENDER,
39         INTERNAL_ERROR
40     }
41 
42     /**
43      * Level of importance
44      */
45     public enum Level {
46         ERROR,
47         WARNING,
48         INFO,
49         /** The test not ran or suppressed. */
50         VERBOSE,
51     }
52 
53     /**
54      * Determine what types and levels of validation to run.
55      */
56     public static class Policy {
57         /** Sets of types to filter by. */
58         @NotNull public final EnumSet<Type> mTypes;
59         /** Sets of levels to filter by. */
60         @NotNull public final EnumSet<Level> mLevels;
61         /**
62          * List of checks to use for the scan. If empty we use the default set
63          * defined by {@link AccessibilityCheckPreset.LATEST}
64          */
65         @NotNull public final HashSet<AccessibilityHierarchyCheck> mChecks = new HashSet();
66 
Policy(@otNull EnumSet<Type> types, @NotNull EnumSet<Level> levels)67         public Policy(@NotNull EnumSet<Type> types, @NotNull EnumSet<Level> levels) {
68             mTypes = types;
69             mLevels = levels;
70         }
71     }
72 
73     /**
74      * Issue describing the layout problem.
75      */
76     public static class Issue {
77         @NotNull
78         public final String mCategory;
79         @NotNull
80         public final Type mType;
81         @NotNull
82         public final String mMsg;
83         @NotNull
84         public final Level mLevel;
85         @Nullable
86         public final Long mSrcId;
87         @Nullable
88         public final Fix mFix;
89         @NotNull
90         public final String mSourceClass;
91         @Nullable
92         public final String mHelpfulUrl;
93 
Issue( @otNull String category, @NotNull Type type, @NotNull String msg, @NotNull Level level, @Nullable Long srcId, @Nullable Fix fix, @NotNull String sourceClass, @Nullable String helpfulUrl)94         private Issue(
95                 @NotNull String category,
96                 @NotNull Type type,
97                 @NotNull String msg,
98                 @NotNull Level level,
99                 @Nullable Long srcId,
100                 @Nullable Fix fix,
101                 @NotNull String sourceClass,
102                 @Nullable String helpfulUrl) {
103             mCategory = category;
104             mType = type;
105             mMsg = msg;
106             mLevel = level;
107             mSrcId = srcId;
108             mFix = fix;
109             mSourceClass = sourceClass;
110             mHelpfulUrl = helpfulUrl;
111         }
112 
113         public static class IssueBuilder {
114             private String mCategory;
115             private Type mType = Type.ACCESSIBILITY;
116             private String mMsg;
117             private Level mLevel;
118             private Long mSrcId;
119             private Fix mFix;
120             private String mSourceClass;
121             private String mHelpfulUrl;
122 
setCategory(String category)123             public IssueBuilder setCategory(String category) {
124                 mCategory = category;
125                 return this;
126             }
127 
setType(Type type)128             public IssueBuilder setType(Type type) {
129                 mType = type;
130                 return this;
131             }
132 
setMsg(String msg)133             public IssueBuilder setMsg(String msg) {
134                 mMsg = msg;
135                 return this;
136             }
137 
setLevel(Level level)138             public IssueBuilder setLevel(Level level) {
139                 mLevel = level;
140                 return this;
141             }
142 
setSrcId(Long srcId)143             public IssueBuilder setSrcId(Long srcId) {
144                 mSrcId = srcId;
145                 return this;
146             }
147 
setFix(Fix fix)148             public IssueBuilder setFix(Fix fix) {
149                 mFix = fix;
150                 return this;
151             }
152 
setSourceClass(String sourceClass)153             public IssueBuilder setSourceClass(String sourceClass) {
154                 mSourceClass = sourceClass;
155                 return this;
156             }
157 
setHelpfulUrl(String url)158             public IssueBuilder setHelpfulUrl(String url) {
159                 mHelpfulUrl = url;
160                 return this;
161             }
162 
build()163             public Issue build() {
164                 assert(mCategory != null);
165                 assert(mType != null);
166                 assert(mMsg != null);
167                 assert(mLevel != null);
168                 assert(mSourceClass != null);
169                 return new Issue(mCategory,
170                         mType,
171                         mMsg,
172                         mLevel,
173                         mSrcId,
174                         mFix,
175                         mSourceClass,
176                         mHelpfulUrl);
177             }
178         }
179     }
180 
181     /**
182      * Represents a view attribute which contains a namespace and an attribute name.
183      */
184     public static class ViewAttribute {
185         /** The namespace used in XML files for this view attribute. */
186         @NotNull public final String mNamespaceUri;
187         /** The namespace of this view attribute. */
188         @NotNull public final String mNamespace;
189         /** The attribute name of this view attribute. */
190         @NotNull public final String mAttributeName;
191 
ViewAttribute( @otNull String namespaceUri, @NotNull String namespace, @NotNull String attributeName)192         public ViewAttribute(
193                 @NotNull String namespaceUri,
194                 @NotNull String namespace,
195                 @NotNull String attributeName) {
196             mNamespaceUri = namespaceUri;
197             mNamespace = namespace;
198             mAttributeName = attributeName;
199         }
200     }
201 
202     /**
203      * Suggested fix to the user or to the studio.
204      */
205     public static interface Fix {
206         /**
207          * @return a human-readable description for this fix.
208          */
getDescription()209         @NotNull String getDescription();
210     }
211 
212     /**
213      * Suggest setting a value to a {@link ViewAttribute} to fix a specific {@link Issue}.
214      *
215      * <ul>
216      *   <li>If the view attribute has not been set before, add the view attribute and set its value
217      *       to the suggested value.
218      *   <li>If the view attribute has been set before, replace its value with the suggested value.
219      *   <li>If the suggested value is an empty string, ask the developer to set the view attribute
220      *       to a meaningful non-empty string or resource reference. DO NOT set the view attribute
221      *       to an empty string.
222      * </ul>
223      */
224     public static class SetViewAttributeFix implements Fix {
225         /** The {@link ViewAttribute} suggested to be changed. */
226         @NotNull public final ViewAttribute mViewAttribute;
227 
228         /** The suggested value of the {@link ViewAttribute} suggested to be changed. */
229         @NotNull public final String mSuggestedValue;
230 
231         @NotNull private final String mDescription;
232 
SetViewAttributeFix(@otNull ViewAttribute viewAttribute, @NotNull String suggestedValue, @NotNull String description)233         public SetViewAttributeFix(@NotNull ViewAttribute viewAttribute,
234                 @NotNull String suggestedValue, @NotNull String description) {
235             mViewAttribute = viewAttribute;
236             mSuggestedValue = suggestedValue;
237             mDescription = description;
238         }
239 
240         @Override
getDescription()241         @NotNull public String getDescription() {
242             return mDescription;
243         }
244     }
245 
246     /**
247      * Suggest removing a {@link ViewAttribute} to fix a specific {@link Issue}.
248      */
249     public static class RemoveViewAttributeFix implements Fix {
250         /** The {@link ViewAttribute} suggested to be removed. */
251         @NotNull public final ViewAttribute mViewAttribute;
252 
253         @NotNull private final String mDescription;
254 
RemoveViewAttributeFix(@otNull ViewAttribute viewAttribute, @NotNull String description)255         public RemoveViewAttributeFix(@NotNull ViewAttribute viewAttribute,
256                 @NotNull String description) {
257             mViewAttribute = viewAttribute;
258             mDescription = description;
259         }
260 
261         @Override
getDescription()262         @NotNull public String getDescription() {
263             return mDescription;
264         }
265     }
266 
267     /**
268      * Suggest applying multiple {@link Fix} together to fix a specific {@link Issue}.
269      *
270      * <p>A {@link CompoundFix} must contain at least 2 {@link Fix}.
271      */
272     public static class CompoundFix implements Fix {
273         /** Lists of {@link Fix} suggested to be applied together. */
274         @NotNull public final List<Fix> mFixes;
275 
276         @NotNull private final String mDescription;
277 
CompoundFix(@otNull List<Fix> fixes, String description)278         public CompoundFix(@NotNull List<Fix> fixes, String description) {
279             mFixes = fixes;
280             mDescription = description;
281         }
282 
283         @Override
getDescription()284         @NotNull public String getDescription() {
285             return mDescription;
286         }
287     }
288 }
289