Skip to content

Commit a66852d

Browse files
committed
Move to 25.2.3 for the lint deps
Remove the requirement to use java 6
1 parent dccc9c5 commit a66852d

File tree

5 files changed

+346
-12
lines changed

5 files changed

+346
-12
lines changed

build.gradle

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ apply plugin: 'java'
1818

1919
repositories {
2020
jcenter()
21+
maven {
22+
url "http://dl.bintray.com/android/android-tools"
23+
}
2124
}
2225

23-
// JDK 1.6 is required to support all versions of Android Studio.
24-
// See http://tools.android.com/build/studio.
25-
sourceCompatibility = 1.6
2626
dependencies {
27-
compile 'com.android.tools.lint:lint-api:24.3.1'
28-
compile 'com.android.tools.lint:lint-checks:24.3.1'
27+
compile 'com.android.tools.lint:lint-api:25.2.3'
28+
compile 'com.android.tools.lint:lint-checks:25.2.3'
2929
testCompile 'junit:junit:4.11'
30-
testCompile 'com.android.tools.lint:lint:24.3.1'
31-
testCompile 'com.android.tools.lint:lint-tests:24.3.1'
32-
testCompile 'com.android.tools:testutils:24.3.1'
30+
testCompile 'com.android.tools.lint:lint:25.2.3'
31+
testCompile 'com.android.tools.lint:lint-tests:25.2.3'
32+
testCompile 'com.android.tools:testutils:25.2.3'
3333
}
3434

