Home | History | Annotate | Download | only in checks
      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.checks;
     18 
     19 import static com.android.tools.lint.detector.api.LintConstants.ABSOLUTE_LAYOUT;
     20 import static com.android.tools.lint.detector.api.LintConstants.ANDROID_URI;
     21 import static com.android.tools.lint.detector.api.LintConstants.ATTR_AUTO_TEXT;
     22 import static com.android.tools.lint.detector.api.LintConstants.ATTR_CAPITALIZE;
     23 import static com.android.tools.lint.detector.api.LintConstants.ATTR_EDITABLE;
     24 import static com.android.tools.lint.detector.api.LintConstants.ATTR_ENABLED;
     25 import static com.android.tools.lint.detector.api.LintConstants.ATTR_INPUT_METHOD;
     26 import static com.android.tools.lint.detector.api.LintConstants.ATTR_NUMERIC;
     27 import static com.android.tools.lint.detector.api.LintConstants.ATTR_PASSWORD;
     28 import static com.android.tools.lint.detector.api.LintConstants.ATTR_PHONE_NUMBER;
     29 import static com.android.tools.lint.detector.api.LintConstants.ATTR_SINGLE_LINE;
     30 
     31 import com.android.tools.lint.detector.api.Category;
     32 import com.android.tools.lint.detector.api.Issue;
     33 import com.android.tools.lint.detector.api.LayoutDetector;
     34 import com.android.tools.lint.detector.api.Scope;
     35 import com.android.tools.lint.detector.api.Severity;
     36 import com.android.tools.lint.detector.api.Speed;
     37 import com.android.tools.lint.detector.api.XmlContext;
     38 
     39 import org.w3c.dom.Attr;
     40 import org.w3c.dom.Element;
     41 
     42 import java.util.Arrays;
     43 import java.util.Collection;
     44 import java.util.Collections;
     45 
     46 /**
     47  * Check which looks for usage of deprecated tags, attributes, etc.
     48  */
     49 public class DeprecationDetector extends LayoutDetector {
     50     /** Usage of deprecated views or attributes */
     51     public static final Issue ISSUE = Issue.create(
     52             "Deprecated", //$NON-NLS-1$
     53             "Looks for usages of deprecated layouts, attributes, and so on.",
     54             "Deprecated views, attributes and so on are deprecated because there " +
     55             "is a better way to do something. Do it that new way. You've been warned.",
     56             Category.CORRECTNESS,
     57             2,
     58             Severity.WARNING,
     59             DeprecationDetector.class,
     60             Scope.RESOURCE_FILE_SCOPE);
     61 
     62     /** Constructs a new {@link DeprecationDetector} */
     63     public DeprecationDetector() {
     64     }
     65 
     66     @Override
     67     public Speed getSpeed() {
     68         return Speed.FAST;
     69     }
     70 
     71     @Override
     72     public Collection<String> getApplicableElements() {
     73         return Collections.singletonList(
     74                 ABSOLUTE_LAYOUT
     75         );
     76     }
     77 
     78     @Override
     79     public Collection<String> getApplicableAttributes() {
     80         return Arrays.asList(
     81                 // TODO: fill_parent is deprecated as of API 8.
     82                 // We could warn about it, but it will probably be very noisy
     83                 // and make people disable the deprecation check; let's focus on
     84                 // some older flags for now
     85                 //"fill_parent",
     86 
     87                 ATTR_EDITABLE,
     88                 ATTR_INPUT_METHOD,
     89                 ATTR_AUTO_TEXT,
     90                 ATTR_CAPITALIZE,
     91 
     92                 // This flag is still used a lot and is still properly handled by TextView
     93                 // so in the interest of not being too noisy and make people ignore all the
     94                 // output, keep quiet about this one -for now-.
     95                 //ATTR_SINGLE_LINE,
     96 
     97                 // This attribute is marked deprecated in android.R.attr but apparently
     98                 // using the suggested replacement of state_enabled doesn't work, see issue 27613
     99                 //ATTR_ENABLED,
    100 
    101                 ATTR_NUMERIC,
    102                 ATTR_PHONE_NUMBER,
    103                 ATTR_PASSWORD
    104 
    105                 // These attributes are also deprecated; not yet enabled until we
    106                 // know the API level to apply the deprecation for:
    107 
    108                 // "ignored as of ICS (but deprecated earlier)"
    109                 //"fadingEdge",
    110 
    111                 // "This attribute is not used by the Android operating system."
    112                 //"restoreNeedsApplication",
    113 
    114                 // "This will create a non-standard UI appearance, because the search bar UI is
    115                 // changing to use only icons for its buttons."
    116                 //"searchButtonText",
    117 
    118         );
    119     }
    120 
    121     @Override
    122     public void visitElement(XmlContext context, Element element) {
    123         context.report(ISSUE, element, context.getLocation(element),
    124                 String.format("%1$s is deprecated", element.getTagName()), null);
    125     }
    126 
    127     @Override
    128     public void visitAttribute(XmlContext context, Attr attribute) {
    129         if (!ANDROID_URI.equals(attribute.getNamespaceURI())) {
    130             return;
    131         }
    132 
    133         String name = attribute.getLocalName();
    134         String fix;
    135         int minSdk = 1;
    136         if (name.equals(ATTR_EDITABLE)) {
    137             fix = "Use an <EditText> to make it editable";
    138         } else if (name.equals(ATTR_ENABLED)) {
    139             fix = "Use state_enabled instead";
    140         } else if (name.equals(ATTR_SINGLE_LINE)) {
    141             fix = "Use maxLines=\"1\" instead";
    142         } else {
    143             assert name.equals(ATTR_INPUT_METHOD)
    144                 || name.equals(ATTR_CAPITALIZE)
    145                 || name.equals(ATTR_NUMERIC)
    146                 || name.equals(ATTR_PHONE_NUMBER)
    147                 || name.equals(ATTR_PASSWORD)
    148                 || name.equals(ATTR_AUTO_TEXT);
    149             fix = "Use inputType instead";
    150             // The inputType attribute was introduced in API 3 so don't warn about
    151             // deprecation if targeting older platforms
    152             minSdk = 3;
    153         }
    154 
    155         if (context.getProject().getMinSdk() < minSdk) {
    156             return;
    157         }
    158 
    159         context.report(ISSUE, attribute, context.getLocation(attribute),
    160                 String.format("%1$s is deprecated: %2$s",
    161                         attribute.getName(), fix), null);
    162     }
    163 }
    164