1#!/usr/bin/env python3
2#
3# Copyright 2020 - The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""It is an AIDEGen sub task: generate the .code_workspace file.
18    Usage:
19        path = vscode_workspace_file_gen.generate_code_workspace_file(abs_paths)
20        _launch_ide(ide_util_obj, path)
21"""
22
23import os
24
25from aidegen import constant
26from aidegen.lib import common_util
27
28_NAME = 'name'
29_FOLDERS = 'folders'
30_VSCODE_WORKSPACE_EXT = '.code-workspace'
31
32
33def generate_code_workspace_file(abs_paths):
34    """Generates .code-workspace file to launch multiple projects in VSCode.
35
36    The rules:
37        1. Get all folder names.
38        2. Get file name and absolute file path for .code-workspace file.
39        3. Generate .code-workspace file content.
40        4. Create .code-workspace file.
41
42    Args:
43        abs_paths: A list of absolute paths of all modules in the projects.
44
45    Returns:
46        A string of the absolute path of ${project}.code-workspace file.
47    """
48    workspace_dict = {_FOLDERS: []}
49    root_dir = common_util.get_android_root_dir()
50    for path in abs_paths:
51        name = _get_unique_project_name(path, root_dir)
52        workspace_dict[_FOLDERS].append({_NAME: name, constant.KEY_PATH: path})
53    return _create_code_workspace_file_content(workspace_dict)
54
55
56def _create_code_workspace_file_content(workspace_dict):
57    """Create '${project}.code-workspace' file content with workspace_dict.
58
59    Args:
60        workspace_dict: A dictionary contains the 'folders', 'name', 'path'
61                        formats. e.g.,
62                        {
63                            "folders": [
64                                {
65                                     "name": "frameworks.base",
66                                     "path": "/usr/aosp/frameworks/base"
67                                },
68                                {
69                                     "name": "packages.apps.Settings",
70                                     "path": "/usr/aosp/packages/apps/Settings"
71                                }
72                            ]
73                        }
74    Returns:
75        A string of the absolute path of ${project}.code-workspace file.
76    """
77    folder_name = workspace_dict[_FOLDERS][0][_NAME]
78    abs_path = workspace_dict[_FOLDERS][0][constant.KEY_PATH]
79    file_name = ''.join([folder_name, _VSCODE_WORKSPACE_EXT])
80    file_path = os.path.join(abs_path, file_name)
81    common_util.dump_json_dict(file_path, workspace_dict)
82    return file_path
83
84
85def _get_unique_project_name(abs_path, root_dir):
86    """Gets an unique project name from the project absolute path.
87
88    If it's the whole Android source case, replace the relative path '.' with
89    the root folder name.
90
91    Args:
92        abs_path: A string of the project absolute path.
93        root_dir: A string of the absolute Android root path.
94
95    Returns:
96        A string of an unique project name.
97    """
98    unique_name = os.path.relpath(abs_path, root_dir).replace(os.sep, '.')
99    if unique_name == '.':
100        unique_name = os.path.basename(root_dir)
101    return unique_name
102