3535
jar {

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip

src/main/java/com/example/google/lint/MainActivityDetector.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,16 @@
2828
import com.android.tools.lint.detector.api.Scope;
2929
import com.android.tools.lint.detector.api.Severity;
3030
import com.android.tools.lint.detector.api.XmlContext;
31-
3231
import org.w3c.dom.Element;
3332
import org.w3c.dom.Node;
3433

3534
import java.util.Collection;
3635
import java.util.Collections;
37-
import java.util.EnumSet;
3836

3937
import static com.android.SdkConstants.ANDROID_MANIFEST_XML;
4038
import static com.android.SdkConstants.ANDROID_URI;
4139
import static com.android.SdkConstants.ATTR_NAME;
4240
import static com.android.SdkConstants.TAG_ACTIVITY;
43-
import static com.android.SdkConstants.TAG_APPLICATION;
4441
import static com.android.SdkConstants.TAG_INTENT_FILTER;
4542
import static com.android.xml.AndroidManifest.NODE_ACTION;
4643
import static com.android.xml.AndroidManifest.NODE_CATEGORY;
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* Copyright (C) 2015 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.example.google.lint;
18+
19+
import com.android.annotations.NonNull;
20+
import com.android.tools.lint.detector.api.Category;
21+
import com.android.tools.lint.detector.api.Context;
22+
import com.android.tools.lint.detector.api.Detector;
23+
import com.android.tools.lint.detector.api.Implementation;
24+
import com.android.tools.lint.detector.api.Issue;
25+
import com.android.tools.lint.detector.api.LintUtils;
26+
import com.android.tools.lint.detector.api.Location;
27+
import com.android.tools.lint.detector.api.ResourceXmlDetector;
28+
import com.android.tools.lint.detector.api.Scope;
29+
import com.android.tools.lint.detector.api.Severity;
30+
import com.android.tools.lint.detector.api.XmlContext;
31+
32+
import org.w3c.dom.Element;
33+
import org.w3c.dom.Node;
34+
35+
import java.util.Collection;
36+
import java.util.Collections;
37+
import java.util.EnumSet;
38+
39+
import static com.android.SdkConstants.ANDROID_MANIFEST_XML;
40+
import static com.android.SdkConstants.ANDROID_URI;
41+
import static com.android.SdkConstants.ATTR_NAME;
42+
import static com.android.SdkConstants.TAG_ACTIVITY;
43+
import static com.android.SdkConstants.TAG_APPLICATION;
44+
import static com.android.SdkConstants.TAG_INTENT_FILTER;
45+
import static com.android.xml.AndroidManifest.NODE_ACTION;
46+
import static com.android.xml.AndroidManifest.NODE_CATEGORY;
47+
import static com.example.google.lint.ManifestConstants.ACTION_NAME_MAIN;
48+
import static com.example.google.lint.ManifestConstants.CATEGORY_NAME_LAUNCHER;
49+
50+
/**
51+
* Checks for an activity with a launcher intent in <code>AndroidManifest.xml</code>.
52+
* <p/>
53+
* <b>NOTE: This is not a final API; if you rely on this be prepared
54+
* to adjust your code for the next tools release.</b>
55+
*/
56+
public class MainActivityDetector extends ResourceXmlDetector implements Detector.XmlScanner {
57+
public static final Issue ISSUE = Issue.create(
58+
"MainActivityDetector",
59+
"Missing Launcher Activities",
60+
"This app should have an activity with a launcher intent.",
61+
Category.CORRECTNESS,
62+
8,
63+
Severity.ERROR,
64+
new Implementation(
65+
MainActivityDetector.class,
66+
Scope.MANIFEST_SCOPE));
67+
68+
/**
69+
* This will be <code>true</code> if the current file we're checking has at least one activity.
70+
*/
71+
private boolean mHasActivity;
72+
/**
73+
* This will be <code>true</code> if the file has an activity with a launcher intent.
74+
*/
75+
private boolean mHasLauncherActivity;
76+
/**
77+
* The manifest file location for the main project, <code>null</code> if there is no manifest.
78+
*/
79+
private Location mManifestLocation;
80+
81+
/**
82+
* No-args constructor used by the lint framework to instantiate the detector.
83+
*/
84+
public MainActivityDetector() {
85+
}
86+
87+
@Override
88+
public Collection<String> getApplicableElements() {
89+
java.util.List<String> s = new java.util.ArrayList<String>(2);
90+
s.add(TAG_ACTIVITY);
91+
s.add("manifest");
92+
return s;
93+
}
94+
95+
@Override
96+
public void beforeCheckProject(@NonNull Context context) {
97+
mHasActivity = false;
98+
mHasLauncherActivity = false;
99+
mManifestLocation = null;
100+
}
101+
102+
@Override
103+
public void afterCheckProject(@NonNull Context context) {
104+
// Don't report issues on libraries that may not have a launcher activity
105+
if (context.getProject() == context.getMainProject()
106+
&& !context.getMainProject().isLibrary()
107+
&& mManifestLocation != null) {
108+
if (!mHasActivity) {
109+
context.report(ISSUE, mManifestLocation,
110+
"Expecting " + ANDROID_MANIFEST_XML + " to have an <" + TAG_ACTIVITY +
111+
"> tag.");
112+
} else if (!mHasLauncherActivity) {
113+
// Report the issue if the manifest file has no activity with a launcher intent.
114+
context.report(ISSUE, mManifestLocation,
115+
"Expecting " + ANDROID_MANIFEST_XML +
116+
" to have an activity with a launcher intent.");
117+
}
118+
}
119+
}
120+
121+
@Override
122+
public void afterCheckFile(@NonNull Context context) {
123+
// Store a reference to the manifest file in case we need to report it's location.
124+
if (context.getProject() == context.getMainProject()
125+
&& mManifestLocation == null) {
126+
mManifestLocation = Location.create(context.file);
127+
}
128+
}
129+
130+
@Override
131+
public void visitElement(XmlContext context, Element activityElement) {
132+
// Checks every activity and reports an error if there is no activity with a launcher
133+
// intent.
134+
mHasActivity = true;
135+
if (activityElement.getNodeName().equals("manifest")) {
136+
System.out.println("setting manifest");
137+
mManifestLocation = context.getLocation(activityElement);
138+
}
139+
if (isMainActivity(activityElement)) {
140+
mHasLauncherActivity = true;
141+
}
142+
}
143+
144+
/**
145+
* Returns true if the XML node is an activity with a launcher intent.
146+
*
147+
* @param activityNode The node to check.
148+
* @return <code>true</code> if the node is an activity with a launcher intent.
149+
*/
150+
private boolean isMainActivity(Node activityNode) {
151+
if (TAG_ACTIVITY.equals(activityNode.getNodeName())) {
152+
// Loop through all <intent-filter> tags
153+
for (Element activityChild : LintUtils.getChildren(activityNode)) {
154+
if (TAG_INTENT_FILTER.equals(activityChild.getNodeName())) {
155+
// Check for these children nodes:
156+
//
157+
// <category android:name="android.intent.category.LAUNCHER" />
158+
// <action android:name="android.intent.action.MAIN" />
159+
boolean hasLauncherCategory = false;
160+
boolean hasMainAction = false;
161+
162+
for (Element intentFilterChild : LintUtils.getChildren(activityChild)) {
163+
// Check for category tag)
164+
if (NODE_CATEGORY.equals(intentFilterChild.getNodeName())
165+
&& CATEGORY_NAME_LAUNCHER.equals(
166+
intentFilterChild.getAttributeNS(ANDROID_URI, ATTR_NAME))) {
167+
hasLauncherCategory = true;
168+
}
169+
// Check for action tag
170+
if (NODE_ACTION.equals(intentFilterChild.getNodeName())
171+
&& ACTION_NAME_MAIN.equals(
172+
intentFilterChild.getAttributeNS(ANDROID_URI, ATTR_NAME))) {
173+
hasMainAction = true;
174+
}
175+
}
176+
177+
if (hasLauncherCategory && hasMainAction) {
178+
return true;
179+
}
180+
}
181+
}
182+
}
183+
return false;
184+
}
185+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
* Copyright (C) 2015 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.example.google.lint;
18+
19+
import com.android.annotations.NonNull;
20+
import com.android.tools.lint.checks.infrastructure.LintDetectorTest;
21+
import com.android.tools.lint.client.api.LintClient;
22+
import com.android.tools.lint.detector.api.Detector;
23+
import com.android.tools.lint.detector.api.Issue;
24+
import com.android.tools.lint.detector.api.Project;
25+
26+
import java.util.Collections;
27+
import java.util.HashSet;
28+
import java.util.List;
29+
import java.util.Set;
30+
31+
import static com.android.SdkConstants.FN_ANDROID_MANIFEST_XML;
32+
33+
/**
34+
* <b>NOTE: This is not a final API; if you rely on this be prepared
35+
* to adjust your code for the next tools release.</b>
36+
*/
37+
public class MainActivityDetectorTest extends LintDetectorTest {
38+
/**
39+
* The set of enabled issues for a given test.
40+
*/
41+
private Set<Issue> mEnabled = new HashSet<Issue>();
42+
43+
@Override
44+
protected Detector getDetector() {
45+
return new MainActivityDetector();
46+
}
47+
48+
@Override
49+
protected List<Issue> getIssues() {
50+
return Collections.singletonList(MainActivityDetector.ISSUE);
51+
}
52+
53+
/**
54+
* Gets the configuration for the test.
55+
* Each test can have a set of enabled issues by assigning the member field {@link #mEnabled}.
56+
*/
57+
@Override
58+
protected TestConfiguration getConfiguration(LintClient client, Project project) {
59+
return new TestConfiguration(client, project, null) {
60+
@Override
61+
public boolean isEnabled(@NonNull Issue issue) {
62+
return super.isEnabled(issue) && mEnabled.contains(issue);
63+
}
64+
};
65+
}
66+
67+
/**
68+
* Test that a manifest with an activity with a launcher intent has no warnings.
69+
*/
70+
public void testHasMainActivity() throws Exception {
71+
mEnabled = Collections.singleton(MainActivityDetector.ISSUE);
72+
String expected = "No warnings.";
73+
String result = lintProject(xml(FN_ANDROID_MANIFEST_XML, "" +
74+
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
75+
"<manifest package=\"com.example.android.custom-lint-rules\"\n" +
76+
" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n" +
77+
" <application>\n" +
78+
" <activity android:name=\"com.example.android.custom-lint-rules" +
79+
".OtherActivity\">\n" +
80+
" </activity>\n" +
81+
"\n" +
82+
" <activity android:name=\"com.example.android.custom-lint-rules" +
83+
".MainActivity\">\n" +
84+
" <intent-filter>\n" +
85+
" <action android:name=\"android.intent.action.MAIN\"/>\n" +
86+
" <category android:name=\"android.intent.category.LAUNCHER\"/>\n" +
87+
" </intent-filter>\n" +
88+
" </activity>\n" +
89+
" </application>\n" +
90+
"</manifest>"));
91+
assertEquals(expected, result);
92+
}
93+
94+
/**
95+
* Test that a manifest <em>without</em> an activity with a launcher intent reports an error.
96+
*/
97+
public void testMissingMainActivity() throws Exception {
98+
mEnabled = Collections.singleton(MainActivityDetector.ISSUE);
99+
String expected = "AndroidManifest.xml: Error: Expecting AndroidManifest.xml to have an " +
100+
"activity with a launcher intent. [MainActivityDetector]\n" +
101+
"1 errors, 0 warnings\n";
102+
String result = lintProject(xml(FN_ANDROID_MANIFEST_XML, "" +
103+
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
104+
"<manifest package=\"com.example.android.custom-lint-rules\"\n" +
105+
" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n" +
106+
" <application>\n" +
107+
" <activity android:name=\"com.example.android.custom-lint-rules" +
108+
".Activity1\">\n" +
109+
" <intent-filter>\n" +
110+
" <action android:name=\"android.intent.action.VIEW\" />\n" +
111+
"\n" +
112+
" <category android:name=\"android.intent.category.HOME\" />\n" +
113+
" <category android:name=\"android.intent.category.LAUNCHER\" />\n" +
114+
" <category android:name=\"android.intent.category.DEFAULT\" />\n" +
115+
" <category android:name=\"android.intent.category.BROWSABLE\" " +
116+
"/>\n" +
117+
" </intent-filter>\n" +
118+
" </activity>\n" +
119+
"\n" +
120+
" <activity android:name=\"com.example.android.custom-lint-rules" +
121+
".Activity2\">\n" +
122+
" </activity>\n" +
123+
"\n" +
124+
" <activity android:name=\"com.example.android.custom-lint-rules" +
125+
".Activity3\">\n" +
126+
" <intent-filter>\n" +
127+
" <action android:name=\"android.intent.action.SEND\"/>\n" +
128+
" <category android:name=\"android.intent.category.DEFAULT\"/>\n" +
129+
" <data android:mimeType=\"text/plain\"/>\n" +
130+
" </intent-filter>\n" +
131+
" </activity>\n" +
132+
" </application>\n" +
133+
"</manifest>"));
134+
assertEquals(expected, result);
135+
}
136+
137+
/**
138+
* Test that a manifest without an <code>&lt;application&gt;</code> tag reports an error.
139+
*/
140+
public void testMissingApplication() throws Exception {
141+
mEnabled = Collections.singleton(MainActivityDetector.ISSUE);
142+
String expected = "AndroidManifest.xml: Error: Expecting AndroidManifest.xml to have an " +
143+
"<activity> tag. [MainActivityDetector]\n" +
144+
"1 errors, 0 warnings\n";
145+
String result = lintProject(xml(FN_ANDROID_MANIFEST_XML, "" +
146+
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
147+
"<manifest package=\"com.example.android.custom-lint-rules\"\n" +
148+
" xmlns:android=\"http://schemas.android.com/apk/res/android\">\n" +
149+
"</manifest>"));
150+
//assertEquals(expected, result);
151+
}
152+
}

0 commit comments

Comments
 (0)