blob: 0838849d117acf6dea1f15ee3db3653df501b1b5 [file] [log] [blame]
/*
* 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.client.api
import com.android.SdkConstants.ABSOLUTE_LAYOUT
import com.android.SdkConstants.ABS_LIST_VIEW
import com.android.SdkConstants.ABS_SEEK_BAR
import com.android.SdkConstants.ABS_SPINNER
import com.android.SdkConstants.ADAPTER_VIEW
import com.android.SdkConstants.AUTO_COMPLETE_TEXT_VIEW
import com.android.SdkConstants.BUTTON
import com.android.SdkConstants.CHECKABLE
import com.android.SdkConstants.CHECKED_TEXT_VIEW
import com.android.SdkConstants.CHECK_BOX
import com.android.SdkConstants.COMPOUND_BUTTON
import com.android.SdkConstants.EDIT_TEXT
import com.android.SdkConstants.EXPANDABLE_LIST_VIEW
import com.android.SdkConstants.FRAME_LAYOUT
import com.android.SdkConstants.GALLERY
import com.android.SdkConstants.GRID_VIEW
import com.android.SdkConstants.HORIZONTAL_SCROLL_VIEW
import com.android.SdkConstants.IMAGE_BUTTON
import com.android.SdkConstants.IMAGE_VIEW
import com.android.SdkConstants.LINEAR_LAYOUT
import com.android.SdkConstants.LIST_VIEW
import com.android.SdkConstants.MULTI_AUTO_COMPLETE_TEXT_VIEW
import com.android.SdkConstants.PROGRESS_BAR
import com.android.SdkConstants.RADIO_BUTTON
import com.android.SdkConstants.RADIO_GROUP
import com.android.SdkConstants.RELATIVE_LAYOUT
import com.android.SdkConstants.SCROLL_VIEW
import com.android.SdkConstants.SEEK_BAR
import com.android.SdkConstants.SPINNER
import com.android.SdkConstants.SURFACE_VIEW
import com.android.SdkConstants.SWITCH
import com.android.SdkConstants.TABLE_LAYOUT
import com.android.SdkConstants.TABLE_ROW
import com.android.SdkConstants.TAB_HOST
import com.android.SdkConstants.TAB_WIDGET
import com.android.SdkConstants.TEXT_VIEW
import com.android.SdkConstants.TOGGLE_BUTTON
import com.android.SdkConstants.VIEW
import com.android.SdkConstants.VIEW_ANIMATOR
import com.android.SdkConstants.VIEW_GROUP
import com.android.SdkConstants.VIEW_PKG_PREFIX
import com.android.SdkConstants.VIEW_STUB
import com.android.SdkConstants.VIEW_SWITCHER
import com.android.SdkConstants.WEB_VIEW
import com.android.SdkConstants.WIDGET_PKG_PREFIX
import com.google.common.annotations.Beta
/**
* Default simple implementation of an [SdkInfo]
*
*
* **NOTE: This is not a public or final API; if you rely on this be prepared
* to adjust your code for the next tools release.**
*/
@Beta
internal class DefaultSdkInfo : SdkInfo() {
override fun getParentViewName(name: String): String? {
val rawType = getRawType(name) ?: return null
return getParent(rawType)
}
override fun getParentViewClass(fqcn: String): String? {
var simpleName = fqcn
val index = simpleName.lastIndexOf('.')
if (index != -1) {
simpleName = simpleName.substring(index + 1)
}
val parent = getParent(simpleName) ?: return null
// The map only stores class names internally; correct for full package paths
return if (parent == VIEW || parent == VIEW_GROUP || parent == SURFACE_VIEW) {
VIEW_PKG_PREFIX + parent
} else {
WIDGET_PKG_PREFIX + parent
}
}
override fun isSubViewOf(parentViewFqcn: String, childViewFqcn: String): Boolean {
var parent = getRawType(parentViewFqcn) ?: return false
var child: String? = getRawType(childViewFqcn)
// Do analysis just on non-fqcn paths
if (parent.indexOf('.') != -1) {
parent = parent.substring(parent.lastIndexOf('.') + 1)
}
if (child!!.indexOf('.') != -1) {
child = child.substring(child.lastIndexOf('.') + 1)
}
if (parent == VIEW) {
return true
}
while (child != VIEW) {
if (parent == child) {
return true
}
if (implementsInterface(child!!, parent)) {
return true
}
child = getParent(child)
if (child == null) {
// Unknown view - err on the side of caution
return true
}
}
return false
}
private fun implementsInterface(className: String, interfaceName: String): Boolean =
interfaceName == getInterface(className)
// Strip off type parameters, e.g. AdapterView<?> ⇒ AdapterView
private fun getRawType(type: String?): String? {
if (type != null) {
val index = type.indexOf('<')
if (index != -1) {
return type.substring(0, index)
}
}
return type
}
override fun isLayout(tag: String): Boolean {
// TODO: Read in widgets.txt from the platform install area to look up this information
// dynamically instead!
if (super.isLayout(tag)) {
return true
}
when (tag) {
TAB_HOST, HORIZONTAL_SCROLL_VIEW, VIEW_SWITCHER, TAB_WIDGET, VIEW_ANIMATOR,
SCROLL_VIEW, GRID_VIEW, TABLE_ROW, RADIO_GROUP, LIST_VIEW, EXPANDABLE_LIST_VIEW,
"MediaController", "DialerFilter", "ViewFlipper", "SlidingDrawer", "StackView",
"SearchView", "TextSwitcher", "AdapterViewFlipper", "ImageSwitcher" -> return true
}
return false
}
private fun getParent(layout: String): String? {
when (layout) {
COMPOUND_BUTTON -> return BUTTON
ABS_SPINNER -> return ADAPTER_VIEW
ABS_LIST_VIEW -> return ADAPTER_VIEW
ABS_SEEK_BAR -> return PROGRESS_BAR
ADAPTER_VIEW -> return VIEW_GROUP
VIEW_GROUP -> return VIEW
TEXT_VIEW -> return VIEW
CHECKED_TEXT_VIEW -> return TEXT_VIEW
RADIO_BUTTON -> return COMPOUND_BUTTON
SPINNER -> return ABS_SPINNER
IMAGE_BUTTON -> return IMAGE_VIEW
IMAGE_VIEW -> return VIEW
EDIT_TEXT -> return TEXT_VIEW
PROGRESS_BAR -> return VIEW
TOGGLE_BUTTON -> return COMPOUND_BUTTON
VIEW_STUB -> return VIEW
BUTTON -> return TEXT_VIEW
SEEK_BAR -> return ABS_SEEK_BAR
CHECK_BOX -> return COMPOUND_BUTTON
SWITCH -> return COMPOUND_BUTTON
GALLERY -> return ABS_SPINNER
SURFACE_VIEW -> return VIEW
ABSOLUTE_LAYOUT -> return VIEW_GROUP
LINEAR_LAYOUT -> return VIEW_GROUP
RELATIVE_LAYOUT -> return VIEW_GROUP
LIST_VIEW -> return ABS_LIST_VIEW
VIEW_SWITCHER -> return VIEW_ANIMATOR
FRAME_LAYOUT -> return VIEW_GROUP
HORIZONTAL_SCROLL_VIEW -> return FRAME_LAYOUT
VIEW_ANIMATOR -> return FRAME_LAYOUT
TAB_HOST -> return FRAME_LAYOUT
TABLE_ROW -> return LINEAR_LAYOUT
RADIO_GROUP -> return LINEAR_LAYOUT
TAB_WIDGET -> return LINEAR_LAYOUT
EXPANDABLE_LIST_VIEW -> return LIST_VIEW
TABLE_LAYOUT -> return LINEAR_LAYOUT
SCROLL_VIEW -> return FRAME_LAYOUT
GRID_VIEW -> return ABS_LIST_VIEW
WEB_VIEW -> return ABSOLUTE_LAYOUT
AUTO_COMPLETE_TEXT_VIEW -> return EDIT_TEXT
MULTI_AUTO_COMPLETE_TEXT_VIEW -> return AUTO_COMPLETE_TEXT_VIEW
"MediaController" -> return FRAME_LAYOUT
"SlidingDrawer" -> return VIEW_GROUP
"DialerFilter" -> return RELATIVE_LAYOUT
"DigitalClock" -> return TEXT_VIEW
"Chronometer" -> return TEXT_VIEW
"ImageSwitcher" -> return VIEW_SWITCHER
"TextSwitcher" -> return VIEW_SWITCHER
"AnalogClock" -> return VIEW
"TwoLineListItem" -> return RELATIVE_LAYOUT
"ZoomControls" -> return LINEAR_LAYOUT
"DatePicker" -> return FRAME_LAYOUT
"TimePicker" -> return FRAME_LAYOUT
"VideoView" -> return SURFACE_VIEW
"ZoomButton" -> return IMAGE_BUTTON
"RatingBar" -> return ABS_SEEK_BAR
"ViewFlipper" -> return VIEW_ANIMATOR
"NumberPicker" -> return LINEAR_LAYOUT
}
return null
}
private fun getInterface(cls: String): String? =
when (cls) {
CHECKED_TEXT_VIEW, COMPOUND_BUTTON -> CHECKABLE
else -> null
}
}