diff options
25 files changed, 337 insertions, 235 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java index c47cd2d..d690473 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java @@ -16,6 +16,7 @@ package com.android.ide.eclipse.adt; +import static com.android.tools.lint.detector.api.LintConstants.HIGHEST_KNOWN_API; import static com.android.tools.lint.detector.api.LintConstants.TOOLS_PREFIX; import static com.android.tools.lint.detector.api.LintConstants.TOOLS_URI; @@ -825,6 +826,8 @@ public class AdtUtils { case 14: return "ICE_CREAM_SANDWICH"; //$NON-NLS-1$ case 15: return "ICE_CREAM_SANDWICH_MR1"; //$NON-NLS-1$ case 16: return "JELLY_BEAN"; //$NON-NLS-1$ + // If you add more versions here, also update #getAndroidName and + // LintConstants#HIGHEST_KNOWN_API } return null; @@ -855,6 +858,9 @@ public class AdtUtils { case 14: return "API 14: Android 4.0 (IceCreamSandwich)"; case 15: return "API 15: Android 4.0.3 (IceCreamSandwich)"; case 16: return "API 16: Android 4.1 (Jelly Bean)"; + // If you add more versions here, also update #getBuildCodes and + // LintConstants#HIGHEST_KNOWN_API + default: { // Consult SDK manager to see if we know any more (later) names, // installed by user @@ -891,7 +897,7 @@ public class AdtUtils { * @return the highest known API number */ public static int getHighestKnownApiLevel() { - return 16; + return HIGHEST_KNOWN_API; } /** @@ -901,7 +907,7 @@ public class AdtUtils { * maximum known versions (with no gaps) */ public static String[] getKnownVersions() { - int max = 15; + int max = getHighestKnownApiLevel(); Sdk sdk = Sdk.getCurrent(); if (sdk != null) { for (IAndroidTarget target : sdk.getTargets()) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java index 36ebf5a..bc3da29 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java @@ -29,6 +29,8 @@ import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; +import com.android.ide.eclipse.adt.internal.sdk.Sdk; +import com.android.sdklib.IAndroidTarget; import com.android.tools.lint.checks.BuiltinIssueRegistry; import com.android.tools.lint.client.api.Configuration; import com.android.tools.lint.client.api.IDomParser; @@ -859,6 +861,12 @@ public class EclipseLintClient extends LintClient implements IDomParser { } } + @Override + @NonNull + public IAndroidTarget[] getTargets() { + return Sdk.getCurrent().getTargets(); + } + private static class LazyLocation extends Location implements Location.Handle { private final IStructuredDocument mDocument; private final IndexedRegion mRegion; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java index 84f4cf6..51d34e0 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java @@ -387,8 +387,10 @@ public class NewProjectWizard extends TemplateWizard { parameters.put(ATTR_APP_TITLE, mValues.applicationName); parameters.put(ATTR_MIN_API, mValues.minSdk); parameters.put(ATTR_MIN_API_LEVEL, mValues.minSdkLevel); - parameters.put(ATTR_TARGET_API, 15); - parameters.put(ATTR_BUILD_API, mValues.target.getVersion().getApiLevel()); + int buildApiLevel = mValues.target.getVersion().getApiLevel(); + parameters.put(ATTR_BUILD_API, buildApiLevel); + parameters.put(ATTR_TARGET_API, buildApiLevel); + parameters.put(ATTR_COPY_ICONS, !mValues.createIcon); parameters.putAll(mValues.parameters); } diff --git a/lint/cli/.classpath b/lint/cli/.classpath index b5483f0..fd221d0 100644 --- a/lint/cli/.classpath +++ b/lint/cli/.classpath @@ -2,13 +2,14 @@ <classpath> <classpathentry kind="src" path="src"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> - <classpathentry combineaccessrules="false" kind="src" path="/common"/> + <classpathentry combineaccessrules="false" kind="src" path="/common"/> <classpathentry combineaccessrules="false" kind="src" path="/lint-api"/> <classpathentry combineaccessrules="false" kind="src" path="/lint-checks"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-tree-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-tree-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/> <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-analysis-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/guava-tools/guava-10.0.1.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/guava-tools/src.zip"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/lombok-ast/lombok-ast-0.2.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/lombok-ast/src.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/guava-tools/guava-10.0.1.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/guava-tools/src.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/lombok-ast/lombok-ast-0.2.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/lombok-ast/src.zip"/> + <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/lint/cli/Android.mk b/lint/cli/Android.mk index 8a46d48..f762d60 100644 --- a/lint/cli/Android.mk +++ b/lint/cli/Android.mk @@ -11,6 +11,7 @@ LOCAL_JAR_MANIFEST := etc/manifest.txt # If the dependency list is changed, etc/manifest.txt LOCAL_JAVA_LIBRARIES := \ common \ + sdklib \ lint_api \ lint_checks \ lombok-ast-0.2 \ diff --git a/lint/cli/etc/manifest.txt b/lint/cli/etc/manifest.txt index 5f10a7e..f9c95db 100644 --- a/lint/cli/etc/manifest.txt +++ b/lint/cli/etc/manifest.txt @@ -1,2 +1,2 @@ Main-Class: com.android.tools.lint.Main -Class-Path: common.jar layout_lib.jar lint_api.jar lint_checks.jar asm-4.0.jar asm-tree-4.0.jar asm-analysis-4.0.jar guava-10.0.1.jar lombok-ast-0.2.jar +Class-Path: common.jar layout_lib.jar lint_api.jar lint_checks.jar asm-4.0.jar asm-tree-4.0.jar asm-analysis-4.0.jar guava-10.0.1.jar lombok-ast-0.2.jar sdklib.jar diff --git a/lint/libs/lint_api/.classpath b/lint/libs/lint_api/.classpath index f52ce2f..39495cc 100644 --- a/lint/libs/lint_api/.classpath +++ b/lint/libs/lint_api/.classpath @@ -8,5 +8,6 @@ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/guava-tools/guava-10.0.1.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/guava-tools/src.zip"/> <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/lombok-ast/lombok-ast-0.2.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/lombok-ast/src.zip"/> <classpathentry combineaccessrules="false" kind="src" path="/layoutlib_api"/> + <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/lint/libs/lint_api/Android.mk b/lint/libs/lint_api/Android.mk index d6d26f3..9e2e678 100644 --- a/lint/libs/lint_api/Android.mk +++ b/lint/libs/lint_api/Android.mk @@ -22,6 +22,7 @@ LOCAL_JAVA_RESOURCE_DIRS := src LOCAL_JAVA_LIBRARIES := \ lombok-ast-0.2 \ common \ + sdklib \ layoutlib_api \ asm-tools \ asm-tree-tools \ diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java index f168d7a..363b9cd 100644 --- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java +++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java @@ -24,13 +24,18 @@ import static com.android.tools.lint.detector.api.LintConstants.SRC_FOLDER; import com.android.annotations.NonNull; import com.android.annotations.Nullable; +import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.SdkManager; import com.android.tools.lint.detector.api.Context; import com.android.tools.lint.detector.api.Detector; import com.android.tools.lint.detector.api.Issue; +import com.android.tools.lint.detector.api.LintConstants; import com.android.tools.lint.detector.api.LintUtils; import com.android.tools.lint.detector.api.Location; import com.android.tools.lint.detector.api.Project; import com.android.tools.lint.detector.api.Severity; +import com.android.utils.StdLogger; +import com.android.utils.StdLogger.Level; import com.google.common.annotations.Beta; import com.google.common.collect.Maps; import com.google.common.io.Files; @@ -285,6 +290,32 @@ public abstract class LintClient { } /** + * Returns the File pointing to the user's SDK install area. This is generally + * the root directory containing the lint tool (but also platforms/ etc). + * + * @return a file pointing to the user's install area + */ + @Nullable + public File getSdkHome() { + File binDir = getLintBinDir(); + if (binDir != null) { + assert binDir.getName().equals("tools"); + + File root = binDir.getParentFile(); + if (root != null && root.isDirectory()) { + return root; + } + } + + String home = System.getenv("ANDROID_HOME"); //$NON-NLS-1$ + if (home != null) { + return new File(home); + } + + return null; + } + + /** * Locates an SDK resource (relative to the SDK root directory). * <p> * TODO: Consider switching to a {@link URL} return type instead. @@ -524,4 +555,48 @@ public abstract class LintClient { mDirToProject.put(canonicalDir, project); return project; } + + private IAndroidTarget[] mTargets; + + /** + * Returns all the {@link IAndroidTarget} versions installed in the user's SDK install + * area. + * + * @return all the installed targets + */ + @NonNull + public IAndroidTarget[] getTargets() { + if (mTargets == null) { + File sdkHome = getSdkHome(); + if (sdkHome != null) { + StdLogger log = new StdLogger(Level.WARNING); + SdkManager manager = SdkManager.createManager(sdkHome.getPath(), log); + mTargets = manager.getTargets(); + } else { + mTargets = new IAndroidTarget[0]; + } + } + + return mTargets; + } + + /** + * Returns the highest known API level. + * + * @return the highest known API level + */ + public int getHighestKnownApiLevel() { + int max = LintConstants.HIGHEST_KNOWN_API; + + for (IAndroidTarget target : getTargets()) { + if (target.isPlatform()) { + int api = target.getVersion().getApiLevel(); + if (api > max && !target.getVersion().isPreview()) { + max = api; + } + } + } + + return max; + } } diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java index d91b155..8ff5fc0 100644 --- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java +++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java @@ -34,6 +34,7 @@ import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.annotations.VisibleForTesting; import com.android.resources.ResourceFolderType; +import com.android.sdklib.IAndroidTarget; import com.android.tools.lint.client.api.LintListener.EventType; import com.android.tools.lint.detector.api.Category; import com.android.tools.lint.detector.api.ClassContext; @@ -1650,6 +1651,41 @@ public class LintDriver { public File findResource(@NonNull String relativePath) { return mDelegate.findResource(relativePath); } + + @Override + @Nullable + public File getCacheDir(boolean create) { + return mDelegate.getCacheDir(create); + } + + @Override + @NonNull + protected ClassPathInfo getClassPath(@NonNull Project project) { + return mDelegate.getClassPath(project); + } + + @Override + public void log(@Nullable Throwable exception, @Nullable String format, + @Nullable Object... args) { + mDelegate.log(exception, format, args); + } + + @Override + @Nullable + public File getSdkHome() { + return mDelegate.getSdkHome(); + } + + @Override + @NonNull + public IAndroidTarget[] getTargets() { + return mDelegate.getTargets(); + } + + @Override + public int getHighestKnownApiLevel() { + return mDelegate.getHighestKnownApiLevel(); + } } /** diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java index a0ff760..40b468d 100644 --- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java +++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java @@ -341,4 +341,13 @@ public class LintConstants { "android/content/ContentProvider"; //$NON-NLS-1$ public static final String ANDROID_CONTENT_BROADCAST_RECEIVER = "android/content/BroadcastReceiver"; //$NON-NLS-1$ + + /** + * The highest known API level. Note that the tools may also look at the + * installed platforms to see if they can find more recently released + * platforms, e.g. when the tools have not yet been updated for a new + * release. This number is used as a baseline and any more recent platforms + * found can be used to increase the highest known number. + */ + public static final int HIGHEST_KNOWN_API = 16; } diff --git a/lint/libs/lint_checks/.classpath b/lint/libs/lint_checks/.classpath index 1316db4..4a48734 100644 --- a/lint/libs/lint_checks/.classpath +++ b/lint/libs/lint_checks/.classpath @@ -10,5 +10,6 @@ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/lombok-ast/lombok-ast-0.2.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/lombok-ast/src.zip"/> <classpathentry combineaccessrules="false" kind="src" path="/layoutlib_api"/> <classpathentry combineaccessrules="false" kind="src" path="/common"/> + <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/lint/libs/lint_checks/Android.mk b/lint/libs/lint_checks/Android.mk index a5ed601..e15e928 100644 --- a/lint/libs/lint_checks/Android.mk +++ b/lint/libs/lint_checks/Android.mk @@ -7,11 +7,10 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_JAVA_RESOURCE_DIRS := src -LOCAL_JAR_MANIFEST := etc/manifest.txt - # If the dependency list is changed, etc/manifest.txt LOCAL_JAVA_LIBRARIES := \ common \ + sdklib \ layoutlib_api \ lombok-ast-0.2 \ lint_api \ diff --git a/lint/libs/lint_checks/NOTICE b/lint/libs/lint_checks/NOTICE deleted file mode 100644 index becc120..0000000 --- a/lint/libs/lint_checks/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/lint/libs/lint_checks/etc/manifest.txt b/lint/libs/lint_checks/etc/manifest.txt deleted file mode 100644 index 36cee35..0000000 --- a/lint/libs/lint_checks/etc/manifest.txt +++ /dev/null @@ -1 +0,0 @@ -Class-Path: lint_api.jar common.jar layoutlib_api.jar diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java index dd1e973..e1325b5 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java @@ -54,7 +54,7 @@ public class BuiltinIssueRegistry extends IssueRegistry { private static final List<Issue> sIssues; static { - final int initialCapacity = 101; + final int initialCapacity = 102; List<Issue> issues = new ArrayList<Issue>(initialCapacity); issues.add(AccessibilityDetector.ISSUE); @@ -109,6 +109,7 @@ public class BuiltinIssueRegistry extends IssueRegistry { issues.add(ManifestOrderDetector.MULTIPLE_USES_SDK); issues.add(ManifestOrderDetector.WRONG_PARENT); issues.add(ManifestOrderDetector.DUPLICATE_ACTIVITY); + issues.add(ManifestOrderDetector.TARGET_NEWER); issues.add(SecurityDetector.EXPORTED_PROVIDER); issues.add(SecurityDetector.EXPORTED_SERVICE); issues.add(SecurityDetector.EXPORTED_ACTIVITY); diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java index b116eb9..eca0a90 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java @@ -87,13 +87,37 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann "the version for.)", Category.CORRECTNESS, - 2, + 9, Severity.WARNING, ManifestOrderDetector.class, Scope.MANIFEST_SCOPE).setMoreInfo( "http://developer.android.com/guide/topics/manifest/uses-sdk-element.html"); //$NON-NLS-1$ - /** Missing a {@code <uses-sdk>} element */ + /** Using a targetSdkVersion that isn't recent */ + public static final Issue TARGET_NEWER = Issue.create( + "OldTargetApi", //$NON-NLS-1$ + "Checks that the manifest specifies a targetSdkVersion that is recent", + + "When your application runs on a version of Android that is more recent than your " + + "targetSdkVersion specifies that it has been tested with, various compatibility " + + "modes kick in. This ensures that your application continues to work, but it may " + + "look out of place. For example, if the targetSdkVersion is less than 14, your " + + "app may get an option button in the UI.\n" + + "\n" + + "To fix this issue, set the targetSdkVersion to the highest available value. Then " + + "test your app to make sure everything works correctly. You may want to consult " + + "the compatibility notes to see what changes apply to each version you are adding " + + "support for: " + + "http://developer.android.com/reference/android/os/Build.VERSION_CODES.html", + + Category.CORRECTNESS, + 6, + Severity.WARNING, + ManifestOrderDetector.class, + Scope.MANIFEST_SCOPE).setMoreInfo( + "http://developer.android.com/reference/android/os/Build.VERSION_CODES.html"); //$NON-NLS-1$ + + /** Using multiple {@code <uses-sdk>} elements */ public static final Issue MULTIPLE_USES_SDK = Issue.create( "MultipleUsesSdk", //$NON-NLS-1$ "Checks that the <uses-sdk> element appears at most once", @@ -291,8 +315,9 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann "<uses-sdk> tag should specify a minimum API level with " + "android:minSdkVersion=\"?\"", null); } - } else if (context.getProject().getMinSdk() <= 9 - && !element.hasAttributeNS(ANDROID_URI, ATTR_TARGET_SDK_VERSION)) { + } + + if (!element.hasAttributeNS(ANDROID_URI, ATTR_TARGET_SDK_VERSION)) { // Warn if not setting target SDK -- but only if the min SDK is somewhat // old so there's some compatibility stuff kicking in (such as the menu // button etc) @@ -303,6 +328,20 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann "compatibility behaviors may be enabled) with " + "android:targetSdkVersion=\"?\"", null); } + } else if (context.isEnabled(TARGET_NEWER)){ + String target = element.getAttributeNS(ANDROID_URI, ATTR_TARGET_SDK_VERSION); + try { + int api = Integer.parseInt(target); + if (api < context.getClient().getHighestKnownApiLevel()) { + context.report(TARGET_NEWER, element, context.getLocation(element), + "Not targeting the latest versions of Android; compatibility " + + "modes apply. Consider testing and updating this version. " + + "Consult the android.os.Build.VERSION_CODES javadoc for details.", + null); + } + } catch (NumberFormatException nufe) { + // Ignore: AAPT will enforce this. + } } } diff --git a/lint/libs/lint_checks/tests/.classpath b/lint/libs/lint_checks/tests/.classpath index 18970b8..752dafd 100644 --- a/lint/libs/lint_checks/tests/.classpath +++ b/lint/libs/lint_checks/tests/.classpath @@ -13,5 +13,6 @@ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/lombok-ast/lombok-ast-0.2.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/lombok-ast/src.zip"/> <classpathentry combineaccessrules="false" kind="src" path="/layoutlib_api"/> <classpathentry combineaccessrules="false" kind="src" path="/common"/> + <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/lint/libs/lint_checks/tests/Android.mk b/lint/libs/lint_checks/tests/Android.mk index b078f2b..9f591f6 100644 --- a/lint/libs/lint_checks/tests/Android.mk +++ b/lint/libs/lint_checks/tests/Android.mk @@ -22,7 +22,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_MODULE := lint_checks-tests LOCAL_MODULE_TAGS := optional -LOCAL_JAVA_LIBRARIES := common lint_api lint_checks lint junit easymock asm-tools asm-tree-tools guava-tools layoutlib_api +LOCAL_JAVA_LIBRARIES := common sdklib lint_api lint_checks lint junit easymock asm-tools asm-tree-tools guava-tools layoutlib_api include $(BUILD_HOST_JAVA_LIBRARY) diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/XmlReporterTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/XmlReporterTest.java index c908319..c9a537a 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/XmlReporterTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/XmlReporterTest.java @@ -88,7 +88,7 @@ public class XmlReporterTest extends AbstractCheckTest { " severity=\"Warning\"\n" + " message=\"<uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion="?"\"\n" + " category=\"Correctness\"\n" + - " priority=\"2\"\n" + + " priority=\"9\"\n" + " summary=\"Checks that the minimum SDK and target SDK attributes are defined\"\n" + " explanation=\"The manifest should contain a <uses-sdk> element which defines the minimum minimum API Level required for the application to run, as well as the target version (the highest API level you have tested the version for.)\"\n" + " url=\"http://developer.android.com/guide/topics/manifest/uses-sdk-element.html\"\n" + diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java index 4351a7e..25e60a8 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java @@ -93,7 +93,7 @@ public abstract class AbstractCheckTest extends TestCase { protected String checkLint(List<File> files) throws Exception { mOutput = new StringBuilder(); - TestLintClient lintClient = new TestLintClient(); + TestLintClient lintClient = createClient(); String result = lintClient.analyze(files); // The output typically contains a few directory/filenames. @@ -106,6 +106,14 @@ public abstract class AbstractCheckTest extends TestCase { return result; } + protected TestLintClient createClient() { + return new TestLintClient(); + } + + protected TestConfiguration getConfiguration(Project project) { + return new TestConfiguration(); + } + /** * Run lint on the given files when constructed as a separate project * @return The output of the lint check. On Windows, this transforms all directory @@ -349,7 +357,7 @@ public abstract class AbstractCheckTest extends TestCase { @Override public Configuration getConfiguration(Project project) { - return new TestConfiguration(); + return AbstractCheckTest.this.getConfiguration(project); } @Override diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java index ad5274c..1b8c8f4 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ManifestOrderDetectorTest.java @@ -17,6 +17,12 @@ package com.android.tools.lint.checks; import com.android.tools.lint.detector.api.Detector; +import com.android.tools.lint.detector.api.Issue; +import com.android.tools.lint.detector.api.Project; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; @SuppressWarnings("javadoc") public class ManifestOrderDetectorTest extends AbstractCheckTest { @@ -25,7 +31,20 @@ public class ManifestOrderDetectorTest extends AbstractCheckTest { return new ManifestOrderDetector(); } + private Set<Issue> mEnabled = new HashSet<Issue>(); + + @Override + protected TestConfiguration getConfiguration(Project project) { + return new TestConfiguration() { + @Override + public boolean isEnabled(Issue issue) { + return super.isEnabled(issue) && mEnabled.contains(issue); + } + }; + } + public void testOrderOk() throws Exception { + mEnabled = Collections.singleton(ManifestOrderDetector.ORDER); assertEquals( "No warnings.", lintProject( @@ -34,14 +53,12 @@ public class ManifestOrderDetectorTest extends AbstractCheckTest { } public void testBrokenOrder() throws Exception { + mEnabled = Collections.singleton(ManifestOrderDetector.ORDER); assertEquals( "AndroidManifest.xml:16: Warning: <uses-sdk> tag appears after <application> tag [ManifestOrder]\n" + " <uses-sdk android:minSdkVersion=\"Froyo\" />\n" + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - "AndroidManifest.xml:16: Warning: <uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion=\"?\" [UsesMinSdkAttributes]\n" + - " <uses-sdk android:minSdkVersion=\"Froyo\" />\n" + - " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - "0 errors, 2 warnings\n" + + "0 errors, 1 warnings\n" + "", lintProject( @@ -50,6 +67,7 @@ public class ManifestOrderDetectorTest extends AbstractCheckTest { } public void testMissingUsesSdk() throws Exception { + mEnabled = Collections.singleton(ManifestOrderDetector.USES_SDK); assertEquals( "AndroidManifest.xml: Warning: Manifest should specify a minimum API level with <uses-sdk android:minSdkVersion=\"?\" />; if it really supports all versions of Android set it to 1. [UsesMinSdkAttributes]\n" + "0 errors, 1 warnings\n", @@ -59,6 +77,7 @@ public class ManifestOrderDetectorTest extends AbstractCheckTest { } public void testMissingMinSdk() throws Exception { + mEnabled = Collections.singleton(ManifestOrderDetector.USES_SDK); assertEquals( "AndroidManifest.xml:7: Warning: <uses-sdk> tag should specify a minimum API level with android:minSdkVersion=\"?\" [UsesMinSdkAttributes]\n" + " <uses-sdk android:targetSdkVersion=\"10\" />\n" + @@ -70,21 +89,39 @@ public class ManifestOrderDetectorTest extends AbstractCheckTest { "res/values/strings.xml")); } + public void testMissingTargetSdk() throws Exception { + mEnabled = Collections.singleton(ManifestOrderDetector.USES_SDK); + assertEquals( + "AndroidManifest.xml:7: Warning: <uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion=\"?\" [UsesMinSdkAttributes]\n" + + " <uses-sdk android:minSdkVersion=\"10\" />\n" + + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + "0 errors, 1 warnings\n", + lintProject( + "missingtarget.xml=>AndroidManifest.xml", + "res/values/strings.xml")); + } + + public void testOldTargetSdk() throws Exception { + mEnabled = Collections.singleton(ManifestOrderDetector.TARGET_NEWER); + assertEquals( + "AndroidManifest.xml:7: Warning: Not targeting the latest versions of Android; compatibility modes apply. Consider testing and updating this version. Consult the android.os.Build.VERSION_CODES javadoc for details. [OldTargetApi]\n" + + " <uses-sdk android:minSdkVersion=\"10\" android:targetSdkVersion=\"14\" />\n" + + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + + "0 errors, 1 warnings\n", + lintProject( + "oldtarget.xml=>AndroidManifest.xml", + "res/values/strings.xml")); + } + public void testMultipleSdk() throws Exception { + mEnabled = Collections.singleton(ManifestOrderDetector.MULTIPLE_USES_SDK); assertEquals( "AndroidManifest.xml:8: Error: There should only be a single <uses-sdk> element in the manifest: merge these together [MultipleUsesSdk]\n" + " <uses-sdk android:targetSdkVersion=\"14\" />\n" + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " AndroidManifest.xml:7: Also appears here\n" + " AndroidManifest.xml:9: Also appears here\n" + - "AndroidManifest.xml:7: Warning: <uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion=\"?\" [UsesMinSdkAttributes]\n" + - " <uses-sdk android:minSdkVersion=\"5\" />\n" + - " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - "AndroidManifest.xml:9: Warning: <uses-sdk> tag should specify a minimum API level with android:minSdkVersion=\"?\" [UsesMinSdkAttributes]\n" + - " <uses-sdk android:maxSdkVersion=\"15\" />\n" + - " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - "1 errors, 2 warnings\n" + - "", + "1 errors, 0 warnings\n", lintProject( "multiplesdk.xml=>AndroidManifest.xml", @@ -92,11 +129,8 @@ public class ManifestOrderDetectorTest extends AbstractCheckTest { } public void testWrongLocation() throws Exception { + mEnabled = Collections.singleton(ManifestOrderDetector.WRONG_PARENT); assertEquals( - "AndroidManifest.xml:14: Error: There should only be a single <uses-sdk> element in the manifest: merge these together [MultipleUsesSdk]\n" + - " <uses-sdk />\n" + - " ~~~~~~~~~~~~\n" + - " AndroidManifest.xml:8: Also appears here\n" + "AndroidManifest.xml:8: Error: The <uses-sdk> element must be a direct child of the <manifest> root element [WrongManifestParent]\n" + " <uses-sdk android:minSdkVersion=\"Froyo\" />\n" + " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + @@ -136,19 +170,14 @@ public class ManifestOrderDetectorTest extends AbstractCheckTest { "AndroidManifest.xml:25: Error: The <activity> element must be a direct child of the <application> element [WrongManifestParent]\n" + " <activity android:name=\".HelloWorld\"\n" + " ^\n" + - "AndroidManifest.xml:8: Warning: <uses-sdk> tag appears after <application> tag [ManifestOrder]\n" + - " <uses-sdk android:minSdkVersion=\"Froyo\" />\n" + - " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - "AndroidManifest.xml:8: Warning: <uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion=\"?\" [UsesMinSdkAttributes]\n" + - " <uses-sdk android:minSdkVersion=\"Froyo\" />\n" + - " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - "14 errors, 2 warnings\n" + + "13 errors, 0 warnings\n" + "", lintProject("broken-manifest2.xml=>AndroidManifest.xml")); } public void testDuplicateActivity() throws Exception { + mEnabled = Collections.singleton(ManifestOrderDetector.DUPLICATE_ACTIVITY); assertEquals( "AndroidManifest.xml:16: Error: Duplicate registration for activity com.example.helloworld.HelloWorld [DuplicateActivity]\n" + " <activity android:name=\"com.example.helloworld.HelloWorld\"\n" + diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/missingtarget.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/missingtarget.xml new file mode 100644 index 0000000..1f4fba0 --- /dev/null +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/missingtarget.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="test.bytecode" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk android:minSdkVersion="10" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" > + <activity + android:name=".BytecodeTestsActivity" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/oldtarget.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/oldtarget.xml new file mode 100644 index 0000000..d72d7fc --- /dev/null +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/oldtarget.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="test.bytecode" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="14" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" > + <activity + android:name=".BytecodeTestsActivity" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/client/api/LintClientTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/client/api/LintClientTest.java new file mode 100644 index 0000000..2a3a43a --- /dev/null +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/client/api/LintClientTest.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php + * + * 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.client.api; + +import com.android.tools.lint.Main; + +import junit.framework.TestCase; + +@SuppressWarnings("javadoc") +public class LintClientTest extends TestCase { + public void test() throws Exception { + Main client = new Main(); + int max = client.getHighestKnownApiLevel(); + assertTrue(max >= 16); + } +} |