1 /*
2  * Copyright (C) 2024 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.text
18 
19 import com.android.tools.metalava.model.ClassKind
20 import com.android.tools.metalava.model.ClassTypeItem
21 import com.android.tools.metalava.model.ModifierList
22 import com.android.tools.metalava.reporter.FileLocation
23 
24 /**
25  * Characteristics of a class apart from its members.
26  *
27  * This is basically everything that could appear on the line defining the class in the API
28  * signature file.
29  */
30 internal data class ClassCharacteristics(
31     /** The position of the class definition within the API signature file. */
32     val fileLocation: FileLocation,
33 
34     /** Name including package and full name. */
35     val qualifiedName: String,
36 
37     /**
38      * Full name, this is in addition to [qualifiedName] as it is possible for two classed to have
39      * the same qualified name but different full names. e.g. `a.b.c.D.E` in package `a.b.c` has a
40      * full name of `D.E` but in a package `a.b` has a full name of `c.D.E`. While those names would
41      * break naming conventions and so would be unlikely they are possible.
42      */
43     val fullName: String,
44 
45     /** The kind of the class. */
46     val classKind: ClassKind,
47 
48     /** The modifiers. */
49     val modifiers: ModifierList,
50 
51     /** The super class type . */
52     val superClassType: ClassTypeItem?,
53 // TODO(b/323168612): Add interface type strings.
54 ) {
55     /**
56      * Checks if the [cls] from different signature file can be merged with this [TextClassItem].
57      * For instance, `current.txt` and `system-current.txt` may contain equal class definitions with
58      * different class methods. This method is used to determine if the two [TextClassItem]s can be
59      * safely merged in such scenarios.
60      *
61      * @param cls [TextClassItem] to be checked if it is compatible with [this] and can be merged
62      * @return a Boolean value representing if [cls] is compatible with [this]
63      */
isCompatiblenull64     fun isCompatible(other: ClassCharacteristics): Boolean {
65         // TODO(b/323168612): Check super interface types and super class type of the two
66         // TextClassItem
67         return fullName == other.fullName &&
68             classKind == other.classKind &&
69             modifiers.equivalentTo(other.modifiers)
70     }
71 
72     companion object {
ofnull73         fun of(classItem: TextClassItem): ClassCharacteristics =
74             ClassCharacteristics(
75                 fileLocation = classItem.fileLocation,
76                 qualifiedName = classItem.qualifiedName,
77                 fullName = classItem.fullName(),
78                 classKind = classItem.classKind,
79                 modifiers = classItem.modifiers,
80                 superClassType = classItem.superClassType(),
81             )
82     }
83 }
84