1 /* 2 * Copyright (C) 2011 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.lint.detector.api; 18 19 import com.android.annotations.NonNull; 20 import com.android.annotations.Nullable; 21 import com.android.tools.lint.client.api.Configuration; 22 import com.google.common.annotations.Beta; 23 24 import java.util.EnumSet; 25 26 27 /** 28 * An issue is a potential bug in an Android application. An issue is discovered 29 * by a {@link Detector}, and has an associated {@link Severity}. 30 * <p> 31 * Issues and detectors are separate classes because a detector can discover 32 * multiple different issues as it's analyzing code, and we want to be able to 33 * different severities for different issues, the ability to suppress one but 34 * not other issues from the same detector, and so on. 35 * <p/> 36 * <b>NOTE: This is not a public or final API; if you rely on this be prepared 37 * to adjust your code for the next tools release.</b> 38 */ 39 @Beta 40 public final class Issue implements Comparable<Issue> { 41 private final String mId; 42 private final String mDescription; 43 private final String mExplanation; 44 private final Category mCategory; 45 private final int mPriority; 46 private final Severity mSeverity; 47 private String mMoreInfoUrl; 48 private boolean mEnabledByDefault = true; 49 private final EnumSet<Scope> mScope; 50 private final Class<? extends Detector> mClass; 51 52 // Use factory methods 53 private Issue( 54 @NonNull String id, 55 @NonNull String description, 56 @NonNull String explanation, 57 @NonNull Category category, 58 int priority, 59 @NonNull Severity severity, 60 @NonNull Class<? extends Detector> detectorClass, 61 @NonNull EnumSet<Scope> scope) { 62 super(); 63 mId = id; 64 mDescription = description; 65 mExplanation = explanation; 66 mCategory = category; 67 mPriority = priority; 68 mSeverity = severity; 69 mClass = detectorClass; 70 mScope = scope; 71 } 72 73 /** 74 * Creates a new issue 75 * 76 * @param id the fixed id of the issue 77 * @param description the quick summary of the issue (one line) 78 * @param explanation a full explanation of the issue, with suggestions for 79 * how to fix it 80 * @param category the associated category, if any 81 * @param priority the priority, a number from 1 to 10 with 10 being most 82 * important/severe 83 * @param severity the default severity of the issue 84 * @param detectorClass the class of the detector to find this issue 85 * @param scope the scope of files required to analyze this issue 86 * @return a new {@link Issue} 87 */ 88 @NonNull 89 public static Issue create( 90 @NonNull String id, 91 @NonNull String description, 92 @NonNull String explanation, 93 @NonNull Category category, 94 int priority, 95 @NonNull Severity severity, 96 @NonNull Class<? extends Detector> detectorClass, 97 @NonNull EnumSet<Scope> scope) { 98 return new Issue(id, description, explanation, category, priority, severity, 99 detectorClass, scope); 100 } 101 102 /** 103 * Returns the unique id of this issue. These should not change over time 104 * since they are used to persist the names of issues suppressed by the user 105 * etc. It is typically a single camel-cased word. 106 * 107 * @return the associated fixed id, never null and always unique 108 */ 109 @NonNull 110 public String getId() { 111 return mId; 112 } 113 114 /** 115 * Briefly (one line) describes the kinds of checks performed by this rule 116 * 117 * @return a quick summary of the issue, never null 118 */ 119 @NonNull 120 public String getDescription() { 121 return mDescription; 122 } 123 124 /** 125 * Describes the error found by this rule, e.g. 126 * "Buttons must define contentDescriptions". Preferably the explanation 127 * should also contain a description of how the problem should be solved. 128 * Additional info can be provided via {@link #getMoreInfo()}. 129 * 130 * @return an explanation of the issue, never null. 131 */ 132 @NonNull 133 public String getExplanation() { 134 return mExplanation; 135 } 136 137 /** 138 * The primary category of the issue 139 * 140 * @return the primary category of the issue, never null 141 */ 142 @NonNull 143 public Category getCategory() { 144 return mCategory; 145 } 146 147 /** 148 * Returns a priority, in the range 1-10, with 10 being the most severe and 149 * 1 the least 150 * 151 * @return a priority from 1 to 10 152 */ 153 public int getPriority() { 154 return mPriority; 155 } 156 157 /** 158 * Returns the default severity of the issues found by this detector (some 159 * tools may allow the user to specify custom severities for detectors). 160 * <p> 161 * Note that even though the normal way for an issue to be disabled is for 162 * the {@link Configuration} to return {@link Severity#IGNORE}, there is a 163 * {@link #isEnabledByDefault()} method which can be used to turn off issues 164 * by default. This is done rather than just having the severity as the only 165 * attribute on the issue such that an issue can be configured with an 166 * appropriate severity (such as {@link Severity#ERROR}) even when issues 167 * are disabled by default for example because they are experimental or not 168 * yet stable. 169 * 170 * @return the severity of the issues found by this detector 171 */ 172 @NonNull 173 public Severity getDefaultSeverity() { 174 return mSeverity; 175 } 176 177 /** 178 * Returns a link (a URL string) to more information, or null 179 * 180 * @return a link to more information, or null 181 */ 182 @Nullable 183 public String getMoreInfo() { 184 return mMoreInfoUrl; 185 } 186 187 /** 188 * Returns whether this issue should be enabled by default, unless the user 189 * has explicitly disabled it. 190 * 191 * @return true if this issue should be enabled by default 192 */ 193 public boolean isEnabledByDefault() { 194 return mEnabledByDefault; 195 } 196 197 /** 198 * Returns the scope required to analyze the code to detect this issue. 199 * This is determined by the detectors which reports the issue. 200 * 201 * @return the required scope 202 */ 203 @NonNull 204 public EnumSet<Scope> getScope() { 205 return mScope; 206 } 207 208 /** 209 * Sorts the detectors alphabetically by id. This is intended to make it 210 * convenient to store settings for detectors in a fixed order. It is not 211 * intended as the order to be shown to the user; for that, a tool embedding 212 * lint might consider the priorities, categories, severities etc of the 213 * various detectors. 214 * 215 * @param other the {@link Issue} to compare this issue to 216 */ 217 @Override 218 public int compareTo(@NonNull Issue other) { 219 return getId().compareTo(other.getId()); 220 } 221 222 /** 223 * Sets a more info URL string 224 * 225 * @param moreInfoUrl url string 226 * @return this, for constructor chaining 227 */ 228 @NonNull 229 public Issue setMoreInfo(@NonNull String moreInfoUrl) { 230 mMoreInfoUrl = moreInfoUrl; 231 return this; 232 } 233 234 /** 235 * Sets whether this issue is enabled by default. 236 * 237 * @param enabledByDefault whether the issue should be enabled by default 238 * @return this, for constructor chaining 239 */ 240 @NonNull 241 public Issue setEnabledByDefault(boolean enabledByDefault) { 242 mEnabledByDefault = enabledByDefault; 243 return this; 244 } 245 246 /** 247 * Returns the class of the detector to use to find this issue 248 * 249 * @return the class of the detector to use to find this issue 250 */ 251 @NonNull 252 public Class<? extends Detector> getDetectorClass() { 253 return mClass; 254 } 255 256 @Override 257 public String toString() { 258 return mId; 259 } 260 } 261