1 /*
<lambda>null2  * 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
18 
19 import com.android.tools.metalava.model.visitors.ApiVisitor
20 import com.android.tools.metalava.model.visitors.ItemVisitor
21 import com.android.tools.metalava.model.visitors.TypeVisitor
22 import com.android.tools.metalava.tick
23 
24 interface PackageItem : Item {
25     /** The qualified name of this package */
26     fun qualifiedName(): String
27 
28     /** All top level classes in this package */
29     fun topLevelClasses(): Sequence<ClassItem>
30 
31     /** All top level classes **and inner classes** in this package */
32     fun allClasses(): Sequence<ClassItem> {
33         return topLevelClasses().asSequence().flatMap { it.allClasses() }
34     }
35 
36     override fun type(): TypeItem? = null
37 
38     val isDefault get() = qualifiedName().isEmpty()
39 
40     override fun parent(): PackageItem? = if (qualifiedName().isEmpty()) null else containingPackage()
41 
42     override fun containingPackage(strict: Boolean): PackageItem? {
43         if (!strict) {
44             return this
45         }
46         val name = qualifiedName()
47         val lastDot = name.lastIndexOf('.')
48         return if (lastDot != -1) {
49             codebase.findPackage(name.substring(0, lastDot))
50         } else {
51             null
52         }
53     }
54 
55     /** Whether this package is empty */
56     fun empty() = topLevelClasses().none()
57 
58     override fun accept(visitor: ItemVisitor) {
59         if (visitor.skipEmptyPackages && empty()) {
60             return
61         }
62 
63         if (visitor is ApiVisitor) {
64             if (!emit) {
65                 return
66             }
67 
68             // For the API visitor packages are visited lazily; only when we encounter
69             // an unfiltered item within the class
70             topLevelClasses()
71                 .asSequence()
72                 .sortedWith(ClassItem.classNameSorter())
73                 .forEach {
74                     tick()
75                     it.accept(visitor)
76                 }
77 
78             if (visitor.visitingPackage) {
79                 visitor.visitingPackage = false
80                 visitor.afterVisitPackage(this)
81                 visitor.afterVisitItem(this)
82             }
83 
84             return
85         }
86 
87         if (visitor.skip(this)) {
88             return
89         }
90 
91         visitor.visitItem(this)
92         visitor.visitPackage(this)
93 
94         for (cls in topLevelClasses()) {
95             cls.accept(visitor)
96         }
97 
98         visitor.afterVisitPackage(this)
99         visitor.afterVisitItem(this)
100     }
101 
102     override fun acceptTypes(visitor: TypeVisitor) {
103         if (visitor.skip(this)) {
104             return
105         }
106 
107         for (unit in topLevelClasses()) {
108             unit.acceptTypes(visitor)
109         }
110     }
111 
112     companion object {
113         val comparator: Comparator<PackageItem> = Comparator { a, b -> a.qualifiedName().compareTo(b.qualifiedName()) }
114     }
115 }