xref: /aosp_15_r20/tools/asuite/aidegen/lib/source_locator.py (revision c2e18aaa1096c836b086f94603d04f4eb9cf37f5)
1*c2e18aaaSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*c2e18aaaSAndroid Build Coastguard Worker#
3*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2018 - The Android Open Source Project
4*c2e18aaaSAndroid Build Coastguard Worker#
5*c2e18aaaSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*c2e18aaaSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*c2e18aaaSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*c2e18aaaSAndroid Build Coastguard Worker#
9*c2e18aaaSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
10*c2e18aaaSAndroid Build Coastguard Worker#
11*c2e18aaaSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*c2e18aaaSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*c2e18aaaSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*c2e18aaaSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*c2e18aaaSAndroid Build Coastguard Worker# limitations under the License.
16*c2e18aaaSAndroid Build Coastguard Worker
17*c2e18aaaSAndroid Build Coastguard Worker"""ModuleData information."""
18*c2e18aaaSAndroid Build Coastguard Worker
19*c2e18aaaSAndroid Build Coastguard Workerfrom __future__ import absolute_import
20*c2e18aaaSAndroid Build Coastguard Worker
21*c2e18aaaSAndroid Build Coastguard Workerimport glob
22*c2e18aaaSAndroid Build Coastguard Workerimport logging
23*c2e18aaaSAndroid Build Coastguard Workerimport os
24*c2e18aaaSAndroid Build Coastguard Workerimport re
25*c2e18aaaSAndroid Build Coastguard Worker
26*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen import constant
27*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import common_util
28*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import module_info
29*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import project_config
30*c2e18aaaSAndroid Build Coastguard Worker
31*c2e18aaaSAndroid Build Coastguard Worker# Parse package name from the package declaration line of a java.
32*c2e18aaaSAndroid Build Coastguard Worker# Group matches "foo.bar" of line "package foo.bar;" or "package foo.bar"
33*c2e18aaaSAndroid Build Coastguard Worker_PACKAGE_RE = re.compile(r'\s*package\s+(?P<package>[^(;|\s)]+)\s*', re.I)
34*c2e18aaaSAndroid Build Coastguard Worker_ANDROID_SUPPORT_PATH_KEYWORD = 'prebuilts/sdk/current/'
35*c2e18aaaSAndroid Build Coastguard Worker
36*c2e18aaaSAndroid Build Coastguard Worker# File extensions
37*c2e18aaaSAndroid Build Coastguard Worker_JAVA_EXT = '.java'
38*c2e18aaaSAndroid Build Coastguard Worker_KOTLIN_EXT = '.kt'
39*c2e18aaaSAndroid Build Coastguard Worker_TARGET_FILES = [_JAVA_EXT, _KOTLIN_EXT]
40*c2e18aaaSAndroid Build Coastguard Worker_JARJAR_RULES_FILE = 'jarjar-rules.txt'
41*c2e18aaaSAndroid Build Coastguard Worker_KEY_JARJAR_RULES = 'jarjar_rules'
42*c2e18aaaSAndroid Build Coastguard Worker_TARGET_AAPT2_SRCJAR = constant.NAME_AAPT2 + constant.SRCJAR_EXT
43*c2e18aaaSAndroid Build Coastguard Worker_TARGET_BUILD_FILES = [_TARGET_AAPT2_SRCJAR, constant.TARGET_R_SRCJAR]
44*c2e18aaaSAndroid Build Coastguard Worker_IGNORE_DIRS = [
45*c2e18aaaSAndroid Build Coastguard Worker    # The java files under this directory have to be ignored because it will
46*c2e18aaaSAndroid Build Coastguard Worker    # cause duplicated classes by libcore/ojluni/src/main/java.
47*c2e18aaaSAndroid Build Coastguard Worker    'libcore/ojluni/src/lambda/java'
48*c2e18aaaSAndroid Build Coastguard Worker]
49*c2e18aaaSAndroid Build Coastguard Worker_ANDROID = 'android'
50*c2e18aaaSAndroid Build Coastguard Worker_REPACKAGES = 'repackaged'
51*c2e18aaaSAndroid Build Coastguard Worker_FRAMEWORK_SRCJARS_PATH = os.path.join(constant.FRAMEWORK_PATH,
52*c2e18aaaSAndroid Build Coastguard Worker                                       constant.FRAMEWORK_SRCJARS)
53*c2e18aaaSAndroid Build Coastguard Worker
54*c2e18aaaSAndroid Build Coastguard Worker
55*c2e18aaaSAndroid Build Coastguard Workerclass ModuleData:
56*c2e18aaaSAndroid Build Coastguard Worker    """ModuleData class.
57*c2e18aaaSAndroid Build Coastguard Worker
58*c2e18aaaSAndroid Build Coastguard Worker    Attributes:
59*c2e18aaaSAndroid Build Coastguard Worker        All following relative paths stand for the path relative to the android
60*c2e18aaaSAndroid Build Coastguard Worker        repo root.
61*c2e18aaaSAndroid Build Coastguard Worker
62*c2e18aaaSAndroid Build Coastguard Worker        module_path: A string of the relative path to the module.
63*c2e18aaaSAndroid Build Coastguard Worker        src_dirs: A list to keep the unique source folder relative paths.
64*c2e18aaaSAndroid Build Coastguard Worker        test_dirs: A list to keep the unique test folder relative paths.
65*c2e18aaaSAndroid Build Coastguard Worker        jar_files: A list to keep the unique jar file relative paths.
66*c2e18aaaSAndroid Build Coastguard Worker        r_java_paths: A list to keep the R folder paths to use in Eclipse.
67*c2e18aaaSAndroid Build Coastguard Worker        srcjar_paths: A list to keep the srcjar source root paths to use in
68*c2e18aaaSAndroid Build Coastguard Worker                      IntelliJ. Some modules' srcjar_paths will be removed when
69*c2e18aaaSAndroid Build Coastguard Worker                      run with the MultiProjectInfo.
70*c2e18aaaSAndroid Build Coastguard Worker        dep_paths: A list to keep the dependency modules' path.
71*c2e18aaaSAndroid Build Coastguard Worker        referenced_by_jar: A boolean to check if the module is referenced by a
72*c2e18aaaSAndroid Build Coastguard Worker                           jar file.
73*c2e18aaaSAndroid Build Coastguard Worker        build_targets: A set to keep the unique build target jar or srcjar file
74*c2e18aaaSAndroid Build Coastguard Worker                       relative paths which are ready to be rebuilt.
75*c2e18aaaSAndroid Build Coastguard Worker        missing_jars: A set to keep the jar file relative paths if it doesn't
76*c2e18aaaSAndroid Build Coastguard Worker                      exist.
77*c2e18aaaSAndroid Build Coastguard Worker        specific_soong_path: A string of the relative path to the module's
78*c2e18aaaSAndroid Build Coastguard Worker                             intermediates folder under out/.
79*c2e18aaaSAndroid Build Coastguard Worker    """
80*c2e18aaaSAndroid Build Coastguard Worker
81*c2e18aaaSAndroid Build Coastguard Worker    def __init__(self, module_name, module_data, depth):
82*c2e18aaaSAndroid Build Coastguard Worker        """Initialize ModuleData.
83*c2e18aaaSAndroid Build Coastguard Worker
84*c2e18aaaSAndroid Build Coastguard Worker        Args:
85*c2e18aaaSAndroid Build Coastguard Worker            module_name: Name of the module.
86*c2e18aaaSAndroid Build Coastguard Worker            module_data: A dictionary holding a module information.
87*c2e18aaaSAndroid Build Coastguard Worker            depth: An integer shows the depth of module dependency referenced by
88*c2e18aaaSAndroid Build Coastguard Worker                   source. Zero means the max module depth.
89*c2e18aaaSAndroid Build Coastguard Worker            For example:
90*c2e18aaaSAndroid Build Coastguard Worker                {
91*c2e18aaaSAndroid Build Coastguard Worker                    'class': ['APPS'],
92*c2e18aaaSAndroid Build Coastguard Worker                    'path': ['path/to/the/module'],
93*c2e18aaaSAndroid Build Coastguard Worker                    'depth': 0,
94*c2e18aaaSAndroid Build Coastguard Worker                    'dependencies': ['bouncycastle', 'ims-common'],
95*c2e18aaaSAndroid Build Coastguard Worker                    'srcs': [
96*c2e18aaaSAndroid Build Coastguard Worker                        'path/to/the/module/src/com/android/test.java',
97*c2e18aaaSAndroid Build Coastguard Worker                        'path/to/the/module/src/com/google/test.java',
98*c2e18aaaSAndroid Build Coastguard Worker                        'out/soong/.intermediates/path/to/the/module/test/src/
99*c2e18aaaSAndroid Build Coastguard Worker                         com/android/test.srcjar'
100*c2e18aaaSAndroid Build Coastguard Worker                    ],
101*c2e18aaaSAndroid Build Coastguard Worker                    'installed': ['out/target/product/generic_x86_64/
102*c2e18aaaSAndroid Build Coastguard Worker                                   system/framework/framework.jar'],
103*c2e18aaaSAndroid Build Coastguard Worker                    'jars': ['settings.jar'],
104*c2e18aaaSAndroid Build Coastguard Worker                    'jarjar_rules': ['jarjar-rules.txt']
105*c2e18aaaSAndroid Build Coastguard Worker                }
106*c2e18aaaSAndroid Build Coastguard Worker        """
107*c2e18aaaSAndroid Build Coastguard Worker        assert module_name, 'Module name can\'t be null.'
108*c2e18aaaSAndroid Build Coastguard Worker        assert module_data, 'Module data of %s can\'t be null.' % module_name
109*c2e18aaaSAndroid Build Coastguard Worker        self.module_name = module_name
110*c2e18aaaSAndroid Build Coastguard Worker        self.module_data = module_data
111*c2e18aaaSAndroid Build Coastguard Worker        self._init_module_path()
112*c2e18aaaSAndroid Build Coastguard Worker        self._init_module_depth(depth)
113*c2e18aaaSAndroid Build Coastguard Worker        self.src_dirs = []
114*c2e18aaaSAndroid Build Coastguard Worker        self.test_dirs = []
115*c2e18aaaSAndroid Build Coastguard Worker        self.jar_files = []
116*c2e18aaaSAndroid Build Coastguard Worker        self.r_java_paths = []
117*c2e18aaaSAndroid Build Coastguard Worker        self.srcjar_paths = []
118*c2e18aaaSAndroid Build Coastguard Worker        self.dep_paths = []
119*c2e18aaaSAndroid Build Coastguard Worker        self.referenced_by_jar = False
120*c2e18aaaSAndroid Build Coastguard Worker        self.build_targets = set()
121*c2e18aaaSAndroid Build Coastguard Worker        self.missing_jars = set()
122*c2e18aaaSAndroid Build Coastguard Worker        self.specific_soong_path = os.path.join(
123*c2e18aaaSAndroid Build Coastguard Worker            'out/soong/.intermediates', self.module_path, self.module_name)
124*c2e18aaaSAndroid Build Coastguard Worker
125*c2e18aaaSAndroid Build Coastguard Worker    def _is_app_module(self):
126*c2e18aaaSAndroid Build Coastguard Worker        """Check if the current module's class is APPS"""
127*c2e18aaaSAndroid Build Coastguard Worker        return self._check_key('class') and 'APPS' in self.module_data['class']
128*c2e18aaaSAndroid Build Coastguard Worker
129*c2e18aaaSAndroid Build Coastguard Worker    def _is_target_module(self):
130*c2e18aaaSAndroid Build Coastguard Worker        """Check if the current module is a target module.
131*c2e18aaaSAndroid Build Coastguard Worker
132*c2e18aaaSAndroid Build Coastguard Worker        A target module is the target project or a module under the
133*c2e18aaaSAndroid Build Coastguard Worker        target project and it's module depth is 0.
134*c2e18aaaSAndroid Build Coastguard Worker        For example: aidegen Settings framework
135*c2e18aaaSAndroid Build Coastguard Worker            The target projects are Settings and framework so they are also
136*c2e18aaaSAndroid Build Coastguard Worker            target modules. And the dependent module SettingsUnitTests's path
137*c2e18aaaSAndroid Build Coastguard Worker            is packages/apps/Settings/tests/unit so it also a target module.
138*c2e18aaaSAndroid Build Coastguard Worker        """
139*c2e18aaaSAndroid Build Coastguard Worker        return self.module_depth == 0
140*c2e18aaaSAndroid Build Coastguard Worker
141*c2e18aaaSAndroid Build Coastguard Worker    def _collect_r_srcs_paths(self):
142*c2e18aaaSAndroid Build Coastguard Worker        """Collect the source folder of R.java.
143*c2e18aaaSAndroid Build Coastguard Worker
144*c2e18aaaSAndroid Build Coastguard Worker        Check if the path of aapt2.srcjar or R.srcjar exists, these are both the
145*c2e18aaaSAndroid Build Coastguard Worker        values of key "srcjars" in module_data. If neither of the cases exists,
146*c2e18aaaSAndroid Build Coastguard Worker        build it onto an intermediates directory.
147*c2e18aaaSAndroid Build Coastguard Worker
148*c2e18aaaSAndroid Build Coastguard Worker        For IntelliJ, we can set the srcjar file as a source root for
149*c2e18aaaSAndroid Build Coastguard Worker        dependency. For Eclipse, we still use the R folder as dependencies until
150*c2e18aaaSAndroid Build Coastguard Worker        we figure out how to set srcjar file as dependency.
151*c2e18aaaSAndroid Build Coastguard Worker        # TODO(b/135594800): Set aapt2.srcjar or R.srcjar as a dependency in
152*c2e18aaaSAndroid Build Coastguard Worker                             Eclipse.
153*c2e18aaaSAndroid Build Coastguard Worker        """
154*c2e18aaaSAndroid Build Coastguard Worker        if (self._is_app_module() and self._is_target_module()
155*c2e18aaaSAndroid Build Coastguard Worker                and self._check_key(constant.KEY_SRCJARS)):
156*c2e18aaaSAndroid Build Coastguard Worker            for srcjar in self.module_data[constant.KEY_SRCJARS]:
157*c2e18aaaSAndroid Build Coastguard Worker                if not os.path.exists(common_util.get_abs_path(srcjar)):
158*c2e18aaaSAndroid Build Coastguard Worker                    self.build_targets.add(srcjar)
159*c2e18aaaSAndroid Build Coastguard Worker                self._collect_srcjar_path(srcjar)
160*c2e18aaaSAndroid Build Coastguard Worker                r_dir = self._get_r_dir(srcjar)
161*c2e18aaaSAndroid Build Coastguard Worker                if r_dir and r_dir not in self.r_java_paths:
162*c2e18aaaSAndroid Build Coastguard Worker                    self.r_java_paths.append(r_dir)
163*c2e18aaaSAndroid Build Coastguard Worker
164*c2e18aaaSAndroid Build Coastguard Worker    def _collect_srcjar_path(self, srcjar):
165*c2e18aaaSAndroid Build Coastguard Worker        """Collect the source folders from a srcjar path.
166*c2e18aaaSAndroid Build Coastguard Worker
167*c2e18aaaSAndroid Build Coastguard Worker        Set the aapt2.srcjar or R.srcjar as source root:
168*c2e18aaaSAndroid Build Coastguard Worker        Case aapt2.srcjar:
169*c2e18aaaSAndroid Build Coastguard Worker            The source path string is
170*c2e18aaaSAndroid Build Coastguard Worker            out/.../Bluetooth_intermediates/aapt2.srcjar.
171*c2e18aaaSAndroid Build Coastguard Worker        Case R.srcjar:
172*c2e18aaaSAndroid Build Coastguard Worker            The source path string is out/soong/.../gen/android/R.srcjar.
173*c2e18aaaSAndroid Build Coastguard Worker
174*c2e18aaaSAndroid Build Coastguard Worker        Args:
175*c2e18aaaSAndroid Build Coastguard Worker            srcjar: A file path string relative to ANDROID_BUILD_TOP, the build
176*c2e18aaaSAndroid Build Coastguard Worker                    target of the module to generate R.java.
177*c2e18aaaSAndroid Build Coastguard Worker        """
178*c2e18aaaSAndroid Build Coastguard Worker        if (os.path.basename(srcjar) in _TARGET_BUILD_FILES
179*c2e18aaaSAndroid Build Coastguard Worker                and srcjar not in self.srcjar_paths):
180*c2e18aaaSAndroid Build Coastguard Worker            self.srcjar_paths.append(srcjar)
181*c2e18aaaSAndroid Build Coastguard Worker
182*c2e18aaaSAndroid Build Coastguard Worker    def _collect_all_srcjar_paths(self):
183*c2e18aaaSAndroid Build Coastguard Worker        """Collect all srcjar files of target module as source folders.
184*c2e18aaaSAndroid Build Coastguard Worker
185*c2e18aaaSAndroid Build Coastguard Worker        Since the aidl files are built to *.java and collected in the
186*c2e18aaaSAndroid Build Coastguard Worker        aidl.srcjar file by the build system. AIDEGen needs to collect these
187*c2e18aaaSAndroid Build Coastguard Worker        aidl.srcjar files as the source root folders in IntelliJ. Furthermore,
188*c2e18aaaSAndroid Build Coastguard Worker        AIDEGen collects all *.srcjar files for other cases to fulfil the same
189*c2e18aaaSAndroid Build Coastguard Worker        purpose.
190*c2e18aaaSAndroid Build Coastguard Worker        """
191*c2e18aaaSAndroid Build Coastguard Worker        if self._is_target_module() and self._check_key(constant.KEY_SRCJARS):
192*c2e18aaaSAndroid Build Coastguard Worker            for srcjar in self.module_data[constant.KEY_SRCJARS]:
193*c2e18aaaSAndroid Build Coastguard Worker                if not os.path.exists(common_util.get_abs_path(srcjar)):
194*c2e18aaaSAndroid Build Coastguard Worker                    self.build_targets.add(srcjar)
195*c2e18aaaSAndroid Build Coastguard Worker                if srcjar not in self.srcjar_paths:
196*c2e18aaaSAndroid Build Coastguard Worker                    self.srcjar_paths.append(srcjar)
197*c2e18aaaSAndroid Build Coastguard Worker
198*c2e18aaaSAndroid Build Coastguard Worker    @staticmethod
199*c2e18aaaSAndroid Build Coastguard Worker    def _get_r_dir(srcjar):
200*c2e18aaaSAndroid Build Coastguard Worker        """Get the source folder of R.java for Eclipse.
201*c2e18aaaSAndroid Build Coastguard Worker
202*c2e18aaaSAndroid Build Coastguard Worker        Get the folder contains the R.java of aapt2.srcjar or R.srcjar:
203*c2e18aaaSAndroid Build Coastguard Worker        Case aapt2.srcjar:
204*c2e18aaaSAndroid Build Coastguard Worker            If the relative path of the aapt2.srcjar is a/b/aapt2.srcjar, the
205*c2e18aaaSAndroid Build Coastguard Worker            source root of the R.java is a/b/aapt2
206*c2e18aaaSAndroid Build Coastguard Worker        Case R.srcjar:
207*c2e18aaaSAndroid Build Coastguard Worker            If the relative path of the R.srcjar is a/b/android/R.srcjar, the
208*c2e18aaaSAndroid Build Coastguard Worker            source root of the R.java is a/b/aapt2/R
209*c2e18aaaSAndroid Build Coastguard Worker
210*c2e18aaaSAndroid Build Coastguard Worker        Args:
211*c2e18aaaSAndroid Build Coastguard Worker            srcjar: A file path string, the build target of the module to
212*c2e18aaaSAndroid Build Coastguard Worker                    generate R.java.
213*c2e18aaaSAndroid Build Coastguard Worker
214*c2e18aaaSAndroid Build Coastguard Worker        Returns:
215*c2e18aaaSAndroid Build Coastguard Worker            A relative source folder path string, and return None if the target
216*c2e18aaaSAndroid Build Coastguard Worker            file name is not aapt2.srcjar or R.srcjar.
217*c2e18aaaSAndroid Build Coastguard Worker        """
218*c2e18aaaSAndroid Build Coastguard Worker        target_folder, target_file = os.path.split(srcjar)
219*c2e18aaaSAndroid Build Coastguard Worker        base_dirname = os.path.basename(target_folder)
220*c2e18aaaSAndroid Build Coastguard Worker        if target_file == _TARGET_AAPT2_SRCJAR:
221*c2e18aaaSAndroid Build Coastguard Worker            return os.path.join(target_folder, constant.NAME_AAPT2)
222*c2e18aaaSAndroid Build Coastguard Worker        if target_file == constant.TARGET_R_SRCJAR and base_dirname == _ANDROID:
223*c2e18aaaSAndroid Build Coastguard Worker            return os.path.join(os.path.dirname(target_folder),
224*c2e18aaaSAndroid Build Coastguard Worker                                constant.NAME_AAPT2, 'R')
225*c2e18aaaSAndroid Build Coastguard Worker        return None
226*c2e18aaaSAndroid Build Coastguard Worker
227*c2e18aaaSAndroid Build Coastguard Worker    def _init_module_path(self):
228*c2e18aaaSAndroid Build Coastguard Worker        """Initialize self.module_path."""
229*c2e18aaaSAndroid Build Coastguard Worker        self.module_path = (self.module_data[constant.KEY_PATH][0]
230*c2e18aaaSAndroid Build Coastguard Worker                            if self._check_key(constant.KEY_PATH) else '')
231*c2e18aaaSAndroid Build Coastguard Worker
232*c2e18aaaSAndroid Build Coastguard Worker    def _init_module_depth(self, depth):
233*c2e18aaaSAndroid Build Coastguard Worker        """Initialize module depth's settings.
234*c2e18aaaSAndroid Build Coastguard Worker
235*c2e18aaaSAndroid Build Coastguard Worker        Set the module's depth from module info when user have -d parameter.
236*c2e18aaaSAndroid Build Coastguard Worker        Set the -d value from user input, default to 0.
237*c2e18aaaSAndroid Build Coastguard Worker
238*c2e18aaaSAndroid Build Coastguard Worker        Args:
239*c2e18aaaSAndroid Build Coastguard Worker            depth: the depth to be set.
240*c2e18aaaSAndroid Build Coastguard Worker        """
241*c2e18aaaSAndroid Build Coastguard Worker        self.module_depth = (int(self.module_data[constant.KEY_DEPTH])
242*c2e18aaaSAndroid Build Coastguard Worker                             if depth else 0)
243*c2e18aaaSAndroid Build Coastguard Worker        self.depth_by_source = depth
244*c2e18aaaSAndroid Build Coastguard Worker
245*c2e18aaaSAndroid Build Coastguard Worker    def _is_android_supported_module(self):
246*c2e18aaaSAndroid Build Coastguard Worker        """Determine if this is an Android supported module."""
247*c2e18aaaSAndroid Build Coastguard Worker        return common_util.is_source_under_relative_path(
248*c2e18aaaSAndroid Build Coastguard Worker            self.module_path, _ANDROID_SUPPORT_PATH_KEYWORD)
249*c2e18aaaSAndroid Build Coastguard Worker
250*c2e18aaaSAndroid Build Coastguard Worker    def _check_jarjar_rules_exist(self):
251*c2e18aaaSAndroid Build Coastguard Worker        """Check if jarjar rules exist."""
252*c2e18aaaSAndroid Build Coastguard Worker        return (_KEY_JARJAR_RULES in self.module_data and
253*c2e18aaaSAndroid Build Coastguard Worker                self.module_data[_KEY_JARJAR_RULES][0] == _JARJAR_RULES_FILE)
254*c2e18aaaSAndroid Build Coastguard Worker
255*c2e18aaaSAndroid Build Coastguard Worker    def _check_jars_exist(self):
256*c2e18aaaSAndroid Build Coastguard Worker        """Check if jars exist."""
257*c2e18aaaSAndroid Build Coastguard Worker        return self._check_key(constant.KEY_JARS)
258*c2e18aaaSAndroid Build Coastguard Worker
259*c2e18aaaSAndroid Build Coastguard Worker    def _check_classes_jar_exist(self):
260*c2e18aaaSAndroid Build Coastguard Worker        """Check if classes_jar exist."""
261*c2e18aaaSAndroid Build Coastguard Worker        return self._check_key(constant.KEY_CLASSES_JAR)
262*c2e18aaaSAndroid Build Coastguard Worker
263*c2e18aaaSAndroid Build Coastguard Worker    def _collect_srcs_paths(self):
264*c2e18aaaSAndroid Build Coastguard Worker        """Collect source folder paths in src_dirs from module_data['srcs']."""
265*c2e18aaaSAndroid Build Coastguard Worker        if self._check_key(constant.KEY_SRCS):
266*c2e18aaaSAndroid Build Coastguard Worker            scanned_dirs = set()
267*c2e18aaaSAndroid Build Coastguard Worker            for src_item in self.module_data[constant.KEY_SRCS]:
268*c2e18aaaSAndroid Build Coastguard Worker                src_dir = None
269*c2e18aaaSAndroid Build Coastguard Worker                src_item = os.path.relpath(src_item)
270*c2e18aaaSAndroid Build Coastguard Worker                if common_util.is_target(src_item, _TARGET_FILES):
271*c2e18aaaSAndroid Build Coastguard Worker                    # Only scan one java file in each source directories.
272*c2e18aaaSAndroid Build Coastguard Worker                    src_item_dir = os.path.dirname(src_item)
273*c2e18aaaSAndroid Build Coastguard Worker                    if src_item_dir not in scanned_dirs:
274*c2e18aaaSAndroid Build Coastguard Worker                        scanned_dirs.add(src_item_dir)
275*c2e18aaaSAndroid Build Coastguard Worker                        src_dir = self._get_source_folder(src_item)
276*c2e18aaaSAndroid Build Coastguard Worker                else:
277*c2e18aaaSAndroid Build Coastguard Worker                    # To record what files except java and kt in the srcs.
278*c2e18aaaSAndroid Build Coastguard Worker                    logging.debug('%s is not in parsing scope.', src_item)
279*c2e18aaaSAndroid Build Coastguard Worker                if src_dir:
280*c2e18aaaSAndroid Build Coastguard Worker                    self._add_to_source_or_test_dirs(
281*c2e18aaaSAndroid Build Coastguard Worker                        self._switch_repackaged(src_dir))
282*c2e18aaaSAndroid Build Coastguard Worker
283*c2e18aaaSAndroid Build Coastguard Worker    def _check_key(self, key):
284*c2e18aaaSAndroid Build Coastguard Worker        """Check if key is in self.module_data and not empty.
285*c2e18aaaSAndroid Build Coastguard Worker
286*c2e18aaaSAndroid Build Coastguard Worker        Args:
287*c2e18aaaSAndroid Build Coastguard Worker            key: the key to be checked.
288*c2e18aaaSAndroid Build Coastguard Worker        """
289*c2e18aaaSAndroid Build Coastguard Worker        return key in self.module_data and self.module_data[key]
290*c2e18aaaSAndroid Build Coastguard Worker
291*c2e18aaaSAndroid Build Coastguard Worker    def _add_to_source_or_test_dirs(self, src_dir):
292*c2e18aaaSAndroid Build Coastguard Worker        """Add folder to source or test directories.
293*c2e18aaaSAndroid Build Coastguard Worker
294*c2e18aaaSAndroid Build Coastguard Worker        Args:
295*c2e18aaaSAndroid Build Coastguard Worker            src_dir: the directory to be added.
296*c2e18aaaSAndroid Build Coastguard Worker        """
297*c2e18aaaSAndroid Build Coastguard Worker        if (src_dir not in _IGNORE_DIRS and src_dir not in self.src_dirs
298*c2e18aaaSAndroid Build Coastguard Worker                and src_dir not in self.test_dirs):
299*c2e18aaaSAndroid Build Coastguard Worker            if self._is_test_module(src_dir):
300*c2e18aaaSAndroid Build Coastguard Worker                self.test_dirs.append(src_dir)
301*c2e18aaaSAndroid Build Coastguard Worker            else:
302*c2e18aaaSAndroid Build Coastguard Worker                self.src_dirs.append(src_dir)
303*c2e18aaaSAndroid Build Coastguard Worker
304*c2e18aaaSAndroid Build Coastguard Worker    @staticmethod
305*c2e18aaaSAndroid Build Coastguard Worker    def _is_test_module(src_dir):
306*c2e18aaaSAndroid Build Coastguard Worker        """Check if the module path is a test module path.
307*c2e18aaaSAndroid Build Coastguard Worker
308*c2e18aaaSAndroid Build Coastguard Worker        Args:
309*c2e18aaaSAndroid Build Coastguard Worker            src_dir: the directory to be checked.
310*c2e18aaaSAndroid Build Coastguard Worker
311*c2e18aaaSAndroid Build Coastguard Worker        Returns:
312*c2e18aaaSAndroid Build Coastguard Worker            True if module path is a test module path, otherwise False.
313*c2e18aaaSAndroid Build Coastguard Worker        """
314*c2e18aaaSAndroid Build Coastguard Worker        return constant.KEY_TESTS in src_dir.split(os.sep)
315*c2e18aaaSAndroid Build Coastguard Worker
316*c2e18aaaSAndroid Build Coastguard Worker    def _get_source_folder(self, java_file):
317*c2e18aaaSAndroid Build Coastguard Worker        """Parsing a java to get the package name to filter out source path.
318*c2e18aaaSAndroid Build Coastguard Worker
319*c2e18aaaSAndroid Build Coastguard Worker        Args:
320*c2e18aaaSAndroid Build Coastguard Worker            java_file: A string, the java file with relative path.
321*c2e18aaaSAndroid Build Coastguard Worker                       e.g. path/to/the/java/file.java
322*c2e18aaaSAndroid Build Coastguard Worker
323*c2e18aaaSAndroid Build Coastguard Worker        Returns:
324*c2e18aaaSAndroid Build Coastguard Worker            source_folder: A string of path to source folder(e.g. src/main/java)
325*c2e18aaaSAndroid Build Coastguard Worker                           or none when it failed to get package name.
326*c2e18aaaSAndroid Build Coastguard Worker        """
327*c2e18aaaSAndroid Build Coastguard Worker        abs_java_path = common_util.get_abs_path(java_file)
328*c2e18aaaSAndroid Build Coastguard Worker        if os.path.exists(abs_java_path):
329*c2e18aaaSAndroid Build Coastguard Worker            package_name = self._get_package_name(abs_java_path)
330*c2e18aaaSAndroid Build Coastguard Worker            if package_name:
331*c2e18aaaSAndroid Build Coastguard Worker                return self._parse_source_path(java_file, package_name)
332*c2e18aaaSAndroid Build Coastguard Worker        return None
333*c2e18aaaSAndroid Build Coastguard Worker
334*c2e18aaaSAndroid Build Coastguard Worker    @staticmethod
335*c2e18aaaSAndroid Build Coastguard Worker    def _parse_source_path(java_file, package_name):
336*c2e18aaaSAndroid Build Coastguard Worker        """Parse the source path by filter out the package name.
337*c2e18aaaSAndroid Build Coastguard Worker
338*c2e18aaaSAndroid Build Coastguard Worker        Case 1:
339*c2e18aaaSAndroid Build Coastguard Worker        java file: a/b/c/d/e.java
340*c2e18aaaSAndroid Build Coastguard Worker        package name: c.d
341*c2e18aaaSAndroid Build Coastguard Worker        The source folder is a/b.
342*c2e18aaaSAndroid Build Coastguard Worker
343*c2e18aaaSAndroid Build Coastguard Worker        Case 2:
344*c2e18aaaSAndroid Build Coastguard Worker        java file: a/b/c.d/e.java
345*c2e18aaaSAndroid Build Coastguard Worker        package name: c.d
346*c2e18aaaSAndroid Build Coastguard Worker        The source folder is a/b.
347*c2e18aaaSAndroid Build Coastguard Worker
348*c2e18aaaSAndroid Build Coastguard Worker        Case 3:
349*c2e18aaaSAndroid Build Coastguard Worker        java file: a/b/c/d/e.java
350*c2e18aaaSAndroid Build Coastguard Worker        package name: x.y
351*c2e18aaaSAndroid Build Coastguard Worker        The source folder is a/b/c/d.
352*c2e18aaaSAndroid Build Coastguard Worker
353*c2e18aaaSAndroid Build Coastguard Worker        Case 4:
354*c2e18aaaSAndroid Build Coastguard Worker        java file: a/b/c.d/e/c/d/f.java
355*c2e18aaaSAndroid Build Coastguard Worker        package name: c.d
356*c2e18aaaSAndroid Build Coastguard Worker        The source folder is a/b/c.d/e.
357*c2e18aaaSAndroid Build Coastguard Worker
358*c2e18aaaSAndroid Build Coastguard Worker        Case 5:
359*c2e18aaaSAndroid Build Coastguard Worker        java file: a/b/c.d/e/c.d/e/f.java
360*c2e18aaaSAndroid Build Coastguard Worker        package name: c.d.e
361*c2e18aaaSAndroid Build Coastguard Worker        The source folder is a/b/c.d/e.
362*c2e18aaaSAndroid Build Coastguard Worker
363*c2e18aaaSAndroid Build Coastguard Worker        Args:
364*c2e18aaaSAndroid Build Coastguard Worker            java_file: A string of the java file relative path.
365*c2e18aaaSAndroid Build Coastguard Worker            package_name: A string of the java file's package name.
366*c2e18aaaSAndroid Build Coastguard Worker
367*c2e18aaaSAndroid Build Coastguard Worker        Returns:
368*c2e18aaaSAndroid Build Coastguard Worker            A string, the source folder path.
369*c2e18aaaSAndroid Build Coastguard Worker        """
370*c2e18aaaSAndroid Build Coastguard Worker        java_file_name = os.path.basename(java_file)
371*c2e18aaaSAndroid Build Coastguard Worker        pattern = r'%s/%s$' % (package_name, java_file_name)
372*c2e18aaaSAndroid Build Coastguard Worker        search_result = re.search(pattern, java_file)
373*c2e18aaaSAndroid Build Coastguard Worker        if search_result:
374*c2e18aaaSAndroid Build Coastguard Worker            return java_file[:search_result.start()].strip(os.sep)
375*c2e18aaaSAndroid Build Coastguard Worker        return os.path.dirname(java_file)
376*c2e18aaaSAndroid Build Coastguard Worker
377*c2e18aaaSAndroid Build Coastguard Worker    @staticmethod
378*c2e18aaaSAndroid Build Coastguard Worker    def _switch_repackaged(src_dir):
379*c2e18aaaSAndroid Build Coastguard Worker        """Changes the directory to repackaged if it does exist.
380*c2e18aaaSAndroid Build Coastguard Worker
381*c2e18aaaSAndroid Build Coastguard Worker        Args:
382*c2e18aaaSAndroid Build Coastguard Worker            src_dir: a string of relative path.
383*c2e18aaaSAndroid Build Coastguard Worker
384*c2e18aaaSAndroid Build Coastguard Worker        Returns:
385*c2e18aaaSAndroid Build Coastguard Worker            The source folder under repackaged if it exists, otherwise the
386*c2e18aaaSAndroid Build Coastguard Worker            original one.
387*c2e18aaaSAndroid Build Coastguard Worker        """
388*c2e18aaaSAndroid Build Coastguard Worker        root_path = common_util.get_android_root_dir()
389*c2e18aaaSAndroid Build Coastguard Worker        dir_list = src_dir.split(os.sep)
390*c2e18aaaSAndroid Build Coastguard Worker        for i in range(1, len(dir_list)):
391*c2e18aaaSAndroid Build Coastguard Worker            tmp_dir = dir_list.copy()
392*c2e18aaaSAndroid Build Coastguard Worker            tmp_dir.insert(i, _REPACKAGES)
393*c2e18aaaSAndroid Build Coastguard Worker            real_path = os.path.join(root_path, os.path.join(*tmp_dir))
394*c2e18aaaSAndroid Build Coastguard Worker            if os.path.exists(real_path):
395*c2e18aaaSAndroid Build Coastguard Worker                return os.path.relpath(real_path, root_path)
396*c2e18aaaSAndroid Build Coastguard Worker        return src_dir
397*c2e18aaaSAndroid Build Coastguard Worker
398*c2e18aaaSAndroid Build Coastguard Worker    @staticmethod
399*c2e18aaaSAndroid Build Coastguard Worker    def _get_package_name(abs_java_path):
400*c2e18aaaSAndroid Build Coastguard Worker        """Get the package name by parsing a java file.
401*c2e18aaaSAndroid Build Coastguard Worker
402*c2e18aaaSAndroid Build Coastguard Worker        Args:
403*c2e18aaaSAndroid Build Coastguard Worker            abs_java_path: A string of the java file with absolute path.
404*c2e18aaaSAndroid Build Coastguard Worker                           e.g. /root/path/to/the/java/file.java
405*c2e18aaaSAndroid Build Coastguard Worker
406*c2e18aaaSAndroid Build Coastguard Worker        Returns:
407*c2e18aaaSAndroid Build Coastguard Worker            package_name: A string of package name.
408*c2e18aaaSAndroid Build Coastguard Worker        """
409*c2e18aaaSAndroid Build Coastguard Worker        package_name = None
410*c2e18aaaSAndroid Build Coastguard Worker        with open(abs_java_path, 'r', encoding='utf8') as data:
411*c2e18aaaSAndroid Build Coastguard Worker            for line in data.read().splitlines():
412*c2e18aaaSAndroid Build Coastguard Worker                match = _PACKAGE_RE.match(line)
413*c2e18aaaSAndroid Build Coastguard Worker                if match:
414*c2e18aaaSAndroid Build Coastguard Worker                    package_name = match.group('package')
415*c2e18aaaSAndroid Build Coastguard Worker                    break
416*c2e18aaaSAndroid Build Coastguard Worker        return package_name
417*c2e18aaaSAndroid Build Coastguard Worker
418*c2e18aaaSAndroid Build Coastguard Worker    def _append_jar_file(self, jar_path):
419*c2e18aaaSAndroid Build Coastguard Worker        """Append a path to the jar file into self.jar_files if it's exists.
420*c2e18aaaSAndroid Build Coastguard Worker
421*c2e18aaaSAndroid Build Coastguard Worker        Args:
422*c2e18aaaSAndroid Build Coastguard Worker            jar_path: A path supposed to be a jar file.
423*c2e18aaaSAndroid Build Coastguard Worker
424*c2e18aaaSAndroid Build Coastguard Worker        Returns:
425*c2e18aaaSAndroid Build Coastguard Worker            Boolean: True if jar_path is an existing jar file.
426*c2e18aaaSAndroid Build Coastguard Worker        """
427*c2e18aaaSAndroid Build Coastguard Worker        if common_util.is_target(jar_path, constant.TARGET_LIBS):
428*c2e18aaaSAndroid Build Coastguard Worker            self.referenced_by_jar = True
429*c2e18aaaSAndroid Build Coastguard Worker            if os.path.isfile(common_util.get_abs_path(jar_path)):
430*c2e18aaaSAndroid Build Coastguard Worker                if jar_path not in self.jar_files:
431*c2e18aaaSAndroid Build Coastguard Worker                    self.jar_files.append(jar_path)
432*c2e18aaaSAndroid Build Coastguard Worker            else:
433*c2e18aaaSAndroid Build Coastguard Worker                self.missing_jars.add(jar_path)
434*c2e18aaaSAndroid Build Coastguard Worker            return True
435*c2e18aaaSAndroid Build Coastguard Worker        return False
436*c2e18aaaSAndroid Build Coastguard Worker
437*c2e18aaaSAndroid Build Coastguard Worker    def _append_classes_jar(self):
438*c2e18aaaSAndroid Build Coastguard Worker        """Append the jar file as dependency for prebuilt modules."""
439*c2e18aaaSAndroid Build Coastguard Worker        for jar in self.module_data[constant.KEY_CLASSES_JAR]:
440*c2e18aaaSAndroid Build Coastguard Worker            if self._append_jar_file(jar):
441*c2e18aaaSAndroid Build Coastguard Worker                break
442*c2e18aaaSAndroid Build Coastguard Worker
443*c2e18aaaSAndroid Build Coastguard Worker    def _append_jar_from_installed(self, specific_dir=None):
444*c2e18aaaSAndroid Build Coastguard Worker        """Append a jar file's path to the list of jar_files with matching
445*c2e18aaaSAndroid Build Coastguard Worker        path_prefix.
446*c2e18aaaSAndroid Build Coastguard Worker
447*c2e18aaaSAndroid Build Coastguard Worker        There might be more than one jar in "installed" parameter and only the
448*c2e18aaaSAndroid Build Coastguard Worker        first jar file is returned. If specific_dir is set, the jar file must be
449*c2e18aaaSAndroid Build Coastguard Worker        under the specific directory or its sub-directory.
450*c2e18aaaSAndroid Build Coastguard Worker
451*c2e18aaaSAndroid Build Coastguard Worker        Args:
452*c2e18aaaSAndroid Build Coastguard Worker            specific_dir: A string of path.
453*c2e18aaaSAndroid Build Coastguard Worker        """
454*c2e18aaaSAndroid Build Coastguard Worker        if self._check_key(constant.KEY_INSTALLED):
455*c2e18aaaSAndroid Build Coastguard Worker            for jar in self.module_data[constant.KEY_INSTALLED]:
456*c2e18aaaSAndroid Build Coastguard Worker                if specific_dir and not jar.startswith(specific_dir):
457*c2e18aaaSAndroid Build Coastguard Worker                    continue
458*c2e18aaaSAndroid Build Coastguard Worker                if self._append_jar_file(jar):
459*c2e18aaaSAndroid Build Coastguard Worker                    break
460*c2e18aaaSAndroid Build Coastguard Worker
461*c2e18aaaSAndroid Build Coastguard Worker    def _set_jars_jarfile(self):
462*c2e18aaaSAndroid Build Coastguard Worker        """Append prebuilt jars of module into self.jar_files.
463*c2e18aaaSAndroid Build Coastguard Worker
464*c2e18aaaSAndroid Build Coastguard Worker        Some modules' sources are prebuilt jar files instead of source java
465*c2e18aaaSAndroid Build Coastguard Worker        files. The jar files can be imported into IntelliJ as a dependency
466*c2e18aaaSAndroid Build Coastguard Worker        directly. There is only jar file name in self.module_data['jars'], it
467*c2e18aaaSAndroid Build Coastguard Worker        has to be combined with self.module_data['path'] to append into
468*c2e18aaaSAndroid Build Coastguard Worker        self.jar_files.
469*c2e18aaaSAndroid Build Coastguard Worker        Once the file doesn't exist, it's not assumed to be a prebuilt jar so
470*c2e18aaaSAndroid Build Coastguard Worker        that we can ignore it.
471*c2e18aaaSAndroid Build Coastguard Worker        # TODO(b/141959125): Collect the correct prebuilt jar files by jdeps.go.
472*c2e18aaaSAndroid Build Coastguard Worker
473*c2e18aaaSAndroid Build Coastguard Worker        For example:
474*c2e18aaaSAndroid Build Coastguard Worker        'asm-6.0': {
475*c2e18aaaSAndroid Build Coastguard Worker            'jars': [
476*c2e18aaaSAndroid Build Coastguard Worker                'asm-6.0.jar'
477*c2e18aaaSAndroid Build Coastguard Worker            ],
478*c2e18aaaSAndroid Build Coastguard Worker            'path': [
479*c2e18aaaSAndroid Build Coastguard Worker                'prebuilts/misc/common/asm'
480*c2e18aaaSAndroid Build Coastguard Worker            ],
481*c2e18aaaSAndroid Build Coastguard Worker        },
482*c2e18aaaSAndroid Build Coastguard Worker        Path to the jar file is prebuilts/misc/common/asm/asm-6.0.jar.
483*c2e18aaaSAndroid Build Coastguard Worker        """
484*c2e18aaaSAndroid Build Coastguard Worker        if self._check_key(constant.KEY_JARS):
485*c2e18aaaSAndroid Build Coastguard Worker            for jar_name in self.module_data[constant.KEY_JARS]:
486*c2e18aaaSAndroid Build Coastguard Worker                if self._check_key(constant.KEY_INSTALLED):
487*c2e18aaaSAndroid Build Coastguard Worker                    self._append_jar_from_installed()
488*c2e18aaaSAndroid Build Coastguard Worker                else:
489*c2e18aaaSAndroid Build Coastguard Worker                    jar_path = os.path.join(self.module_path, jar_name)
490*c2e18aaaSAndroid Build Coastguard Worker                    jar_abs = common_util.get_abs_path(jar_path)
491*c2e18aaaSAndroid Build Coastguard Worker                    if not os.path.isfile(jar_abs) and jar_name.endswith(
492*c2e18aaaSAndroid Build Coastguard Worker                            'prebuilt.jar'):
493*c2e18aaaSAndroid Build Coastguard Worker                        rel_path = self._get_jar_path_from_prebuilts(jar_name)
494*c2e18aaaSAndroid Build Coastguard Worker                        if rel_path:
495*c2e18aaaSAndroid Build Coastguard Worker                            jar_path = rel_path
496*c2e18aaaSAndroid Build Coastguard Worker                    if os.path.exists(common_util.get_abs_path(jar_path)):
497*c2e18aaaSAndroid Build Coastguard Worker                        self._append_jar_file(jar_path)
498*c2e18aaaSAndroid Build Coastguard Worker
499*c2e18aaaSAndroid Build Coastguard Worker    @staticmethod
500*c2e18aaaSAndroid Build Coastguard Worker    def _get_jar_path_from_prebuilts(jar_name):
501*c2e18aaaSAndroid Build Coastguard Worker        """Get prebuilt jar file from prebuilts folder.
502*c2e18aaaSAndroid Build Coastguard Worker
503*c2e18aaaSAndroid Build Coastguard Worker        If the prebuilt jar file we get from method _set_jars_jarfile() does not
504*c2e18aaaSAndroid Build Coastguard Worker        exist, we should search the prebuilt jar file in prebuilts folder.
505*c2e18aaaSAndroid Build Coastguard Worker        For example:
506*c2e18aaaSAndroid Build Coastguard Worker        'platformprotos': {
507*c2e18aaaSAndroid Build Coastguard Worker            'jars': [
508*c2e18aaaSAndroid Build Coastguard Worker                'platformprotos-prebuilt.jar'
509*c2e18aaaSAndroid Build Coastguard Worker            ],
510*c2e18aaaSAndroid Build Coastguard Worker            'path': [
511*c2e18aaaSAndroid Build Coastguard Worker                'frameworks/base'
512*c2e18aaaSAndroid Build Coastguard Worker            ],
513*c2e18aaaSAndroid Build Coastguard Worker        },
514*c2e18aaaSAndroid Build Coastguard Worker        We get an incorrect path: 'frameworks/base/platformprotos-prebuilt.jar'
515*c2e18aaaSAndroid Build Coastguard Worker        If the file does not exist, we should search the file name from
516*c2e18aaaSAndroid Build Coastguard Worker        prebuilts folder. If we can get the correct path from 'prebuilts', we
517*c2e18aaaSAndroid Build Coastguard Worker        can replace it with the incorrect path.
518*c2e18aaaSAndroid Build Coastguard Worker
519*c2e18aaaSAndroid Build Coastguard Worker        Args:
520*c2e18aaaSAndroid Build Coastguard Worker            jar_name: The prebuilt jar file name.
521*c2e18aaaSAndroid Build Coastguard Worker
522*c2e18aaaSAndroid Build Coastguard Worker        Return:
523*c2e18aaaSAndroid Build Coastguard Worker            A relative prebuilt jar file path if found, otherwise None.
524*c2e18aaaSAndroid Build Coastguard Worker        """
525*c2e18aaaSAndroid Build Coastguard Worker        rel_path = ''
526*c2e18aaaSAndroid Build Coastguard Worker        search = os.sep.join(
527*c2e18aaaSAndroid Build Coastguard Worker            [common_util.get_android_root_dir(), 'prebuilts/**', jar_name])
528*c2e18aaaSAndroid Build Coastguard Worker        results = glob.glob(search, recursive=True)
529*c2e18aaaSAndroid Build Coastguard Worker        if results:
530*c2e18aaaSAndroid Build Coastguard Worker            jar_abs = results[0]
531*c2e18aaaSAndroid Build Coastguard Worker            rel_path = os.path.relpath(
532*c2e18aaaSAndroid Build Coastguard Worker                jar_abs, common_util.get_android_root_dir())
533*c2e18aaaSAndroid Build Coastguard Worker        return rel_path
534*c2e18aaaSAndroid Build Coastguard Worker
535*c2e18aaaSAndroid Build Coastguard Worker    def _collect_specific_jars(self):
536*c2e18aaaSAndroid Build Coastguard Worker        """Collect specific types of jar files."""
537*c2e18aaaSAndroid Build Coastguard Worker        if self._is_android_supported_module():
538*c2e18aaaSAndroid Build Coastguard Worker            self._append_jar_from_installed()
539*c2e18aaaSAndroid Build Coastguard Worker        elif self._check_jarjar_rules_exist():
540*c2e18aaaSAndroid Build Coastguard Worker            self._append_jar_from_installed(self.specific_soong_path)
541*c2e18aaaSAndroid Build Coastguard Worker        elif self._check_jars_exist():
542*c2e18aaaSAndroid Build Coastguard Worker            self._set_jars_jarfile()
543*c2e18aaaSAndroid Build Coastguard Worker
544*c2e18aaaSAndroid Build Coastguard Worker    def _collect_classes_jars(self):
545*c2e18aaaSAndroid Build Coastguard Worker        """Collect classes jar files."""
546*c2e18aaaSAndroid Build Coastguard Worker        # If there is no source/tests folder of the module, reference the
547*c2e18aaaSAndroid Build Coastguard Worker        # module by jar.
548*c2e18aaaSAndroid Build Coastguard Worker        if not self.src_dirs and not self.test_dirs:
549*c2e18aaaSAndroid Build Coastguard Worker            # Add the classes.jar from the classes_jar attribute as
550*c2e18aaaSAndroid Build Coastguard Worker            # dependency if it exists. If the classes.jar doesn't exist,
551*c2e18aaaSAndroid Build Coastguard Worker            # find the jar file from the installed attribute and add the jar
552*c2e18aaaSAndroid Build Coastguard Worker            # as dependency.
553*c2e18aaaSAndroid Build Coastguard Worker            if self._check_classes_jar_exist():
554*c2e18aaaSAndroid Build Coastguard Worker                self._append_classes_jar()
555*c2e18aaaSAndroid Build Coastguard Worker            else:
556*c2e18aaaSAndroid Build Coastguard Worker                self._append_jar_from_installed()
557*c2e18aaaSAndroid Build Coastguard Worker
558*c2e18aaaSAndroid Build Coastguard Worker    def _collect_srcs_and_r_srcs_paths(self):
559*c2e18aaaSAndroid Build Coastguard Worker        """Collect source and R source folder paths for the module."""
560*c2e18aaaSAndroid Build Coastguard Worker        self._collect_specific_jars()
561*c2e18aaaSAndroid Build Coastguard Worker        self._collect_srcs_paths()
562*c2e18aaaSAndroid Build Coastguard Worker        self._collect_classes_jars()
563*c2e18aaaSAndroid Build Coastguard Worker        self._collect_r_srcs_paths()
564*c2e18aaaSAndroid Build Coastguard Worker        self._collect_all_srcjar_paths()
565*c2e18aaaSAndroid Build Coastguard Worker
566*c2e18aaaSAndroid Build Coastguard Worker    def _collect_missing_jars(self):
567*c2e18aaaSAndroid Build Coastguard Worker        """Collect missing jar files to rebuild them."""
568*c2e18aaaSAndroid Build Coastguard Worker        if self.referenced_by_jar and self.missing_jars:
569*c2e18aaaSAndroid Build Coastguard Worker            self.build_targets |= self.missing_jars
570*c2e18aaaSAndroid Build Coastguard Worker
571*c2e18aaaSAndroid Build Coastguard Worker    def _collect_dep_paths(self):
572*c2e18aaaSAndroid Build Coastguard Worker        """Collects the path of dependency modules."""
573*c2e18aaaSAndroid Build Coastguard Worker        config = project_config.ProjectConfig.get_instance()
574*c2e18aaaSAndroid Build Coastguard Worker        modules_info = config.atest_module_info
575*c2e18aaaSAndroid Build Coastguard Worker        self.dep_paths = []
576*c2e18aaaSAndroid Build Coastguard Worker        if self.module_path != constant.FRAMEWORK_PATH:
577*c2e18aaaSAndroid Build Coastguard Worker            self.dep_paths.append(constant.FRAMEWORK_PATH)
578*c2e18aaaSAndroid Build Coastguard Worker        self.dep_paths.append(_FRAMEWORK_SRCJARS_PATH)
579*c2e18aaaSAndroid Build Coastguard Worker        if self.module_path != constant.LIBCORE_PATH:
580*c2e18aaaSAndroid Build Coastguard Worker            self.dep_paths.append(constant.LIBCORE_PATH)
581*c2e18aaaSAndroid Build Coastguard Worker        for module in self.module_data.get(constant.KEY_DEPENDENCIES, []):
582*c2e18aaaSAndroid Build Coastguard Worker            for path in modules_info.get_paths(module):
583*c2e18aaaSAndroid Build Coastguard Worker                if path not in self.dep_paths and path != self.module_path:
584*c2e18aaaSAndroid Build Coastguard Worker                    self.dep_paths.append(path)
585*c2e18aaaSAndroid Build Coastguard Worker
586*c2e18aaaSAndroid Build Coastguard Worker    def locate_sources_path(self):
587*c2e18aaaSAndroid Build Coastguard Worker        """Locate source folders' paths or jar files."""
588*c2e18aaaSAndroid Build Coastguard Worker        # Check if users need to reference source according to source depth.
589*c2e18aaaSAndroid Build Coastguard Worker        if not self.module_depth <= self.depth_by_source:
590*c2e18aaaSAndroid Build Coastguard Worker            self._append_jar_from_installed(self.specific_soong_path)
591*c2e18aaaSAndroid Build Coastguard Worker        else:
592*c2e18aaaSAndroid Build Coastguard Worker            self._collect_srcs_and_r_srcs_paths()
593*c2e18aaaSAndroid Build Coastguard Worker        self._collect_missing_jars()
594*c2e18aaaSAndroid Build Coastguard Worker
595*c2e18aaaSAndroid Build Coastguard Worker
596*c2e18aaaSAndroid Build Coastguard Workerclass EclipseModuleData(ModuleData):
597*c2e18aaaSAndroid Build Coastguard Worker    """Deal with modules data for Eclipse
598*c2e18aaaSAndroid Build Coastguard Worker
599*c2e18aaaSAndroid Build Coastguard Worker    Only project target modules use source folder type and the other ones use
600*c2e18aaaSAndroid Build Coastguard Worker    jar as their source. We'll combine both to establish the whole project's
601*c2e18aaaSAndroid Build Coastguard Worker    dependencies. If the source folder used to build dependency jar file exists
602*c2e18aaaSAndroid Build Coastguard Worker    in Android, we should provide the jar file path as <linkedResource> item in
603*c2e18aaaSAndroid Build Coastguard Worker    source data.
604*c2e18aaaSAndroid Build Coastguard Worker    """
605*c2e18aaaSAndroid Build Coastguard Worker
606*c2e18aaaSAndroid Build Coastguard Worker    def __init__(self, module_name, module_data, project_relpath):
607*c2e18aaaSAndroid Build Coastguard Worker        """Initialize EclipseModuleData.
608*c2e18aaaSAndroid Build Coastguard Worker
609*c2e18aaaSAndroid Build Coastguard Worker        Only project target modules apply source folder type, so set the depth
610*c2e18aaaSAndroid Build Coastguard Worker        of module referenced by source to 0.
611*c2e18aaaSAndroid Build Coastguard Worker
612*c2e18aaaSAndroid Build Coastguard Worker        Args:
613*c2e18aaaSAndroid Build Coastguard Worker            module_name: String type, name of the module.
614*c2e18aaaSAndroid Build Coastguard Worker            module_data: A dictionary contains a module information.
615*c2e18aaaSAndroid Build Coastguard Worker            project_relpath: A string stands for the project's relative path.
616*c2e18aaaSAndroid Build Coastguard Worker        """
617*c2e18aaaSAndroid Build Coastguard Worker        super().__init__(module_name, module_data, depth=0)
618*c2e18aaaSAndroid Build Coastguard Worker        related = module_info.AidegenModuleInfo.is_project_path_relative_module(
619*c2e18aaaSAndroid Build Coastguard Worker            module_data, project_relpath)
620*c2e18aaaSAndroid Build Coastguard Worker        self.is_project = related
621*c2e18aaaSAndroid Build Coastguard Worker
622*c2e18aaaSAndroid Build Coastguard Worker    def locate_sources_path(self):
623*c2e18aaaSAndroid Build Coastguard Worker        """Locate source folders' paths or jar files.
624*c2e18aaaSAndroid Build Coastguard Worker
625*c2e18aaaSAndroid Build Coastguard Worker        Only collect source folders for the project modules and collect jar
626*c2e18aaaSAndroid Build Coastguard Worker        files for the other dependent modules.
627*c2e18aaaSAndroid Build Coastguard Worker        """
628*c2e18aaaSAndroid Build Coastguard Worker        if self.is_project:
629*c2e18aaaSAndroid Build Coastguard Worker            self._locate_project_source_path()
630*c2e18aaaSAndroid Build Coastguard Worker        else:
631*c2e18aaaSAndroid Build Coastguard Worker            self._locate_jar_path()
632*c2e18aaaSAndroid Build Coastguard Worker        self._collect_classes_jars()
633*c2e18aaaSAndroid Build Coastguard Worker        self._collect_missing_jars()
634*c2e18aaaSAndroid Build Coastguard Worker
635*c2e18aaaSAndroid Build Coastguard Worker    def _add_to_source_or_test_dirs(self, src_dir):
636*c2e18aaaSAndroid Build Coastguard Worker        """Add a folder to source list if it is not in ignored directories.
637*c2e18aaaSAndroid Build Coastguard Worker
638*c2e18aaaSAndroid Build Coastguard Worker        Override the parent method since the tests folder has no difference
639*c2e18aaaSAndroid Build Coastguard Worker        with source folder in Eclipse.
640*c2e18aaaSAndroid Build Coastguard Worker
641*c2e18aaaSAndroid Build Coastguard Worker        Args:
642*c2e18aaaSAndroid Build Coastguard Worker            src_dir: a string of relative path to the Android root.
643*c2e18aaaSAndroid Build Coastguard Worker        """
644*c2e18aaaSAndroid Build Coastguard Worker        if src_dir not in _IGNORE_DIRS and src_dir not in self.src_dirs:
645*c2e18aaaSAndroid Build Coastguard Worker            self.src_dirs.append(src_dir)
646*c2e18aaaSAndroid Build Coastguard Worker
647*c2e18aaaSAndroid Build Coastguard Worker    def _locate_project_source_path(self):
648*c2e18aaaSAndroid Build Coastguard Worker        """Locate the source folder paths of the project module.
649*c2e18aaaSAndroid Build Coastguard Worker
650*c2e18aaaSAndroid Build Coastguard Worker        A project module is the target modules or paths that users key in
651*c2e18aaaSAndroid Build Coastguard Worker        aidegen command. Collecting the source folders is necessary for
652*c2e18aaaSAndroid Build Coastguard Worker        developers to edit code. And also collect the central R folder for the
653*c2e18aaaSAndroid Build Coastguard Worker        dependency of resources.
654*c2e18aaaSAndroid Build Coastguard Worker        """
655*c2e18aaaSAndroid Build Coastguard Worker        self._collect_srcs_paths()
656*c2e18aaaSAndroid Build Coastguard Worker        self._collect_r_srcs_paths()
657*c2e18aaaSAndroid Build Coastguard Worker
658*c2e18aaaSAndroid Build Coastguard Worker    def _locate_jar_path(self):
659*c2e18aaaSAndroid Build Coastguard Worker        """Locate the jar path of the module.
660*c2e18aaaSAndroid Build Coastguard Worker
661*c2e18aaaSAndroid Build Coastguard Worker        Use jar files for dependency modules for Eclipse. Collect the jar file
662*c2e18aaaSAndroid Build Coastguard Worker        path with different cases.
663*c2e18aaaSAndroid Build Coastguard Worker        """
664*c2e18aaaSAndroid Build Coastguard Worker        if self._check_jarjar_rules_exist():
665*c2e18aaaSAndroid Build Coastguard Worker            self._append_jar_from_installed(self.specific_soong_path)
666*c2e18aaaSAndroid Build Coastguard Worker        elif self._check_jars_exist():
667*c2e18aaaSAndroid Build Coastguard Worker            self._set_jars_jarfile()
668*c2e18aaaSAndroid Build Coastguard Worker        elif self._check_classes_jar_exist():
669*c2e18aaaSAndroid Build Coastguard Worker            self._append_classes_jar()
670*c2e18aaaSAndroid Build Coastguard Worker        else:
671*c2e18aaaSAndroid Build Coastguard Worker            self._append_jar_from_installed()
672