aboutsummaryrefslogtreecommitdiffstats
path: root/lint/libs/lint_checks/src/com/android/tools/lint/checks/DeprecationDetector.java
blob: 00953d89dec7b9c213484572cc233a6632432ba0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.tools.lint.checks;

import static com.android.SdkConstants.ABSOLUTE_LAYOUT;
import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_AUTO_TEXT;
import static com.android.SdkConstants.ATTR_CAPITALIZE;
import static com.android.SdkConstants.ATTR_EDITABLE;
import static com.android.SdkConstants.ATTR_ENABLED;
import static com.android.SdkConstants.ATTR_INPUT_METHOD;
import static com.android.SdkConstants.ATTR_NUMERIC;
import static com.android.SdkConstants.ATTR_PASSWORD;
import static com.android.SdkConstants.ATTR_PHONE_NUMBER;
import static com.android.SdkConstants.ATTR_SINGLE_LINE;

import com.android.annotations.NonNull;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.LayoutDetector;
import com.android.tools.lint.detector.api.Scope;
import com.android.tools.lint.detector.api.Severity;
import com.android.tools.lint.detector.api.Speed;
import com.android.tools.lint.detector.api.XmlContext;

import org.w3c.dom.Attr;
import org.w3c.dom.Element;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;

/**
 * Check which looks for usage of deprecated tags, attributes, etc.
 */
public class DeprecationDetector extends LayoutDetector {
    /** Usage of deprecated views or attributes */
    public static final Issue ISSUE = Issue.create(
            "Deprecated", //$NON-NLS-1$
            "Looks for usages of deprecated layouts, attributes, and so on.",
            "Deprecated views, attributes and so on are deprecated because there " +
            "is a better way to do something. Do it that new way. You've been warned.",
            Category.CORRECTNESS,
            2,
            Severity.WARNING,
            DeprecationDetector.class,
            Scope.RESOURCE_FILE_SCOPE);

    /** Constructs a new {@link DeprecationDetector} */
    public DeprecationDetector() {
    }

    @Override
    public @NonNull Speed getSpeed() {
        return Speed.FAST;
    }

    @Override
    public Collection<String> getApplicableElements() {
        return Collections.singletonList(
                ABSOLUTE_LAYOUT
        );
    }

    @Override
    public Collection<String> getApplicableAttributes() {
        return Arrays.asList(
                // TODO: fill_parent is deprecated as of API 8.
                // We could warn about it, but it will probably be very noisy
                // and make people disable the deprecation check; let's focus on
                // some older flags for now
                //"fill_parent",

                ATTR_EDITABLE,
                ATTR_INPUT_METHOD,
                ATTR_AUTO_TEXT,
                ATTR_CAPITALIZE,

                // This flag is still used a lot and is still properly handled by TextView
                // so in the interest of not being too noisy and make people ignore all the
                // output, keep quiet about this one -for now-.
                //ATTR_SINGLE_LINE,

                // This attribute is marked deprecated in android.R.attr but apparently
                // using the suggested replacement of state_enabled doesn't work, see issue 27613
                //ATTR_ENABLED,

                ATTR_NUMERIC,
                ATTR_PHONE_NUMBER,
                ATTR_PASSWORD

                // These attributes are also deprecated; not yet enabled until we
                // know the API level to apply the deprecation for:

                // "ignored as of ICS (but deprecated earlier)"
                //"fadingEdge",

                // "This attribute is not used by the Android operating system."
                //"restoreNeedsApplication",

                // "This will create a non-standard UI appearance, because the search bar UI is
                // changing to use only icons for its buttons."
                //"searchButtonText",

        );
    }

    @Override
    public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
        context.report(ISSUE, element, context.getLocation(element),
                String.format("%1$s is deprecated", element.getTagName()), null);
    }

    @Override
    public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) {
        if (!ANDROID_URI.equals(attribute.getNamespaceURI())) {
            return;
        }

        String name = attribute.getLocalName();
        String fix;
        int minSdk = 1;
        if (name.equals(ATTR_EDITABLE)) {
            fix = "Use an <EditText> to make it editable";
        } else if (name.equals(ATTR_ENABLED)) {
            fix = "Use state_enabled instead";
        } else if (name.equals(ATTR_SINGLE_LINE)) {
            fix = "Use maxLines=\"1\" instead";
        } else {
            assert name.equals(ATTR_INPUT_METHOD)
                || name.equals(ATTR_CAPITALIZE)
                || name.equals(ATTR_NUMERIC)
                || name.equals(ATTR_PHONE_NUMBER)
                || name.equals(ATTR_PASSWORD)
                || name.equals(ATTR_AUTO_TEXT);
            fix = "Use inputType instead";
            // The inputType attribute was introduced in API 3 so don't warn about
            // deprecation if targeting older platforms
            minSdk = 3;
        }

        if (context.getProject().getMinSdk() < minSdk) {
            return;
        }

        context.report(ISSUE, attribute, context.getLocation(attribute),
                String.format("%1$s is deprecated: %2$s",
                        attribute.getName(), fix), null);
    }
}