1 /* 2 * Copyright (C) 2017 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.metalava.model.turbine 18 19 import com.android.tools.metalava.model.AnnotationItem 20 import com.android.tools.metalava.model.AnnotationManager 21 import com.android.tools.metalava.model.CLASS_ESTIMATE 22 import com.android.tools.metalava.model.ClassItem 23 import com.android.tools.metalava.model.DefaultAnnotationItem 24 import com.android.tools.metalava.model.DefaultCodebase 25 import com.android.tools.metalava.model.Item 26 import com.android.tools.metalava.model.PackageItem 27 import com.android.tools.metalava.model.PackageList 28 import com.android.tools.metalava.model.source.SourceCodebase 29 import com.google.turbine.tree.Tree.CompUnit 30 import java.io.File 31 32 const val PACKAGE_ESTIMATE = 500 33 34 internal open class TurbineBasedCodebase( 35 location: File, 36 description: String = "Unknown", 37 annotationManager: AnnotationManager, 38 val allowReadingComments: Boolean 39 ) : DefaultCodebase(location, description, false, annotationManager), SourceCodebase { 40 41 /** 42 * Map from class name to class item. Classes are added via [registerClass] while initialising 43 * the codebase 44 */ 45 private lateinit var classMap: MutableMap<String, TurbineClassItem> 46 47 /** Map from package name to the corresponding package item */ 48 private lateinit var packageMap: MutableMap<String, PackageItem> 49 private val hiddenPackages = mutableSetOf<String>() 50 51 /** 52 * A list of the top-level classes declared in the codebase's source (rather than on its 53 * classpath). 54 */ 55 private lateinit var topLevelClassesFromSource: MutableList<ClassItem> 56 57 private lateinit var initializer: TurbineCodebaseInitialiser 58 createAnnotationnull59 override fun createAnnotation( 60 source: String, 61 context: Item?, 62 ): AnnotationItem { 63 return DefaultAnnotationItem.create(this, source) 64 } 65 findClassnull66 override fun findClass(className: String): TurbineClassItem? { 67 return classMap[className] 68 } 69 resolveClassnull70 override fun resolveClass(className: String) = findOrCreateClass(className) 71 72 fun findOrCreateClass(className: String): TurbineClassItem? { 73 return initializer.findOrCreateClass(className) 74 } 75 findPackagenull76 override fun findPackage(pkgName: String): PackageItem? { 77 return packageMap[pkgName] 78 } 79 getPackagesnull80 override fun getPackages(): PackageList { 81 return PackageList( 82 this, 83 packageMap.values.toMutableList().sortedWith(PackageItem.comparator) 84 ) 85 } 86 sizenull87 override fun size(): Int { 88 return packageMap.size 89 } 90 supportsDocumentationnull91 override fun supportsDocumentation(): Boolean = true 92 93 override fun getTopLevelClassesFromSource(): List<ClassItem> { 94 return topLevelClassesFromSource 95 } 96 registerClassnull97 fun registerClass(classItem: TurbineClassItem, isTopClass: Boolean) { 98 val qualifiedName = classItem.qualifiedName() 99 val existing = classMap.put(qualifiedName, classItem) 100 if (existing != null) { 101 error( 102 "Attempted to register $qualifiedName twice; once from ${existing.fileLocation.path} and this one from ${classItem.fileLocation.path}" 103 ) 104 } 105 106 if (isTopClass) { 107 topLevelClassesFromSource.add(classItem) 108 } 109 110 addClass(classItem) 111 } 112 113 /** 114 * Determines if a given package name is marked as hidden. 115 * 116 * @param packageName the name of the package to check. 117 * @return true if the package is hidden, false otherwise. 118 */ isPackageHiddennull119 fun isPackageHidden(packageName: String): Boolean { 120 return hiddenPackages.contains(packageName) 121 } 122 addPackagenull123 fun addPackage(packageItem: TurbinePackageItem) { 124 packageMap.put(packageItem.qualifiedName(), packageItem) 125 } 126 initializenull127 fun initialize(units: List<CompUnit>, classpath: List<File>, hiddenPackages: Set<String>) { 128 this.hiddenPackages.addAll(hiddenPackages) 129 topLevelClassesFromSource = ArrayList(CLASS_ESTIMATE) 130 classMap = HashMap(CLASS_ESTIMATE) 131 packageMap = HashMap(PACKAGE_ESTIMATE) 132 initializer = TurbineCodebaseInitialiser(units, this, classpath) 133 initializer.initialize() 134 } 135 } 136