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     val isDefault get() = qualifiedName().isEmpty()
37 
38     override fun parent(): PackageItem? = if (qualifiedName().isEmpty()) null else containingPackage()
39 
40     fun containingPackage(): PackageItem? {
41         val name = qualifiedName()
42         val lastDot = name.lastIndexOf('.')
43         return if (lastDot != -1) {
44             codebase.findPackage(name.substring(0, lastDot))
45         } else {
46             null
47         }
48     }
49 
50     /** Whether this package is empty */
51     fun empty() = topLevelClasses().none()
52 
53     override fun accept(visitor: ItemVisitor) {
54         if (visitor.skipEmptyPackages && empty()) {
55             return
56         }
57 
58         if (visitor is ApiVisitor) {
59             if (!emit) {
60                 return
61             }
62 
63             // For the API visitor packages are visited lazily; only when we encounter
64             // an unfiltered item within the class
65             topLevelClasses()
66                 .asSequence()
67                 .sortedWith(ClassItem.classNameSorter())
68                 .forEach {
69                     tick()
70                     it.accept(visitor)
71                 }
72 
73             if (visitor.visitingPackage) {
74                 visitor.visitingPackage = false
75                 visitor.afterVisitPackage(this)
76                 visitor.afterVisitItem(this)
77             }
78 
79             return
80         }
81 
82         if (visitor.skip(this)) {
83             return
84         }
85 
86         visitor.visitItem(this)
87         visitor.visitPackage(this)
88 
89         for (cls in topLevelClasses()) {
90             cls.accept(visitor)
91         }
92 
93         visitor.afterVisitPackage(this)
94         visitor.afterVisitItem(this)
95     }
96 
97     override fun acceptTypes(visitor: TypeVisitor) {
98         if (visitor.skip(this)) {
99             return
100         }
101 
102         for (unit in topLevelClasses()) {
103             unit.acceptTypes(visitor)
104         }
105     }
106 
107     companion object {
108         val comparator: Comparator<PackageItem> = Comparator { a, b -> a.qualifiedName().compareTo(b.qualifiedName()) }
109     }
110 }