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"""It is an AIDEGen sub task : IDE operation task! 18*c2e18aaaSAndroid Build Coastguard Worker 19*c2e18aaaSAndroid Build Coastguard WorkerTakes a project file path as input, after passing the needed check(file 20*c2e18aaaSAndroid Build Coastguard Workerexistence, IDE type, etc.), launch the project in related IDE. 21*c2e18aaaSAndroid Build Coastguard Worker 22*c2e18aaaSAndroid Build Coastguard Worker Typical usage example: 23*c2e18aaaSAndroid Build Coastguard Worker 24*c2e18aaaSAndroid Build Coastguard Worker ide_util_obj = IdeUtil() 25*c2e18aaaSAndroid Build Coastguard Worker if ide_util_obj.is_ide_installed(): 26*c2e18aaaSAndroid Build Coastguard Worker ide_util_obj.config_ide(project_file) 27*c2e18aaaSAndroid Build Coastguard Worker ide_util_obj.launch_ide() 28*c2e18aaaSAndroid Build Coastguard Worker 29*c2e18aaaSAndroid Build Coastguard Worker # Get the configuration folders of IntelliJ or Android Studio. 30*c2e18aaaSAndroid Build Coastguard Worker ide_util_obj.get_ide_config_folders() 31*c2e18aaaSAndroid Build Coastguard Worker""" 32*c2e18aaaSAndroid Build Coastguard Worker 33*c2e18aaaSAndroid Build Coastguard Workerimport glob 34*c2e18aaaSAndroid Build Coastguard Workerimport logging 35*c2e18aaaSAndroid Build Coastguard Workerimport os 36*c2e18aaaSAndroid Build Coastguard Workerimport platform 37*c2e18aaaSAndroid Build Coastguard Workerimport re 38*c2e18aaaSAndroid Build Coastguard Workerimport subprocess 39*c2e18aaaSAndroid Build Coastguard Worker 40*c2e18aaaSAndroid Build Coastguard Workerfrom xml.etree import ElementTree 41*c2e18aaaSAndroid Build Coastguard Worker 42*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen import constant 43*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen import templates 44*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import aidegen_metrics 45*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import android_dev_os 46*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import common_util 47*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import config 48*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import errors 49*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import ide_common_util 50*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import project_config 51*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import project_file_gen 52*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.sdk import jdk_table 53*c2e18aaaSAndroid Build Coastguard Workerfrom aidegen.lib import xml_util 54*c2e18aaaSAndroid Build Coastguard Worker 55*c2e18aaaSAndroid Build Coastguard Worker# Add 'nohup' to prevent IDE from being terminated when console is terminated. 56*c2e18aaaSAndroid Build Coastguard Worker_IDEA_FOLDER = '.idea' 57*c2e18aaaSAndroid Build Coastguard Worker_IML_EXTENSION = '.iml' 58*c2e18aaaSAndroid Build Coastguard Worker_JDK_PATH_TOKEN = '@JDKpath' 59*c2e18aaaSAndroid Build Coastguard Worker_COMPONENT_END_TAG = ' </component>' 60*c2e18aaaSAndroid Build Coastguard Worker_ECLIPSE_WS = '~/Documents/AIDEGen_Eclipse_workspace' 61*c2e18aaaSAndroid Build Coastguard Worker_ALERT_CREATE_WS = ('AIDEGen will create a workspace at %s for Eclipse, ' 62*c2e18aaaSAndroid Build Coastguard Worker 'Enter `y` to allow AIDEgen to automatically create the ' 63*c2e18aaaSAndroid Build Coastguard Worker 'workspace for you. Otherwise, you need to select the ' 64*c2e18aaaSAndroid Build Coastguard Worker 'workspace after Eclipse is launched.\nWould you like ' 65*c2e18aaaSAndroid Build Coastguard Worker 'AIDEgen to automatically create the workspace for you?' 66*c2e18aaaSAndroid Build Coastguard Worker '(y/n)' % constant.ECLIPSE_WS) 67*c2e18aaaSAndroid Build Coastguard Worker_NO_LAUNCH_IDE_CMD = """ 68*c2e18aaaSAndroid Build Coastguard WorkerCan not find IDE: {}, in path: {}, you can: 69*c2e18aaaSAndroid Build Coastguard Worker - add IDE executable to your $PATH 70*c2e18aaaSAndroid Build Coastguard Workeror - specify the exact IDE executable path by "aidegen -p" 71*c2e18aaaSAndroid Build Coastguard Workeror - specify "aidegen -n" to generate project file only 72*c2e18aaaSAndroid Build Coastguard Worker""" 73*c2e18aaaSAndroid Build Coastguard Worker_INFO_IMPORT_CONFIG = ('{} needs to import the application configuration for ' 74*c2e18aaaSAndroid Build Coastguard Worker 'the new version!\nAfter the import is finished, rerun ' 75*c2e18aaaSAndroid Build Coastguard Worker 'the command if your project did not launch. Please ' 76*c2e18aaaSAndroid Build Coastguard Worker 'follow the showing dialog to finish the import action.' 77*c2e18aaaSAndroid Build Coastguard Worker '\n\n') 78*c2e18aaaSAndroid Build Coastguard WorkerCONFIG_DIR = 'config' 79*c2e18aaaSAndroid Build Coastguard WorkerLINUX_JDK_PATH = os.path.join(common_util.get_android_root_dir(), 80*c2e18aaaSAndroid Build Coastguard Worker 'prebuilts/jdk/jdk21/linux-x86') 81*c2e18aaaSAndroid Build Coastguard WorkerLINUX_JDK_TABLE_PATH = 'config/options/jdk.table.xml' 82*c2e18aaaSAndroid Build Coastguard WorkerLINUX_FILE_TYPE_PATH = 'config/options/filetypes.xml' 83*c2e18aaaSAndroid Build Coastguard WorkerLINUX_ANDROID_SDK_PATH = os.path.join(os.getenv('HOME'), 'Android/Sdk') 84*c2e18aaaSAndroid Build Coastguard WorkerMAC_JDK_PATH = os.path.join(common_util.get_android_root_dir(), 85*c2e18aaaSAndroid Build Coastguard Worker 'prebuilts/jdk/jdk21/darwin-x86') 86*c2e18aaaSAndroid Build Coastguard WorkerALTERNATIVE_JDK_TABLE_PATH = 'options/jdk.table.xml' 87*c2e18aaaSAndroid Build Coastguard WorkerALTERNATIVE_FILE_TYPE_XML_PATH = 'options/filetypes.xml' 88*c2e18aaaSAndroid Build Coastguard WorkerMAC_ANDROID_SDK_PATH = os.path.join(os.getenv('HOME'), 'Library/Android/sdk') 89*c2e18aaaSAndroid Build Coastguard WorkerPATTERN_KEY = 'pattern' 90*c2e18aaaSAndroid Build Coastguard WorkerTYPE_KEY = 'type' 91*c2e18aaaSAndroid Build Coastguard Worker_TEST_MAPPING_FILE_TYPE = 'JSON' 92*c2e18aaaSAndroid Build Coastguard WorkerTEST_MAPPING_NAME = 'TEST_MAPPING' 93*c2e18aaaSAndroid Build Coastguard Worker_TEST_MAPPING_TYPE = '<mapping pattern="TEST_MAPPING" type="JSON" />' 94*c2e18aaaSAndroid Build Coastguard Worker_XPATH_EXTENSION_MAP = 'component/extensionMap' 95*c2e18aaaSAndroid Build Coastguard Worker_XPATH_MAPPING = _XPATH_EXTENSION_MAP + '/mapping' 96*c2e18aaaSAndroid Build Coastguard Worker_SPECIFIC_INTELLIJ_VERSION = 2020.1 97*c2e18aaaSAndroid Build Coastguard Worker_TEST_MAPPING_FILE_TYPE_ADDING_WARN = '\n{} {}\n'.format( 98*c2e18aaaSAndroid Build Coastguard Worker common_util.COLORED_INFO('WARNING:'), 99*c2e18aaaSAndroid Build Coastguard Worker ('TEST_MAPPING file type can\'t be added to filetypes.xml. The reason ' 100*c2e18aaaSAndroid Build Coastguard Worker 'might be: lack of the parent tag to add TEST_MAPPING file type.')) 101*c2e18aaaSAndroid Build Coastguard Worker 102*c2e18aaaSAndroid Build Coastguard Worker 103*c2e18aaaSAndroid Build Coastguard Worker# pylint: disable=too-many-lines 104*c2e18aaaSAndroid Build Coastguard Worker# pylint: disable=invalid-name 105*c2e18aaaSAndroid Build Coastguard Workerclass IdeUtil: 106*c2e18aaaSAndroid Build Coastguard Worker """Provide a set of IDE operations, e.g., launch and configuration. 107*c2e18aaaSAndroid Build Coastguard Worker 108*c2e18aaaSAndroid Build Coastguard Worker Attributes: 109*c2e18aaaSAndroid Build Coastguard Worker _ide: IdeBase derived instance, the related IDE object. 110*c2e18aaaSAndroid Build Coastguard Worker 111*c2e18aaaSAndroid Build Coastguard Worker For example: 112*c2e18aaaSAndroid Build Coastguard Worker 1. Check if IDE is installed. 113*c2e18aaaSAndroid Build Coastguard Worker 2. Config IDE, e.g. config code style, SDK path, and etc. 114*c2e18aaaSAndroid Build Coastguard Worker 3. Launch an IDE. 115*c2e18aaaSAndroid Build Coastguard Worker """ 116*c2e18aaaSAndroid Build Coastguard Worker 117*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, 118*c2e18aaaSAndroid Build Coastguard Worker installed_path=None, 119*c2e18aaaSAndroid Build Coastguard Worker ide='j', 120*c2e18aaaSAndroid Build Coastguard Worker config_reset=False, 121*c2e18aaaSAndroid Build Coastguard Worker is_mac=False): 122*c2e18aaaSAndroid Build Coastguard Worker logging.debug('IdeUtil with OS name: %s%s', platform.system(), 123*c2e18aaaSAndroid Build Coastguard Worker '(Mac)' if is_mac else '') 124*c2e18aaaSAndroid Build Coastguard Worker self._ide = _get_ide(installed_path, ide, config_reset, is_mac) 125*c2e18aaaSAndroid Build Coastguard Worker 126*c2e18aaaSAndroid Build Coastguard Worker def is_ide_installed(self): 127*c2e18aaaSAndroid Build Coastguard Worker """Checks if the IDE is already installed. 128*c2e18aaaSAndroid Build Coastguard Worker 129*c2e18aaaSAndroid Build Coastguard Worker Returns: 130*c2e18aaaSAndroid Build Coastguard Worker True if IDE is installed already, otherwise False. 131*c2e18aaaSAndroid Build Coastguard Worker """ 132*c2e18aaaSAndroid Build Coastguard Worker return self._ide.is_ide_installed() 133*c2e18aaaSAndroid Build Coastguard Worker 134*c2e18aaaSAndroid Build Coastguard Worker def launch_ide(self): 135*c2e18aaaSAndroid Build Coastguard Worker """Launches the relative IDE by opening the passed project file.""" 136*c2e18aaaSAndroid Build Coastguard Worker return self._ide.launch_ide() 137*c2e18aaaSAndroid Build Coastguard Worker 138*c2e18aaaSAndroid Build Coastguard Worker def config_ide(self, project_abspath): 139*c2e18aaaSAndroid Build Coastguard Worker """To config the IDE, e.g., setup code style, init SDK, and etc. 140*c2e18aaaSAndroid Build Coastguard Worker 141*c2e18aaaSAndroid Build Coastguard Worker Args: 142*c2e18aaaSAndroid Build Coastguard Worker project_abspath: An absolute path of the project. 143*c2e18aaaSAndroid Build Coastguard Worker """ 144*c2e18aaaSAndroid Build Coastguard Worker self._ide.project_abspath = project_abspath 145*c2e18aaaSAndroid Build Coastguard Worker if self.is_ide_installed() and self._ide: 146*c2e18aaaSAndroid Build Coastguard Worker self._ide.apply_optional_config() 147*c2e18aaaSAndroid Build Coastguard Worker 148*c2e18aaaSAndroid Build Coastguard Worker def get_default_path(self): 149*c2e18aaaSAndroid Build Coastguard Worker """Gets IDE default installed path.""" 150*c2e18aaaSAndroid Build Coastguard Worker return self._ide.default_installed_path 151*c2e18aaaSAndroid Build Coastguard Worker 152*c2e18aaaSAndroid Build Coastguard Worker def ide_name(self): 153*c2e18aaaSAndroid Build Coastguard Worker """Gets IDE name.""" 154*c2e18aaaSAndroid Build Coastguard Worker return self._ide.ide_name 155*c2e18aaaSAndroid Build Coastguard Worker 156*c2e18aaaSAndroid Build Coastguard Worker def get_ide_config_folders(self): 157*c2e18aaaSAndroid Build Coastguard Worker """Gets the config folders of IDE.""" 158*c2e18aaaSAndroid Build Coastguard Worker return self._ide.config_folders 159*c2e18aaaSAndroid Build Coastguard Worker 160*c2e18aaaSAndroid Build Coastguard Worker 161*c2e18aaaSAndroid Build Coastguard Workerclass IdeBase: 162*c2e18aaaSAndroid Build Coastguard Worker """The most base class of IDE, provides interface and partial path init. 163*c2e18aaaSAndroid Build Coastguard Worker 164*c2e18aaaSAndroid Build Coastguard Worker Class Attributes: 165*c2e18aaaSAndroid Build Coastguard Worker _JDK_PATH: The path of JDK in android project. 166*c2e18aaaSAndroid Build Coastguard Worker _IDE_JDK_TABLE_PATH: The path of JDK table which record JDK info in IDE. 167*c2e18aaaSAndroid Build Coastguard Worker _IDE_FILE_TYPE_PATH: The path of filetypes.xml. 168*c2e18aaaSAndroid Build Coastguard Worker _JDK_CONTENT: A string, the content of the JDK configuration. 169*c2e18aaaSAndroid Build Coastguard Worker _DEFAULT_ANDROID_SDK_PATH: A string, the path of Android SDK. 170*c2e18aaaSAndroid Build Coastguard Worker _CONFIG_DIR: A string of the config folder name. 171*c2e18aaaSAndroid Build Coastguard Worker _SYMBOLIC_VERSIONS: A string list of the symbolic link paths of the 172*c2e18aaaSAndroid Build Coastguard Worker relevant IDE. 173*c2e18aaaSAndroid Build Coastguard Worker 174*c2e18aaaSAndroid Build Coastguard Worker Attributes: 175*c2e18aaaSAndroid Build Coastguard Worker _installed_path: String for the IDE binary path. 176*c2e18aaaSAndroid Build Coastguard Worker _config_reset: Boolean, True for reset configuration, else not reset. 177*c2e18aaaSAndroid Build Coastguard Worker _bin_file_name: String for IDE executable file name. 178*c2e18aaaSAndroid Build Coastguard Worker _bin_paths: A list of all possible IDE executable file absolute paths. 179*c2e18aaaSAndroid Build Coastguard Worker _ide_name: String for IDE name. 180*c2e18aaaSAndroid Build Coastguard Worker _bin_folders: A list of all possible IDE installed paths. 181*c2e18aaaSAndroid Build Coastguard Worker config_folders: A list of all possible paths for the IntelliJ 182*c2e18aaaSAndroid Build Coastguard Worker configuration folder. 183*c2e18aaaSAndroid Build Coastguard Worker project_abspath: The absolute path of the project. 184*c2e18aaaSAndroid Build Coastguard Worker 185*c2e18aaaSAndroid Build Coastguard Worker For example: 186*c2e18aaaSAndroid Build Coastguard Worker 1. Check if IDE is installed. 187*c2e18aaaSAndroid Build Coastguard Worker 2. Launch IDE. 188*c2e18aaaSAndroid Build Coastguard Worker 3. Config IDE. 189*c2e18aaaSAndroid Build Coastguard Worker """ 190*c2e18aaaSAndroid Build Coastguard Worker 191*c2e18aaaSAndroid Build Coastguard Worker _JDK_PATH = '' 192*c2e18aaaSAndroid Build Coastguard Worker _IDE_JDK_TABLE_PATH = '' 193*c2e18aaaSAndroid Build Coastguard Worker _IDE_FILE_TYPE_PATH = '' 194*c2e18aaaSAndroid Build Coastguard Worker _JDK_CONTENT = '' 195*c2e18aaaSAndroid Build Coastguard Worker _DEFAULT_ANDROID_SDK_PATH = '' 196*c2e18aaaSAndroid Build Coastguard Worker _CONFIG_DIR = '' 197*c2e18aaaSAndroid Build Coastguard Worker _SYMBOLIC_VERSIONS = [] 198*c2e18aaaSAndroid Build Coastguard Worker 199*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 200*c2e18aaaSAndroid Build Coastguard Worker self._installed_path = installed_path 201*c2e18aaaSAndroid Build Coastguard Worker self._config_reset = config_reset 202*c2e18aaaSAndroid Build Coastguard Worker self._ide_name = '' 203*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name = '' 204*c2e18aaaSAndroid Build Coastguard Worker self._bin_paths = [] 205*c2e18aaaSAndroid Build Coastguard Worker self._bin_folders = [] 206*c2e18aaaSAndroid Build Coastguard Worker self.config_folders = [] 207*c2e18aaaSAndroid Build Coastguard Worker self.project_abspath = '' 208*c2e18aaaSAndroid Build Coastguard Worker 209*c2e18aaaSAndroid Build Coastguard Worker def is_ide_installed(self): 210*c2e18aaaSAndroid Build Coastguard Worker """Checks if IDE is already installed. 211*c2e18aaaSAndroid Build Coastguard Worker 212*c2e18aaaSAndroid Build Coastguard Worker Returns: 213*c2e18aaaSAndroid Build Coastguard Worker True if IDE is installed already, otherwise False. 214*c2e18aaaSAndroid Build Coastguard Worker """ 215*c2e18aaaSAndroid Build Coastguard Worker return bool(self._installed_path) 216*c2e18aaaSAndroid Build Coastguard Worker 217*c2e18aaaSAndroid Build Coastguard Worker def launch_ide(self): 218*c2e18aaaSAndroid Build Coastguard Worker """Launches IDE by opening the passed project file.""" 219*c2e18aaaSAndroid Build Coastguard Worker ide_common_util.launch_ide(self.project_abspath, self._get_ide_cmd(), 220*c2e18aaaSAndroid Build Coastguard Worker self._ide_name) 221*c2e18aaaSAndroid Build Coastguard Worker 222*c2e18aaaSAndroid Build Coastguard Worker def apply_optional_config(self): 223*c2e18aaaSAndroid Build Coastguard Worker """Do IDEA global config action. 224*c2e18aaaSAndroid Build Coastguard Worker 225*c2e18aaaSAndroid Build Coastguard Worker Run code style config, SDK config. 226*c2e18aaaSAndroid Build Coastguard Worker """ 227*c2e18aaaSAndroid Build Coastguard Worker if not self._installed_path: 228*c2e18aaaSAndroid Build Coastguard Worker return 229*c2e18aaaSAndroid Build Coastguard Worker # Skip config action if there's no config folder exists. 230*c2e18aaaSAndroid Build Coastguard Worker _path_list = self._get_config_root_paths() 231*c2e18aaaSAndroid Build Coastguard Worker if not _path_list: 232*c2e18aaaSAndroid Build Coastguard Worker return 233*c2e18aaaSAndroid Build Coastguard Worker self.config_folders = _path_list.copy() 234*c2e18aaaSAndroid Build Coastguard Worker 235*c2e18aaaSAndroid Build Coastguard Worker for _config_path in _path_list: 236*c2e18aaaSAndroid Build Coastguard Worker jdk_file = os.path.join(_config_path, self._IDE_JDK_TABLE_PATH) 237*c2e18aaaSAndroid Build Coastguard Worker jdk_xml = jdk_table.JDKTableXML(jdk_file, self._JDK_CONTENT, 238*c2e18aaaSAndroid Build Coastguard Worker self._JDK_PATH, 239*c2e18aaaSAndroid Build Coastguard Worker self._DEFAULT_ANDROID_SDK_PATH) 240*c2e18aaaSAndroid Build Coastguard Worker if jdk_xml.config_jdk_table_xml(): 241*c2e18aaaSAndroid Build Coastguard Worker project_file_gen.gen_enable_debugger_module( 242*c2e18aaaSAndroid Build Coastguard Worker self.project_abspath, jdk_xml.android_sdk_version) 243*c2e18aaaSAndroid Build Coastguard Worker 244*c2e18aaaSAndroid Build Coastguard Worker # Set the max file size in the idea.properties. 245*c2e18aaaSAndroid Build Coastguard Worker intellij_config_dir = os.path.join(_config_path, self._CONFIG_DIR) 246*c2e18aaaSAndroid Build Coastguard Worker config.IdeaProperties(intellij_config_dir).set_max_file_size() 247*c2e18aaaSAndroid Build Coastguard Worker 248*c2e18aaaSAndroid Build Coastguard Worker self._add_test_mapping_file_type(_config_path) 249*c2e18aaaSAndroid Build Coastguard Worker 250*c2e18aaaSAndroid Build Coastguard Worker def _add_test_mapping_file_type(self, _config_path): 251*c2e18aaaSAndroid Build Coastguard Worker """Adds TEST_MAPPING file type. 252*c2e18aaaSAndroid Build Coastguard Worker 253*c2e18aaaSAndroid Build Coastguard Worker IntelliJ can't recognize TEST_MAPPING files as the json file. It needs 254*c2e18aaaSAndroid Build Coastguard Worker adding file type mapping in filetypes.xml to recognize TEST_MAPPING 255*c2e18aaaSAndroid Build Coastguard Worker files. 256*c2e18aaaSAndroid Build Coastguard Worker 257*c2e18aaaSAndroid Build Coastguard Worker Args: 258*c2e18aaaSAndroid Build Coastguard Worker _config_path: the path of IDE config. 259*c2e18aaaSAndroid Build Coastguard Worker """ 260*c2e18aaaSAndroid Build Coastguard Worker file_type_path = os.path.join(_config_path, self._IDE_FILE_TYPE_PATH) 261*c2e18aaaSAndroid Build Coastguard Worker if not os.path.isfile(file_type_path): 262*c2e18aaaSAndroid Build Coastguard Worker logging.warning('The file: filetypes.xml is not found.') 263*c2e18aaaSAndroid Build Coastguard Worker return 264*c2e18aaaSAndroid Build Coastguard Worker 265*c2e18aaaSAndroid Build Coastguard Worker file_type_xml = xml_util.parse_xml(file_type_path) 266*c2e18aaaSAndroid Build Coastguard Worker if not file_type_xml: 267*c2e18aaaSAndroid Build Coastguard Worker logging.warning('Can\'t parse filetypes.xml.') 268*c2e18aaaSAndroid Build Coastguard Worker return 269*c2e18aaaSAndroid Build Coastguard Worker 270*c2e18aaaSAndroid Build Coastguard Worker root = file_type_xml.getroot() 271*c2e18aaaSAndroid Build Coastguard Worker add_pattern = True 272*c2e18aaaSAndroid Build Coastguard Worker for mapping in root.findall(_XPATH_MAPPING): 273*c2e18aaaSAndroid Build Coastguard Worker attrib = mapping.attrib 274*c2e18aaaSAndroid Build Coastguard Worker if PATTERN_KEY in attrib and TYPE_KEY in attrib: 275*c2e18aaaSAndroid Build Coastguard Worker if attrib[PATTERN_KEY] == TEST_MAPPING_NAME: 276*c2e18aaaSAndroid Build Coastguard Worker if attrib[TYPE_KEY] != _TEST_MAPPING_FILE_TYPE: 277*c2e18aaaSAndroid Build Coastguard Worker attrib[TYPE_KEY] = _TEST_MAPPING_FILE_TYPE 278*c2e18aaaSAndroid Build Coastguard Worker file_type_xml.write(file_type_path) 279*c2e18aaaSAndroid Build Coastguard Worker add_pattern = False 280*c2e18aaaSAndroid Build Coastguard Worker break 281*c2e18aaaSAndroid Build Coastguard Worker if add_pattern: 282*c2e18aaaSAndroid Build Coastguard Worker ext_attrib = root.find(_XPATH_EXTENSION_MAP) 283*c2e18aaaSAndroid Build Coastguard Worker if ext_attrib is None: 284*c2e18aaaSAndroid Build Coastguard Worker print(_TEST_MAPPING_FILE_TYPE_ADDING_WARN) 285*c2e18aaaSAndroid Build Coastguard Worker return 286*c2e18aaaSAndroid Build Coastguard Worker ext_attrib.append(ElementTree.fromstring(_TEST_MAPPING_TYPE)) 287*c2e18aaaSAndroid Build Coastguard Worker pretty_xml = common_util.to_pretty_xml(root) 288*c2e18aaaSAndroid Build Coastguard Worker common_util.file_generate(file_type_path, pretty_xml) 289*c2e18aaaSAndroid Build Coastguard Worker 290*c2e18aaaSAndroid Build Coastguard Worker def _get_config_root_paths(self): 291*c2e18aaaSAndroid Build Coastguard Worker """Get the config root paths from derived class. 292*c2e18aaaSAndroid Build Coastguard Worker 293*c2e18aaaSAndroid Build Coastguard Worker Returns: 294*c2e18aaaSAndroid Build Coastguard Worker A string list of IDE config paths, return multiple paths if more 295*c2e18aaaSAndroid Build Coastguard Worker than one path are found, return an empty list when none is found. 296*c2e18aaaSAndroid Build Coastguard Worker """ 297*c2e18aaaSAndroid Build Coastguard Worker raise NotImplementedError() 298*c2e18aaaSAndroid Build Coastguard Worker 299*c2e18aaaSAndroid Build Coastguard Worker @property 300*c2e18aaaSAndroid Build Coastguard Worker def default_installed_path(self): 301*c2e18aaaSAndroid Build Coastguard Worker """Gets IDE default installed path.""" 302*c2e18aaaSAndroid Build Coastguard Worker return ' '.join(self._bin_folders) 303*c2e18aaaSAndroid Build Coastguard Worker 304*c2e18aaaSAndroid Build Coastguard Worker @property 305*c2e18aaaSAndroid Build Coastguard Worker def ide_name(self): 306*c2e18aaaSAndroid Build Coastguard Worker """Gets IDE name.""" 307*c2e18aaaSAndroid Build Coastguard Worker return self._ide_name 308*c2e18aaaSAndroid Build Coastguard Worker 309*c2e18aaaSAndroid Build Coastguard Worker def _get_ide_cmd(self): 310*c2e18aaaSAndroid Build Coastguard Worker """Compose launch IDE command to run a new process and redirect output. 311*c2e18aaaSAndroid Build Coastguard Worker 312*c2e18aaaSAndroid Build Coastguard Worker Returns: 313*c2e18aaaSAndroid Build Coastguard Worker A string of launch IDE command. 314*c2e18aaaSAndroid Build Coastguard Worker """ 315*c2e18aaaSAndroid Build Coastguard Worker return ide_common_util.get_run_ide_cmd(self._installed_path, 316*c2e18aaaSAndroid Build Coastguard Worker self.project_abspath) 317*c2e18aaaSAndroid Build Coastguard Worker 318*c2e18aaaSAndroid Build Coastguard Worker def _init_installed_path(self, installed_path): 319*c2e18aaaSAndroid Build Coastguard Worker """Initialize IDE installed path. 320*c2e18aaaSAndroid Build Coastguard Worker 321*c2e18aaaSAndroid Build Coastguard Worker Args: 322*c2e18aaaSAndroid Build Coastguard Worker installed_path: the installed path to be checked. 323*c2e18aaaSAndroid Build Coastguard Worker """ 324*c2e18aaaSAndroid Build Coastguard Worker if installed_path: 325*c2e18aaaSAndroid Build Coastguard Worker path_list = ide_common_util.get_script_from_input_path( 326*c2e18aaaSAndroid Build Coastguard Worker installed_path, self._bin_file_name) 327*c2e18aaaSAndroid Build Coastguard Worker self._installed_path = path_list[0] if path_list else None 328*c2e18aaaSAndroid Build Coastguard Worker else: 329*c2e18aaaSAndroid Build Coastguard Worker self._installed_path = self._get_script_from_system() 330*c2e18aaaSAndroid Build Coastguard Worker if not self._installed_path: 331*c2e18aaaSAndroid Build Coastguard Worker logging.error('No %s installed.', self._ide_name) 332*c2e18aaaSAndroid Build Coastguard Worker return 333*c2e18aaaSAndroid Build Coastguard Worker 334*c2e18aaaSAndroid Build Coastguard Worker self._set_installed_path() 335*c2e18aaaSAndroid Build Coastguard Worker 336*c2e18aaaSAndroid Build Coastguard Worker def _get_script_from_system(self): 337*c2e18aaaSAndroid Build Coastguard Worker """Get one IDE installed path from internal path. 338*c2e18aaaSAndroid Build Coastguard Worker 339*c2e18aaaSAndroid Build Coastguard Worker Returns: 340*c2e18aaaSAndroid Build Coastguard Worker The sh full path, or None if not found. 341*c2e18aaaSAndroid Build Coastguard Worker """ 342*c2e18aaaSAndroid Build Coastguard Worker sh_list = self._get_existent_scripts_in_system() 343*c2e18aaaSAndroid Build Coastguard Worker return sh_list[0] if sh_list else None 344*c2e18aaaSAndroid Build Coastguard Worker 345*c2e18aaaSAndroid Build Coastguard Worker def _get_possible_bin_paths(self): 346*c2e18aaaSAndroid Build Coastguard Worker """Gets all possible IDE installed paths.""" 347*c2e18aaaSAndroid Build Coastguard Worker return [os.path.join(f, self._bin_file_name) for f in self._bin_folders] 348*c2e18aaaSAndroid Build Coastguard Worker 349*c2e18aaaSAndroid Build Coastguard Worker def _get_ide_from_environment_paths(self): 350*c2e18aaaSAndroid Build Coastguard Worker """Get IDE executable binary file from environment paths. 351*c2e18aaaSAndroid Build Coastguard Worker 352*c2e18aaaSAndroid Build Coastguard Worker Returns: 353*c2e18aaaSAndroid Build Coastguard Worker A string of IDE executable binary path if found, otherwise return 354*c2e18aaaSAndroid Build Coastguard Worker None. 355*c2e18aaaSAndroid Build Coastguard Worker """ 356*c2e18aaaSAndroid Build Coastguard Worker env_paths = os.environ['PATH'].split(':') 357*c2e18aaaSAndroid Build Coastguard Worker for env_path in env_paths: 358*c2e18aaaSAndroid Build Coastguard Worker path = ide_common_util.get_scripts_from_dir_path( 359*c2e18aaaSAndroid Build Coastguard Worker env_path, self._bin_file_name) 360*c2e18aaaSAndroid Build Coastguard Worker if path: 361*c2e18aaaSAndroid Build Coastguard Worker return path 362*c2e18aaaSAndroid Build Coastguard Worker return None 363*c2e18aaaSAndroid Build Coastguard Worker 364*c2e18aaaSAndroid Build Coastguard Worker def _setup_ide(self): 365*c2e18aaaSAndroid Build Coastguard Worker """The callback used to run the necessary setup work of the IDE. 366*c2e18aaaSAndroid Build Coastguard Worker 367*c2e18aaaSAndroid Build Coastguard Worker When ide_util.config_ide is called to set up the JDK, SDK and some 368*c2e18aaaSAndroid Build Coastguard Worker features, the main thread will callback the Idexxx._setup_ide 369*c2e18aaaSAndroid Build Coastguard Worker to provide the chance for running the necessary setup of the specific 370*c2e18aaaSAndroid Build Coastguard Worker IDE. Default is to do nothing. 371*c2e18aaaSAndroid Build Coastguard Worker """ 372*c2e18aaaSAndroid Build Coastguard Worker 373*c2e18aaaSAndroid Build Coastguard Worker def _get_existent_scripts_in_system(self): 374*c2e18aaaSAndroid Build Coastguard Worker """Gets the relevant IDE run script path from system. 375*c2e18aaaSAndroid Build Coastguard Worker 376*c2e18aaaSAndroid Build Coastguard Worker First get correct IDE installed path from internal paths, if not found 377*c2e18aaaSAndroid Build Coastguard Worker search it from environment paths. 378*c2e18aaaSAndroid Build Coastguard Worker 379*c2e18aaaSAndroid Build Coastguard Worker Returns: 380*c2e18aaaSAndroid Build Coastguard Worker The list of script full path, or None if not found. 381*c2e18aaaSAndroid Build Coastguard Worker """ 382*c2e18aaaSAndroid Build Coastguard Worker return (ide_common_util.get_script_from_internal_path(self._bin_paths, 383*c2e18aaaSAndroid Build Coastguard Worker self._ide_name) or 384*c2e18aaaSAndroid Build Coastguard Worker self._get_ide_from_environment_paths()) 385*c2e18aaaSAndroid Build Coastguard Worker 386*c2e18aaaSAndroid Build Coastguard Worker def _get_user_preference(self, versions): 387*c2e18aaaSAndroid Build Coastguard Worker """Make sure the version is valid and update preference if needed. 388*c2e18aaaSAndroid Build Coastguard Worker 389*c2e18aaaSAndroid Build Coastguard Worker Args: 390*c2e18aaaSAndroid Build Coastguard Worker versions: A list of the IDE script path, contains the symbolic path. 391*c2e18aaaSAndroid Build Coastguard Worker 392*c2e18aaaSAndroid Build Coastguard Worker Returns: An IDE script path, or None is not found. 393*c2e18aaaSAndroid Build Coastguard Worker """ 394*c2e18aaaSAndroid Build Coastguard Worker if not versions: 395*c2e18aaaSAndroid Build Coastguard Worker return None 396*c2e18aaaSAndroid Build Coastguard Worker if len(versions) == 1: 397*c2e18aaaSAndroid Build Coastguard Worker return versions[0] 398*c2e18aaaSAndroid Build Coastguard Worker with config.AidegenConfig() as conf: 399*c2e18aaaSAndroid Build Coastguard Worker if not self._config_reset and (conf.preferred_version(self.ide_name) 400*c2e18aaaSAndroid Build Coastguard Worker in versions): 401*c2e18aaaSAndroid Build Coastguard Worker return conf.preferred_version(self.ide_name) 402*c2e18aaaSAndroid Build Coastguard Worker display_versions = self._merge_symbolic_version(versions) 403*c2e18aaaSAndroid Build Coastguard Worker preferred = ide_common_util.ask_preference(display_versions, 404*c2e18aaaSAndroid Build Coastguard Worker self.ide_name) 405*c2e18aaaSAndroid Build Coastguard Worker if preferred: 406*c2e18aaaSAndroid Build Coastguard Worker conf.set_preferred_version(self._get_real_path(preferred), 407*c2e18aaaSAndroid Build Coastguard Worker self.ide_name) 408*c2e18aaaSAndroid Build Coastguard Worker 409*c2e18aaaSAndroid Build Coastguard Worker return conf.preferred_version(self.ide_name) 410*c2e18aaaSAndroid Build Coastguard Worker 411*c2e18aaaSAndroid Build Coastguard Worker def _set_installed_path(self): 412*c2e18aaaSAndroid Build Coastguard Worker """Write the user's input installed path into the config file. 413*c2e18aaaSAndroid Build Coastguard Worker 414*c2e18aaaSAndroid Build Coastguard Worker If users input an existent IDE installed path, we should keep it in 415*c2e18aaaSAndroid Build Coastguard Worker the configuration. 416*c2e18aaaSAndroid Build Coastguard Worker """ 417*c2e18aaaSAndroid Build Coastguard Worker if self._installed_path: 418*c2e18aaaSAndroid Build Coastguard Worker with config.AidegenConfig() as aconf: 419*c2e18aaaSAndroid Build Coastguard Worker aconf.set_preferred_version(self._installed_path, self.ide_name) 420*c2e18aaaSAndroid Build Coastguard Worker 421*c2e18aaaSAndroid Build Coastguard Worker def _merge_symbolic_version(self, versions): 422*c2e18aaaSAndroid Build Coastguard Worker """Merge the duplicate version of symbolic links. 423*c2e18aaaSAndroid Build Coastguard Worker 424*c2e18aaaSAndroid Build Coastguard Worker Stable and beta versions are a symbolic link to an existing version. 425*c2e18aaaSAndroid Build Coastguard Worker This function assemble symbolic and real to make it more clear to read. 426*c2e18aaaSAndroid Build Coastguard Worker Ex: 427*c2e18aaaSAndroid Build Coastguard Worker ['/opt/intellij-ce-stable/bin/idea.sh', 428*c2e18aaaSAndroid Build Coastguard Worker '/opt/intellij-ce-2019.1/bin/idea.sh'] to 429*c2e18aaaSAndroid Build Coastguard Worker ['/opt/intellij-ce-stable/bin/idea.sh -> 430*c2e18aaaSAndroid Build Coastguard Worker /opt/intellij-ce-2019.1/bin/idea.sh', 431*c2e18aaaSAndroid Build Coastguard Worker '/opt/intellij-ce-2019.1/bin/idea.sh'] 432*c2e18aaaSAndroid Build Coastguard Worker 433*c2e18aaaSAndroid Build Coastguard Worker Args: 434*c2e18aaaSAndroid Build Coastguard Worker versions: A list of all installed versions. 435*c2e18aaaSAndroid Build Coastguard Worker 436*c2e18aaaSAndroid Build Coastguard Worker Returns: 437*c2e18aaaSAndroid Build Coastguard Worker A list of versions to show for user to select. It may contain 438*c2e18aaaSAndroid Build Coastguard Worker 'symbolic_path/idea.sh -> original_path/idea.sh'. 439*c2e18aaaSAndroid Build Coastguard Worker """ 440*c2e18aaaSAndroid Build Coastguard Worker display_versions = versions[:] 441*c2e18aaaSAndroid Build Coastguard Worker for symbolic in self._SYMBOLIC_VERSIONS: 442*c2e18aaaSAndroid Build Coastguard Worker if symbolic in display_versions and (os.path.isfile(symbolic)): 443*c2e18aaaSAndroid Build Coastguard Worker real_path = os.path.realpath(symbolic) 444*c2e18aaaSAndroid Build Coastguard Worker for index, path in enumerate(display_versions): 445*c2e18aaaSAndroid Build Coastguard Worker if path == symbolic: 446*c2e18aaaSAndroid Build Coastguard Worker display_versions[index] = ' -> '.join( 447*c2e18aaaSAndroid Build Coastguard Worker [display_versions[index], real_path]) 448*c2e18aaaSAndroid Build Coastguard Worker break 449*c2e18aaaSAndroid Build Coastguard Worker return display_versions 450*c2e18aaaSAndroid Build Coastguard Worker 451*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 452*c2e18aaaSAndroid Build Coastguard Worker def _get_real_path(path): 453*c2e18aaaSAndroid Build Coastguard Worker """ Get real path from merged path. 454*c2e18aaaSAndroid Build Coastguard Worker 455*c2e18aaaSAndroid Build Coastguard Worker Turn the path string "/opt/intellij-ce-stable/bin/idea.sh -> /opt/ 456*c2e18aaaSAndroid Build Coastguard Worker intellij-ce-2019.2/bin/idea.sh" into 457*c2e18aaaSAndroid Build Coastguard Worker "/opt/intellij-ce-stable/bin/idea.sh" 458*c2e18aaaSAndroid Build Coastguard Worker 459*c2e18aaaSAndroid Build Coastguard Worker Args: 460*c2e18aaaSAndroid Build Coastguard Worker path: A path string may be merged with symbolic path. 461*c2e18aaaSAndroid Build Coastguard Worker Returns: 462*c2e18aaaSAndroid Build Coastguard Worker The real IntelliJ installed path. 463*c2e18aaaSAndroid Build Coastguard Worker """ 464*c2e18aaaSAndroid Build Coastguard Worker return path.split()[0] 465*c2e18aaaSAndroid Build Coastguard Worker 466*c2e18aaaSAndroid Build Coastguard Worker 467*c2e18aaaSAndroid Build Coastguard Workerclass IdeIntelliJ(IdeBase): 468*c2e18aaaSAndroid Build Coastguard Worker """Provide basic IntelliJ ops, e.g., launch IDEA, and config IntelliJ. 469*c2e18aaaSAndroid Build Coastguard Worker 470*c2e18aaaSAndroid Build Coastguard Worker For example: 471*c2e18aaaSAndroid Build Coastguard Worker 1. Check if IntelliJ is installed. 472*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an IntelliJ. 473*c2e18aaaSAndroid Build Coastguard Worker 3. Config IntelliJ. 474*c2e18aaaSAndroid Build Coastguard Worker """ 475*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 476*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 477*c2e18aaaSAndroid Build Coastguard Worker self._ide_name = constant.IDE_INTELLIJ 478*c2e18aaaSAndroid Build Coastguard Worker self._ls_ce_path = '' 479*c2e18aaaSAndroid Build Coastguard Worker self._ls_ue_path = '' 480*c2e18aaaSAndroid Build Coastguard Worker 481*c2e18aaaSAndroid Build Coastguard Worker def _get_config_root_paths(self): 482*c2e18aaaSAndroid Build Coastguard Worker """Get the config root paths from derived class. 483*c2e18aaaSAndroid Build Coastguard Worker 484*c2e18aaaSAndroid Build Coastguard Worker Returns: 485*c2e18aaaSAndroid Build Coastguard Worker A string list of IDE config paths, return multiple paths if more 486*c2e18aaaSAndroid Build Coastguard Worker than one path are found, return an empty list when none is found. 487*c2e18aaaSAndroid Build Coastguard Worker """ 488*c2e18aaaSAndroid Build Coastguard Worker raise NotImplementedError() 489*c2e18aaaSAndroid Build Coastguard Worker 490*c2e18aaaSAndroid Build Coastguard Worker def _get_preferred_version(self): 491*c2e18aaaSAndroid Build Coastguard Worker """Get the user's preferred IntelliJ version. 492*c2e18aaaSAndroid Build Coastguard Worker 493*c2e18aaaSAndroid Build Coastguard Worker Locates the IntelliJ IDEA launch script path by following rule. 494*c2e18aaaSAndroid Build Coastguard Worker 495*c2e18aaaSAndroid Build Coastguard Worker 1. If config file recorded user's preference version, load it. 496*c2e18aaaSAndroid Build Coastguard Worker 2. If config file didn't record, search them form default path if there 497*c2e18aaaSAndroid Build Coastguard Worker are more than one version, ask user and record it. 498*c2e18aaaSAndroid Build Coastguard Worker 499*c2e18aaaSAndroid Build Coastguard Worker Returns: 500*c2e18aaaSAndroid Build Coastguard Worker The sh full path, or None if no IntelliJ version is installed. 501*c2e18aaaSAndroid Build Coastguard Worker """ 502*c2e18aaaSAndroid Build Coastguard Worker ce_paths = ide_common_util.get_intellij_version_path(self._ls_ce_path) 503*c2e18aaaSAndroid Build Coastguard Worker ue_paths = ide_common_util.get_intellij_version_path(self._ls_ue_path) 504*c2e18aaaSAndroid Build Coastguard Worker all_versions = self._get_all_versions(ce_paths, ue_paths) 505*c2e18aaaSAndroid Build Coastguard Worker for version in list(all_versions): 506*c2e18aaaSAndroid Build Coastguard Worker real_version = os.path.realpath(version) 507*c2e18aaaSAndroid Build Coastguard Worker if (os.path.islink(version.split('/bin')[0]) and 508*c2e18aaaSAndroid Build Coastguard Worker (real_version in all_versions)): 509*c2e18aaaSAndroid Build Coastguard Worker all_versions.remove(real_version) 510*c2e18aaaSAndroid Build Coastguard Worker if config.AidegenConfig.deprecated_intellij_version(real_version): 511*c2e18aaaSAndroid Build Coastguard Worker all_versions.remove(version) 512*c2e18aaaSAndroid Build Coastguard Worker return self._get_user_preference(all_versions) 513*c2e18aaaSAndroid Build Coastguard Worker 514*c2e18aaaSAndroid Build Coastguard Worker def _setup_ide(self): 515*c2e18aaaSAndroid Build Coastguard Worker """The callback used to run the necessary setup work for the IDE. 516*c2e18aaaSAndroid Build Coastguard Worker 517*c2e18aaaSAndroid Build Coastguard Worker IntelliJ has a default flow to let the user import the configuration 518*c2e18aaaSAndroid Build Coastguard Worker from the previous version, aidegen makes sure not to break the behavior 519*c2e18aaaSAndroid Build Coastguard Worker by checking in this callback implementation. 520*c2e18aaaSAndroid Build Coastguard Worker """ 521*c2e18aaaSAndroid Build Coastguard Worker run_script_path = os.path.realpath(self._installed_path) 522*c2e18aaaSAndroid Build Coastguard Worker app_folder = self._get_application_path(run_script_path) 523*c2e18aaaSAndroid Build Coastguard Worker if not app_folder: 524*c2e18aaaSAndroid Build Coastguard Worker logging.warning('\nInvalid IDE installed path.') 525*c2e18aaaSAndroid Build Coastguard Worker return 526*c2e18aaaSAndroid Build Coastguard Worker 527*c2e18aaaSAndroid Build Coastguard Worker show_hint = False 528*c2e18aaaSAndroid Build Coastguard Worker ide_version = self._get_ide_version(app_folder) 529*c2e18aaaSAndroid Build Coastguard Worker folder_path = self._get_config_dir(ide_version, app_folder) 530*c2e18aaaSAndroid Build Coastguard Worker import_process = None 531*c2e18aaaSAndroid Build Coastguard Worker while not os.path.isdir(folder_path): 532*c2e18aaaSAndroid Build Coastguard Worker # Guide the user to go through the IDE flow. 533*c2e18aaaSAndroid Build Coastguard Worker if not show_hint: 534*c2e18aaaSAndroid Build Coastguard Worker print('\n{} {}'.format(common_util.COLORED_INFO('INFO:'), 535*c2e18aaaSAndroid Build Coastguard Worker _INFO_IMPORT_CONFIG.format( 536*c2e18aaaSAndroid Build Coastguard Worker self.ide_name))) 537*c2e18aaaSAndroid Build Coastguard Worker try: 538*c2e18aaaSAndroid Build Coastguard Worker import_process = subprocess.Popen( 539*c2e18aaaSAndroid Build Coastguard Worker ide_common_util.get_run_ide_cmd(run_script_path, '', 540*c2e18aaaSAndroid Build Coastguard Worker False), shell=True) 541*c2e18aaaSAndroid Build Coastguard Worker except (subprocess.SubprocessError, ValueError): 542*c2e18aaaSAndroid Build Coastguard Worker logging.warning('\nSubprocess call gets the invalid input.') 543*c2e18aaaSAndroid Build Coastguard Worker finally: 544*c2e18aaaSAndroid Build Coastguard Worker show_hint = True 545*c2e18aaaSAndroid Build Coastguard Worker if import_process: 546*c2e18aaaSAndroid Build Coastguard Worker try: 547*c2e18aaaSAndroid Build Coastguard Worker import_process.wait(1) 548*c2e18aaaSAndroid Build Coastguard Worker except subprocess.TimeoutExpired: 549*c2e18aaaSAndroid Build Coastguard Worker import_process.terminate() 550*c2e18aaaSAndroid Build Coastguard Worker return 551*c2e18aaaSAndroid Build Coastguard Worker 552*c2e18aaaSAndroid Build Coastguard Worker def _get_script_from_system(self): 553*c2e18aaaSAndroid Build Coastguard Worker """Get correct IntelliJ installed path from internal path. 554*c2e18aaaSAndroid Build Coastguard Worker 555*c2e18aaaSAndroid Build Coastguard Worker Returns: 556*c2e18aaaSAndroid Build Coastguard Worker The sh full path, or None if no IntelliJ version is installed. 557*c2e18aaaSAndroid Build Coastguard Worker """ 558*c2e18aaaSAndroid Build Coastguard Worker found = self._get_preferred_version() 559*c2e18aaaSAndroid Build Coastguard Worker if found: 560*c2e18aaaSAndroid Build Coastguard Worker logging.debug('IDE internal installed path: %s.', found) 561*c2e18aaaSAndroid Build Coastguard Worker return found 562*c2e18aaaSAndroid Build Coastguard Worker 563*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 564*c2e18aaaSAndroid Build Coastguard Worker def _get_all_versions(cefiles, uefiles): 565*c2e18aaaSAndroid Build Coastguard Worker """Get all versions of launch script files. 566*c2e18aaaSAndroid Build Coastguard Worker 567*c2e18aaaSAndroid Build Coastguard Worker Args: 568*c2e18aaaSAndroid Build Coastguard Worker cefiles: CE version launch script paths. 569*c2e18aaaSAndroid Build Coastguard Worker uefiles: UE version launch script paths. 570*c2e18aaaSAndroid Build Coastguard Worker 571*c2e18aaaSAndroid Build Coastguard Worker Returns: 572*c2e18aaaSAndroid Build Coastguard Worker A list contains all versions of launch script files. 573*c2e18aaaSAndroid Build Coastguard Worker """ 574*c2e18aaaSAndroid Build Coastguard Worker all_versions = [] 575*c2e18aaaSAndroid Build Coastguard Worker if cefiles: 576*c2e18aaaSAndroid Build Coastguard Worker all_versions.extend(cefiles) 577*c2e18aaaSAndroid Build Coastguard Worker if uefiles: 578*c2e18aaaSAndroid Build Coastguard Worker all_versions.extend(uefiles) 579*c2e18aaaSAndroid Build Coastguard Worker return all_versions 580*c2e18aaaSAndroid Build Coastguard Worker 581*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 582*c2e18aaaSAndroid Build Coastguard Worker def _get_application_path(run_script_path): 583*c2e18aaaSAndroid Build Coastguard Worker """Get the relevant configuration folder based on the run script path. 584*c2e18aaaSAndroid Build Coastguard Worker 585*c2e18aaaSAndroid Build Coastguard Worker Args: 586*c2e18aaaSAndroid Build Coastguard Worker run_script_path: The string of the run script path for the IntelliJ. 587*c2e18aaaSAndroid Build Coastguard Worker 588*c2e18aaaSAndroid Build Coastguard Worker Returns: 589*c2e18aaaSAndroid Build Coastguard Worker The string of the IntelliJ application folder name or None if the 590*c2e18aaaSAndroid Build Coastguard Worker run_script_path is invalid. The returned folder format is as 591*c2e18aaaSAndroid Build Coastguard Worker follows, 592*c2e18aaaSAndroid Build Coastguard Worker 1. .IdeaIC2019.3 593*c2e18aaaSAndroid Build Coastguard Worker 2. .IntelliJIdea2019.3 594*c2e18aaaSAndroid Build Coastguard Worker 3. IntelliJIdea2020.1 595*c2e18aaaSAndroid Build Coastguard Worker """ 596*c2e18aaaSAndroid Build Coastguard Worker if not run_script_path or not os.path.isfile(run_script_path): 597*c2e18aaaSAndroid Build Coastguard Worker return None 598*c2e18aaaSAndroid Build Coastguard Worker index = str.find(run_script_path, 'intellij-') 599*c2e18aaaSAndroid Build Coastguard Worker target_path = None if index == -1 else run_script_path[index:] 600*c2e18aaaSAndroid Build Coastguard Worker if not target_path or '-' not in run_script_path: 601*c2e18aaaSAndroid Build Coastguard Worker return None 602*c2e18aaaSAndroid Build Coastguard Worker return IdeIntelliJ._get_config_folder_name(target_path) 603*c2e18aaaSAndroid Build Coastguard Worker 604*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 605*c2e18aaaSAndroid Build Coastguard Worker def _get_ide_version(config_folder_name): 606*c2e18aaaSAndroid Build Coastguard Worker """Gets IntelliJ version from the input app folder name. 607*c2e18aaaSAndroid Build Coastguard Worker 608*c2e18aaaSAndroid Build Coastguard Worker Args: 609*c2e18aaaSAndroid Build Coastguard Worker config_folder_name: A string of the app folder name. 610*c2e18aaaSAndroid Build Coastguard Worker 611*c2e18aaaSAndroid Build Coastguard Worker Returns: 612*c2e18aaaSAndroid Build Coastguard Worker A string of the IntelliJ version. 613*c2e18aaaSAndroid Build Coastguard Worker """ 614*c2e18aaaSAndroid Build Coastguard Worker versions = re.findall(r'\d+', config_folder_name) 615*c2e18aaaSAndroid Build Coastguard Worker if not versions: 616*c2e18aaaSAndroid Build Coastguard Worker logging.warning('\nInvalid IntelliJ config folder name: %s.', 617*c2e18aaaSAndroid Build Coastguard Worker config_folder_name) 618*c2e18aaaSAndroid Build Coastguard Worker return None 619*c2e18aaaSAndroid Build Coastguard Worker return '.'.join(versions) 620*c2e18aaaSAndroid Build Coastguard Worker 621*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 622*c2e18aaaSAndroid Build Coastguard Worker def _get_config_folder_name(script_folder_name): 623*c2e18aaaSAndroid Build Coastguard Worker """Gets IntelliJ config folder name from the IDE version. 624*c2e18aaaSAndroid Build Coastguard Worker 625*c2e18aaaSAndroid Build Coastguard Worker The config folder name has been changed since 2020.1. 626*c2e18aaaSAndroid Build Coastguard Worker 627*c2e18aaaSAndroid Build Coastguard Worker Args: 628*c2e18aaaSAndroid Build Coastguard Worker script_folder_name: A string of the script folder name of IntelliJ. 629*c2e18aaaSAndroid Build Coastguard Worker 630*c2e18aaaSAndroid Build Coastguard Worker Returns: 631*c2e18aaaSAndroid Build Coastguard Worker A string of the IntelliJ config folder name. 632*c2e18aaaSAndroid Build Coastguard Worker """ 633*c2e18aaaSAndroid Build Coastguard Worker path_data = script_folder_name.split('-') 634*c2e18aaaSAndroid Build Coastguard Worker if not path_data or len(path_data) < 3: 635*c2e18aaaSAndroid Build Coastguard Worker return None 636*c2e18aaaSAndroid Build Coastguard Worker ide_version = path_data[2].split(os.sep)[0] 637*c2e18aaaSAndroid Build Coastguard Worker numbers = ide_version.split('.') 638*c2e18aaaSAndroid Build Coastguard Worker if len(numbers) > 2: 639*c2e18aaaSAndroid Build Coastguard Worker ide_version = '.'.join([numbers[0], numbers[1]]) 640*c2e18aaaSAndroid Build Coastguard Worker try: 641*c2e18aaaSAndroid Build Coastguard Worker version = float(ide_version) 642*c2e18aaaSAndroid Build Coastguard Worker except ValueError: 643*c2e18aaaSAndroid Build Coastguard Worker return None 644*c2e18aaaSAndroid Build Coastguard Worker pre_folder = '.IdeaIC' 645*c2e18aaaSAndroid Build Coastguard Worker if version < _SPECIFIC_INTELLIJ_VERSION: 646*c2e18aaaSAndroid Build Coastguard Worker if path_data[1] == 'ue': 647*c2e18aaaSAndroid Build Coastguard Worker pre_folder = '.IntelliJIdea' 648*c2e18aaaSAndroid Build Coastguard Worker else: 649*c2e18aaaSAndroid Build Coastguard Worker if path_data[1] == 'ce': 650*c2e18aaaSAndroid Build Coastguard Worker pre_folder = 'IdeaIC' 651*c2e18aaaSAndroid Build Coastguard Worker elif path_data[1] == 'ue': 652*c2e18aaaSAndroid Build Coastguard Worker pre_folder = 'IntelliJIdea' 653*c2e18aaaSAndroid Build Coastguard Worker return ''.join([pre_folder, ide_version]) 654*c2e18aaaSAndroid Build Coastguard Worker 655*c2e18aaaSAndroid Build Coastguard Worker @staticmethod 656*c2e18aaaSAndroid Build Coastguard Worker def _get_config_dir(ide_version, config_folder_name): 657*c2e18aaaSAndroid Build Coastguard Worker """Gets IntelliJ config directory by the config folder name. 658*c2e18aaaSAndroid Build Coastguard Worker 659*c2e18aaaSAndroid Build Coastguard Worker The IntelliJ config directory is changed from version 2020.1. Get the 660*c2e18aaaSAndroid Build Coastguard Worker version from app folder name and determine the config directory. 661*c2e18aaaSAndroid Build Coastguard Worker URL: https://intellij-support.jetbrains.com/hc/en-us/articles/206544519 662*c2e18aaaSAndroid Build Coastguard Worker 663*c2e18aaaSAndroid Build Coastguard Worker Args: 664*c2e18aaaSAndroid Build Coastguard Worker ide_version: A string of the IntelliJ's version. 665*c2e18aaaSAndroid Build Coastguard Worker config_folder_name: A string of the IntelliJ's config folder name. 666*c2e18aaaSAndroid Build Coastguard Worker 667*c2e18aaaSAndroid Build Coastguard Worker Returns: 668*c2e18aaaSAndroid Build Coastguard Worker A string of the IntelliJ config directory. 669*c2e18aaaSAndroid Build Coastguard Worker """ 670*c2e18aaaSAndroid Build Coastguard Worker try: 671*c2e18aaaSAndroid Build Coastguard Worker version = float(ide_version) 672*c2e18aaaSAndroid Build Coastguard Worker except ValueError: 673*c2e18aaaSAndroid Build Coastguard Worker return None 674*c2e18aaaSAndroid Build Coastguard Worker if version < _SPECIFIC_INTELLIJ_VERSION: 675*c2e18aaaSAndroid Build Coastguard Worker return os.path.join( 676*c2e18aaaSAndroid Build Coastguard Worker os.getenv('HOME'), config_folder_name) 677*c2e18aaaSAndroid Build Coastguard Worker return os.path.join( 678*c2e18aaaSAndroid Build Coastguard Worker os.getenv('HOME'), '.config', 'JetBrains', config_folder_name) 679*c2e18aaaSAndroid Build Coastguard Worker 680*c2e18aaaSAndroid Build Coastguard Worker 681*c2e18aaaSAndroid Build Coastguard Workerclass IdeLinuxIntelliJ(IdeIntelliJ): 682*c2e18aaaSAndroid Build Coastguard Worker """Provide the IDEA behavior implementation for OS Linux. 683*c2e18aaaSAndroid Build Coastguard Worker 684*c2e18aaaSAndroid Build Coastguard Worker Class Attributes: 685*c2e18aaaSAndroid Build Coastguard Worker _INTELLIJ_RE: Regular expression of IntelliJ installed name in GLinux. 686*c2e18aaaSAndroid Build Coastguard Worker 687*c2e18aaaSAndroid Build Coastguard Worker For example: 688*c2e18aaaSAndroid Build Coastguard Worker 1. Check if IntelliJ is installed. 689*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an IntelliJ. 690*c2e18aaaSAndroid Build Coastguard Worker 3. Config IntelliJ. 691*c2e18aaaSAndroid Build Coastguard Worker """ 692*c2e18aaaSAndroid Build Coastguard Worker 693*c2e18aaaSAndroid Build Coastguard Worker _JDK_PATH = LINUX_JDK_PATH 694*c2e18aaaSAndroid Build Coastguard Worker # TODO(b/127899277): Preserve a config for jdk version option case. 695*c2e18aaaSAndroid Build Coastguard Worker _CONFIG_DIR = CONFIG_DIR 696*c2e18aaaSAndroid Build Coastguard Worker _IDE_JDK_TABLE_PATH = LINUX_JDK_TABLE_PATH 697*c2e18aaaSAndroid Build Coastguard Worker _IDE_FILE_TYPE_PATH = LINUX_FILE_TYPE_PATH 698*c2e18aaaSAndroid Build Coastguard Worker _JDK_CONTENT = templates.LINUX_JDK_XML 699*c2e18aaaSAndroid Build Coastguard Worker _DEFAULT_ANDROID_SDK_PATH = LINUX_ANDROID_SDK_PATH 700*c2e18aaaSAndroid Build Coastguard Worker _SYMBOLIC_VERSIONS = ['/opt/intellij-ce-stable/bin/idea.sh', 701*c2e18aaaSAndroid Build Coastguard Worker '/opt/intellij-ue-stable/bin/idea.sh', 702*c2e18aaaSAndroid Build Coastguard Worker '/opt/intellij-ce-beta/bin/idea.sh', 703*c2e18aaaSAndroid Build Coastguard Worker '/opt/intellij-ue-beta/bin/idea.sh'] 704*c2e18aaaSAndroid Build Coastguard Worker _INTELLIJ_RE = re.compile(r'intellij-(ce|ue)-') 705*c2e18aaaSAndroid Build Coastguard Worker 706*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 707*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 708*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name = 'idea.sh' 709*c2e18aaaSAndroid Build Coastguard Worker self._bin_folders = ['/opt/intellij-*/bin'] 710*c2e18aaaSAndroid Build Coastguard Worker self._ls_ce_path = os.path.join('/opt/intellij-ce-*/bin', 711*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name) 712*c2e18aaaSAndroid Build Coastguard Worker self._ls_ue_path = os.path.join('/opt/intellij-ue-*/bin', 713*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name) 714*c2e18aaaSAndroid Build Coastguard Worker self._init_installed_path(installed_path) 715*c2e18aaaSAndroid Build Coastguard Worker 716*c2e18aaaSAndroid Build Coastguard Worker def _get_config_root_paths(self): 717*c2e18aaaSAndroid Build Coastguard Worker """To collect the global config folder paths of IDEA as a string list. 718*c2e18aaaSAndroid Build Coastguard Worker 719*c2e18aaaSAndroid Build Coastguard Worker The config folder of IntelliJ IDEA is under the user's home directory, 720*c2e18aaaSAndroid Build Coastguard Worker .IdeaIC20xx.x and .IntelliJIdea20xx.x are folder names for different 721*c2e18aaaSAndroid Build Coastguard Worker versions. 722*c2e18aaaSAndroid Build Coastguard Worker 723*c2e18aaaSAndroid Build Coastguard Worker Returns: 724*c2e18aaaSAndroid Build Coastguard Worker A string list for IDE config root paths, and return an empty list 725*c2e18aaaSAndroid Build Coastguard Worker when none is found. 726*c2e18aaaSAndroid Build Coastguard Worker """ 727*c2e18aaaSAndroid Build Coastguard Worker if not self._installed_path: 728*c2e18aaaSAndroid Build Coastguard Worker return None 729*c2e18aaaSAndroid Build Coastguard Worker 730*c2e18aaaSAndroid Build Coastguard Worker _config_folders = [] 731*c2e18aaaSAndroid Build Coastguard Worker _config_folder = '' 732*c2e18aaaSAndroid Build Coastguard Worker if IdeLinuxIntelliJ._INTELLIJ_RE.search(self._installed_path): 733*c2e18aaaSAndroid Build Coastguard Worker _path_data = os.path.realpath(self._installed_path) 734*c2e18aaaSAndroid Build Coastguard Worker _config_folder = self._get_application_path(_path_data) 735*c2e18aaaSAndroid Build Coastguard Worker if not _config_folder: 736*c2e18aaaSAndroid Build Coastguard Worker return None 737*c2e18aaaSAndroid Build Coastguard Worker ide_version = self._get_ide_version(_config_folder) 738*c2e18aaaSAndroid Build Coastguard Worker if not ide_version: 739*c2e18aaaSAndroid Build Coastguard Worker return None 740*c2e18aaaSAndroid Build Coastguard Worker try: 741*c2e18aaaSAndroid Build Coastguard Worker version = float(ide_version) 742*c2e18aaaSAndroid Build Coastguard Worker except ValueError: 743*c2e18aaaSAndroid Build Coastguard Worker return None 744*c2e18aaaSAndroid Build Coastguard Worker folder_path = self._get_config_dir(ide_version, _config_folder) 745*c2e18aaaSAndroid Build Coastguard Worker if version >= _SPECIFIC_INTELLIJ_VERSION: 746*c2e18aaaSAndroid Build Coastguard Worker self._IDE_JDK_TABLE_PATH = ALTERNATIVE_JDK_TABLE_PATH 747*c2e18aaaSAndroid Build Coastguard Worker self._IDE_FILE_TYPE_PATH = ALTERNATIVE_FILE_TYPE_XML_PATH 748*c2e18aaaSAndroid Build Coastguard Worker 749*c2e18aaaSAndroid Build Coastguard Worker if not os.path.isdir(folder_path): 750*c2e18aaaSAndroid Build Coastguard Worker logging.debug("\nThe config folder: %s doesn't exist", 751*c2e18aaaSAndroid Build Coastguard Worker _config_folder) 752*c2e18aaaSAndroid Build Coastguard Worker self._setup_ide() 753*c2e18aaaSAndroid Build Coastguard Worker 754*c2e18aaaSAndroid Build Coastguard Worker _config_folders.append(folder_path) 755*c2e18aaaSAndroid Build Coastguard Worker else: 756*c2e18aaaSAndroid Build Coastguard Worker # TODO(b/123459239): For the case that the user provides the IDEA 757*c2e18aaaSAndroid Build Coastguard Worker # binary path, we now collect all possible IDEA config root paths. 758*c2e18aaaSAndroid Build Coastguard Worker _config_folders = glob.glob( 759*c2e18aaaSAndroid Build Coastguard Worker os.path.join(os.getenv('HOME'), '.IdeaI?20*')) 760*c2e18aaaSAndroid Build Coastguard Worker _config_folders.extend( 761*c2e18aaaSAndroid Build Coastguard Worker glob.glob(os.path.join(os.getenv('HOME'), '.IntelliJIdea20*'))) 762*c2e18aaaSAndroid Build Coastguard Worker _config_folders.extend( 763*c2e18aaaSAndroid Build Coastguard Worker glob.glob(os.path.join(os.getenv('HOME'), '.config', 764*c2e18aaaSAndroid Build Coastguard Worker 'IntelliJIdea202*'))) 765*c2e18aaaSAndroid Build Coastguard Worker logging.debug('The config path list: %s.', _config_folders) 766*c2e18aaaSAndroid Build Coastguard Worker 767*c2e18aaaSAndroid Build Coastguard Worker return _config_folders 768*c2e18aaaSAndroid Build Coastguard Worker 769*c2e18aaaSAndroid Build Coastguard Worker 770*c2e18aaaSAndroid Build Coastguard Workerclass IdeMacIntelliJ(IdeIntelliJ): 771*c2e18aaaSAndroid Build Coastguard Worker """Provide the IDEA behavior implementation for OS Mac. 772*c2e18aaaSAndroid Build Coastguard Worker 773*c2e18aaaSAndroid Build Coastguard Worker For example: 774*c2e18aaaSAndroid Build Coastguard Worker 1. Check if IntelliJ is installed. 775*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an IntelliJ. 776*c2e18aaaSAndroid Build Coastguard Worker 3. Config IntelliJ. 777*c2e18aaaSAndroid Build Coastguard Worker """ 778*c2e18aaaSAndroid Build Coastguard Worker 779*c2e18aaaSAndroid Build Coastguard Worker _JDK_PATH = MAC_JDK_PATH 780*c2e18aaaSAndroid Build Coastguard Worker _IDE_JDK_TABLE_PATH = ALTERNATIVE_JDK_TABLE_PATH 781*c2e18aaaSAndroid Build Coastguard Worker _IDE_FILE_TYPE_PATH = ALTERNATIVE_FILE_TYPE_XML_PATH 782*c2e18aaaSAndroid Build Coastguard Worker _JDK_CONTENT = templates.MAC_JDK_XML 783*c2e18aaaSAndroid Build Coastguard Worker _DEFAULT_ANDROID_SDK_PATH = MAC_ANDROID_SDK_PATH 784*c2e18aaaSAndroid Build Coastguard Worker 785*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 786*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 787*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name = 'idea' 788*c2e18aaaSAndroid Build Coastguard Worker self._bin_folders = ['/Applications/IntelliJ IDEA.app/Contents/MacOS'] 789*c2e18aaaSAndroid Build Coastguard Worker self._bin_paths = self._get_possible_bin_paths() 790*c2e18aaaSAndroid Build Coastguard Worker self._ls_ce_path = os.path.join( 791*c2e18aaaSAndroid Build Coastguard Worker '/Applications/IntelliJ IDEA CE.app/Contents/MacOS', 792*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name) 793*c2e18aaaSAndroid Build Coastguard Worker self._ls_ue_path = os.path.join( 794*c2e18aaaSAndroid Build Coastguard Worker '/Applications/IntelliJ IDEA.app/Contents/MacOS', 795*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name) 796*c2e18aaaSAndroid Build Coastguard Worker self._init_installed_path(installed_path) 797*c2e18aaaSAndroid Build Coastguard Worker 798*c2e18aaaSAndroid Build Coastguard Worker def _get_config_root_paths(self): 799*c2e18aaaSAndroid Build Coastguard Worker """To collect the global config folder paths of IDEA as a string list. 800*c2e18aaaSAndroid Build Coastguard Worker 801*c2e18aaaSAndroid Build Coastguard Worker Returns: 802*c2e18aaaSAndroid Build Coastguard Worker A string list for IDE config root paths, and return an empty list 803*c2e18aaaSAndroid Build Coastguard Worker when none is found. 804*c2e18aaaSAndroid Build Coastguard Worker """ 805*c2e18aaaSAndroid Build Coastguard Worker if not self._installed_path: 806*c2e18aaaSAndroid Build Coastguard Worker return None 807*c2e18aaaSAndroid Build Coastguard Worker 808*c2e18aaaSAndroid Build Coastguard Worker _config_folders = [] 809*c2e18aaaSAndroid Build Coastguard Worker if 'IntelliJ' in self._installed_path: 810*c2e18aaaSAndroid Build Coastguard Worker _config_folders = glob.glob( 811*c2e18aaaSAndroid Build Coastguard Worker os.path.join( 812*c2e18aaaSAndroid Build Coastguard Worker os.getenv('HOME'), 'Library/Preferences/IdeaI?20*')) 813*c2e18aaaSAndroid Build Coastguard Worker _config_folders.extend( 814*c2e18aaaSAndroid Build Coastguard Worker glob.glob( 815*c2e18aaaSAndroid Build Coastguard Worker os.path.join( 816*c2e18aaaSAndroid Build Coastguard Worker os.getenv('HOME'), 817*c2e18aaaSAndroid Build Coastguard Worker 'Library/Preferences/IntelliJIdea20*'))) 818*c2e18aaaSAndroid Build Coastguard Worker return _config_folders 819*c2e18aaaSAndroid Build Coastguard Worker 820*c2e18aaaSAndroid Build Coastguard Worker 821*c2e18aaaSAndroid Build Coastguard Workerclass IdeStudio(IdeBase): 822*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of Android Studio launching utilities. 823*c2e18aaaSAndroid Build Coastguard Worker 824*c2e18aaaSAndroid Build Coastguard Worker For example: 825*c2e18aaaSAndroid Build Coastguard Worker 1. Check if Android Studio is installed. 826*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an Android Studio. 827*c2e18aaaSAndroid Build Coastguard Worker 3. Config Android Studio. 828*c2e18aaaSAndroid Build Coastguard Worker """ 829*c2e18aaaSAndroid Build Coastguard Worker 830*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 831*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 832*c2e18aaaSAndroid Build Coastguard Worker self._ide_name = constant.IDE_ANDROID_STUDIO 833*c2e18aaaSAndroid Build Coastguard Worker 834*c2e18aaaSAndroid Build Coastguard Worker def _get_config_root_paths(self): 835*c2e18aaaSAndroid Build Coastguard Worker """Get the config root paths from derived class. 836*c2e18aaaSAndroid Build Coastguard Worker 837*c2e18aaaSAndroid Build Coastguard Worker Returns: 838*c2e18aaaSAndroid Build Coastguard Worker A string list of IDE config paths, return multiple paths if more 839*c2e18aaaSAndroid Build Coastguard Worker than one path are found, return an empty list when none is found. 840*c2e18aaaSAndroid Build Coastguard Worker """ 841*c2e18aaaSAndroid Build Coastguard Worker raise NotImplementedError() 842*c2e18aaaSAndroid Build Coastguard Worker 843*c2e18aaaSAndroid Build Coastguard Worker def _get_script_from_system(self): 844*c2e18aaaSAndroid Build Coastguard Worker """Get correct Studio installed path from internal path. 845*c2e18aaaSAndroid Build Coastguard Worker 846*c2e18aaaSAndroid Build Coastguard Worker Returns: 847*c2e18aaaSAndroid Build Coastguard Worker The sh full path, or None if no Studio version is installed. 848*c2e18aaaSAndroid Build Coastguard Worker """ 849*c2e18aaaSAndroid Build Coastguard Worker found = self._get_preferred_version() 850*c2e18aaaSAndroid Build Coastguard Worker if found: 851*c2e18aaaSAndroid Build Coastguard Worker logging.debug('IDE internal installed path: %s.', found) 852*c2e18aaaSAndroid Build Coastguard Worker return found 853*c2e18aaaSAndroid Build Coastguard Worker 854*c2e18aaaSAndroid Build Coastguard Worker def _get_preferred_version(self): 855*c2e18aaaSAndroid Build Coastguard Worker """Get the user's preferred Studio version. 856*c2e18aaaSAndroid Build Coastguard Worker 857*c2e18aaaSAndroid Build Coastguard Worker Locates the Studio launch script path by following rule. 858*c2e18aaaSAndroid Build Coastguard Worker 859*c2e18aaaSAndroid Build Coastguard Worker 1. If config file recorded user's preference version, load it. 860*c2e18aaaSAndroid Build Coastguard Worker 2. If config file didn't record, search them form default path if there 861*c2e18aaaSAndroid Build Coastguard Worker are more than one version, ask user and record it. 862*c2e18aaaSAndroid Build Coastguard Worker 863*c2e18aaaSAndroid Build Coastguard Worker Returns: 864*c2e18aaaSAndroid Build Coastguard Worker The sh full path, or None if no Studio version is installed. 865*c2e18aaaSAndroid Build Coastguard Worker """ 866*c2e18aaaSAndroid Build Coastguard Worker all_versions = self._get_existent_scripts_in_system() 867*c2e18aaaSAndroid Build Coastguard Worker if not all_versions: 868*c2e18aaaSAndroid Build Coastguard Worker return None 869*c2e18aaaSAndroid Build Coastguard Worker for version in list(all_versions): 870*c2e18aaaSAndroid Build Coastguard Worker real_version = os.path.realpath(version) 871*c2e18aaaSAndroid Build Coastguard Worker if (os.path.islink(version.split('/bin')[0]) and 872*c2e18aaaSAndroid Build Coastguard Worker (real_version in all_versions)): 873*c2e18aaaSAndroid Build Coastguard Worker all_versions.remove(real_version) 874*c2e18aaaSAndroid Build Coastguard Worker if config.AidegenConfig.deprecated_studio_version(real_version): 875*c2e18aaaSAndroid Build Coastguard Worker all_versions.remove(version) 876*c2e18aaaSAndroid Build Coastguard Worker return self._get_user_preference(all_versions) 877*c2e18aaaSAndroid Build Coastguard Worker 878*c2e18aaaSAndroid Build Coastguard Worker def apply_optional_config(self): 879*c2e18aaaSAndroid Build Coastguard Worker """Do the configuration of Android Studio. 880*c2e18aaaSAndroid Build Coastguard Worker 881*c2e18aaaSAndroid Build Coastguard Worker Configures code style and SDK for Java project and do nothing for 882*c2e18aaaSAndroid Build Coastguard Worker others. 883*c2e18aaaSAndroid Build Coastguard Worker """ 884*c2e18aaaSAndroid Build Coastguard Worker if not self.project_abspath: 885*c2e18aaaSAndroid Build Coastguard Worker return 886*c2e18aaaSAndroid Build Coastguard Worker # TODO(b/150662865): The following workaround should be replaced. 887*c2e18aaaSAndroid Build Coastguard Worker # Since the path of the artifact for Java is the .idea directory but 888*c2e18aaaSAndroid Build Coastguard Worker # native is a CMakeLists.txt file using this to workaround first. 889*c2e18aaaSAndroid Build Coastguard Worker if os.path.isfile(self.project_abspath): 890*c2e18aaaSAndroid Build Coastguard Worker return 891*c2e18aaaSAndroid Build Coastguard Worker if os.path.isdir(self.project_abspath): 892*c2e18aaaSAndroid Build Coastguard Worker IdeBase.apply_optional_config(self) 893*c2e18aaaSAndroid Build Coastguard Worker 894*c2e18aaaSAndroid Build Coastguard Worker 895*c2e18aaaSAndroid Build Coastguard Workerclass IdeLinuxStudio(IdeStudio): 896*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of Android Studio launching utilities for OS Linux. 897*c2e18aaaSAndroid Build Coastguard Worker 898*c2e18aaaSAndroid Build Coastguard Worker For example: 899*c2e18aaaSAndroid Build Coastguard Worker 1. Check if Android Studio is installed. 900*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an Android Studio. 901*c2e18aaaSAndroid Build Coastguard Worker 3. Config Android Studio. 902*c2e18aaaSAndroid Build Coastguard Worker """ 903*c2e18aaaSAndroid Build Coastguard Worker 904*c2e18aaaSAndroid Build Coastguard Worker _JDK_PATH = LINUX_JDK_PATH 905*c2e18aaaSAndroid Build Coastguard Worker _CONFIG_DIR = CONFIG_DIR 906*c2e18aaaSAndroid Build Coastguard Worker _IDE_JDK_TABLE_PATH = LINUX_JDK_TABLE_PATH 907*c2e18aaaSAndroid Build Coastguard Worker _JDK_CONTENT = templates.LINUX_JDK_XML 908*c2e18aaaSAndroid Build Coastguard Worker _DEFAULT_ANDROID_SDK_PATH = LINUX_ANDROID_SDK_PATH 909*c2e18aaaSAndroid Build Coastguard Worker _SYMBOLIC_VERSIONS = [ 910*c2e18aaaSAndroid Build Coastguard Worker '/opt/android-studio-with-blaze-stable/bin/studio.sh', 911*c2e18aaaSAndroid Build Coastguard Worker '/opt/android-studio-stable/bin/studio.sh', 912*c2e18aaaSAndroid Build Coastguard Worker '/opt/android-studio-with-blaze-beta/bin/studio.sh', 913*c2e18aaaSAndroid Build Coastguard Worker '/opt/android-studio-beta/bin/studio.sh'] 914*c2e18aaaSAndroid Build Coastguard Worker 915*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 916*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 917*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name = 'studio.sh' 918*c2e18aaaSAndroid Build Coastguard Worker self._bin_folders = ['/opt/android-studio*/bin'] 919*c2e18aaaSAndroid Build Coastguard Worker self._bin_paths = self._get_possible_bin_paths() 920*c2e18aaaSAndroid Build Coastguard Worker self._init_installed_path(installed_path) 921*c2e18aaaSAndroid Build Coastguard Worker 922*c2e18aaaSAndroid Build Coastguard Worker def _get_config_root_paths(self): 923*c2e18aaaSAndroid Build Coastguard Worker """Collect the global config folder paths as a string list. 924*c2e18aaaSAndroid Build Coastguard Worker 925*c2e18aaaSAndroid Build Coastguard Worker Returns: 926*c2e18aaaSAndroid Build Coastguard Worker A string list for IDE config root paths, and return an empty list 927*c2e18aaaSAndroid Build Coastguard Worker when none is found. 928*c2e18aaaSAndroid Build Coastguard Worker """ 929*c2e18aaaSAndroid Build Coastguard Worker return glob.glob(os.path.join(os.getenv('HOME'), '.AndroidStudio*')) 930*c2e18aaaSAndroid Build Coastguard Worker 931*c2e18aaaSAndroid Build Coastguard Worker 932*c2e18aaaSAndroid Build Coastguard Workerclass IdeMacStudio(IdeStudio): 933*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of Android Studio launching utilities for OS Mac. 934*c2e18aaaSAndroid Build Coastguard Worker 935*c2e18aaaSAndroid Build Coastguard Worker For example: 936*c2e18aaaSAndroid Build Coastguard Worker 1. Check if Android Studio is installed. 937*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an Android Studio. 938*c2e18aaaSAndroid Build Coastguard Worker 3. Config Android Studio. 939*c2e18aaaSAndroid Build Coastguard Worker """ 940*c2e18aaaSAndroid Build Coastguard Worker 941*c2e18aaaSAndroid Build Coastguard Worker _JDK_PATH = MAC_JDK_PATH 942*c2e18aaaSAndroid Build Coastguard Worker _IDE_JDK_TABLE_PATH = ALTERNATIVE_JDK_TABLE_PATH 943*c2e18aaaSAndroid Build Coastguard Worker _JDK_CONTENT = templates.MAC_JDK_XML 944*c2e18aaaSAndroid Build Coastguard Worker _DEFAULT_ANDROID_SDK_PATH = MAC_ANDROID_SDK_PATH 945*c2e18aaaSAndroid Build Coastguard Worker 946*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 947*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 948*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name = 'studio' 949*c2e18aaaSAndroid Build Coastguard Worker self._bin_folders = ['/Applications/Android Studio.app/Contents/MacOS'] 950*c2e18aaaSAndroid Build Coastguard Worker self._bin_paths = self._get_possible_bin_paths() 951*c2e18aaaSAndroid Build Coastguard Worker self._init_installed_path(installed_path) 952*c2e18aaaSAndroid Build Coastguard Worker 953*c2e18aaaSAndroid Build Coastguard Worker def _get_config_root_paths(self): 954*c2e18aaaSAndroid Build Coastguard Worker """Collect the global config folder paths as a string list. 955*c2e18aaaSAndroid Build Coastguard Worker 956*c2e18aaaSAndroid Build Coastguard Worker Returns: 957*c2e18aaaSAndroid Build Coastguard Worker A string list for IDE config root paths, and return an empty list 958*c2e18aaaSAndroid Build Coastguard Worker when none is found. 959*c2e18aaaSAndroid Build Coastguard Worker """ 960*c2e18aaaSAndroid Build Coastguard Worker return glob.glob( 961*c2e18aaaSAndroid Build Coastguard Worker os.path.join( 962*c2e18aaaSAndroid Build Coastguard Worker os.getenv('HOME'), 'Library/Preferences/AndroidStudio*')) 963*c2e18aaaSAndroid Build Coastguard Worker 964*c2e18aaaSAndroid Build Coastguard Worker 965*c2e18aaaSAndroid Build Coastguard Workerclass IdeEclipse(IdeBase): 966*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of Eclipse launching utilities. 967*c2e18aaaSAndroid Build Coastguard Worker 968*c2e18aaaSAndroid Build Coastguard Worker Attributes: 969*c2e18aaaSAndroid Build Coastguard Worker cmd: A list of the build command. 970*c2e18aaaSAndroid Build Coastguard Worker 971*c2e18aaaSAndroid Build Coastguard Worker For example: 972*c2e18aaaSAndroid Build Coastguard Worker 1. Check if Eclipse is installed. 973*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an Eclipse. 974*c2e18aaaSAndroid Build Coastguard Worker """ 975*c2e18aaaSAndroid Build Coastguard Worker 976*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 977*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 978*c2e18aaaSAndroid Build Coastguard Worker self._ide_name = constant.IDE_ECLIPSE 979*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name = 'eclipse' 980*c2e18aaaSAndroid Build Coastguard Worker self.cmd = [] 981*c2e18aaaSAndroid Build Coastguard Worker 982*c2e18aaaSAndroid Build Coastguard Worker def _get_script_from_system(self): 983*c2e18aaaSAndroid Build Coastguard Worker """Get correct IDE installed path from internal path. 984*c2e18aaaSAndroid Build Coastguard Worker 985*c2e18aaaSAndroid Build Coastguard Worker Remove any file with extension, the filename should be like, 'eclipse', 986*c2e18aaaSAndroid Build Coastguard Worker 'eclipse47' and so on, check if the file is executable and filter out 987*c2e18aaaSAndroid Build Coastguard Worker file such as 'eclipse.ini'. 988*c2e18aaaSAndroid Build Coastguard Worker 989*c2e18aaaSAndroid Build Coastguard Worker Returns: 990*c2e18aaaSAndroid Build Coastguard Worker The sh full path, or None if no IntelliJ version is installed. 991*c2e18aaaSAndroid Build Coastguard Worker """ 992*c2e18aaaSAndroid Build Coastguard Worker for ide_path in self._bin_paths: 993*c2e18aaaSAndroid Build Coastguard Worker # The binary name of Eclipse could be eclipse47, eclipse49, 994*c2e18aaaSAndroid Build Coastguard Worker # eclipse47_testing or eclipse49_testing. So finding the matched 995*c2e18aaaSAndroid Build Coastguard Worker # binary by /path/to/ide/eclipse*. 996*c2e18aaaSAndroid Build Coastguard Worker ls_output = glob.glob(ide_path + '*', recursive=True) 997*c2e18aaaSAndroid Build Coastguard Worker if ls_output: 998*c2e18aaaSAndroid Build Coastguard Worker ls_output = sorted(ls_output) 999*c2e18aaaSAndroid Build Coastguard Worker match_eclipses = [] 1000*c2e18aaaSAndroid Build Coastguard Worker for path in ls_output: 1001*c2e18aaaSAndroid Build Coastguard Worker if os.access(path, os.X_OK): 1002*c2e18aaaSAndroid Build Coastguard Worker match_eclipses.append(path) 1003*c2e18aaaSAndroid Build Coastguard Worker if match_eclipses: 1004*c2e18aaaSAndroid Build Coastguard Worker match_eclipses = sorted(match_eclipses) 1005*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Result for checking %s after sort: %s.', 1006*c2e18aaaSAndroid Build Coastguard Worker self._ide_name, match_eclipses[0]) 1007*c2e18aaaSAndroid Build Coastguard Worker return match_eclipses[0] 1008*c2e18aaaSAndroid Build Coastguard Worker return None 1009*c2e18aaaSAndroid Build Coastguard Worker 1010*c2e18aaaSAndroid Build Coastguard Worker def _get_ide_cmd(self): 1011*c2e18aaaSAndroid Build Coastguard Worker """Compose launch IDE command to run a new process and redirect output. 1012*c2e18aaaSAndroid Build Coastguard Worker 1013*c2e18aaaSAndroid Build Coastguard Worker AIDEGen will create a default workspace 1014*c2e18aaaSAndroid Build Coastguard Worker ~/Documents/AIDEGen_Eclipse_workspace for users if they agree to do 1015*c2e18aaaSAndroid Build Coastguard Worker that. Also, we could not import the default project through the command 1016*c2e18aaaSAndroid Build Coastguard Worker line so remove the project path argument. 1017*c2e18aaaSAndroid Build Coastguard Worker 1018*c2e18aaaSAndroid Build Coastguard Worker Returns: 1019*c2e18aaaSAndroid Build Coastguard Worker A string of launch IDE command. 1020*c2e18aaaSAndroid Build Coastguard Worker """ 1021*c2e18aaaSAndroid Build Coastguard Worker if (os.path.exists(os.path.expanduser(constant.ECLIPSE_WS)) 1022*c2e18aaaSAndroid Build Coastguard Worker or str(input(_ALERT_CREATE_WS)).lower() == 'y'): 1023*c2e18aaaSAndroid Build Coastguard Worker self.cmd.extend(['-data', constant.ECLIPSE_WS]) 1024*c2e18aaaSAndroid Build Coastguard Worker self.cmd.extend([constant.IGNORE_STD_OUT_ERR_CMD, '&']) 1025*c2e18aaaSAndroid Build Coastguard Worker return ' '.join(self.cmd) 1026*c2e18aaaSAndroid Build Coastguard Worker 1027*c2e18aaaSAndroid Build Coastguard Worker def apply_optional_config(self): 1028*c2e18aaaSAndroid Build Coastguard Worker """Override to do nothing.""" 1029*c2e18aaaSAndroid Build Coastguard Worker 1030*c2e18aaaSAndroid Build Coastguard Worker def _get_config_root_paths(self): 1031*c2e18aaaSAndroid Build Coastguard Worker """Override to do nothing.""" 1032*c2e18aaaSAndroid Build Coastguard Worker 1033*c2e18aaaSAndroid Build Coastguard Worker 1034*c2e18aaaSAndroid Build Coastguard Workerclass IdeLinuxEclipse(IdeEclipse): 1035*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of Eclipse launching utilities for OS Linux. 1036*c2e18aaaSAndroid Build Coastguard Worker 1037*c2e18aaaSAndroid Build Coastguard Worker For example: 1038*c2e18aaaSAndroid Build Coastguard Worker 1. Check if Eclipse is installed. 1039*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an Eclipse. 1040*c2e18aaaSAndroid Build Coastguard Worker """ 1041*c2e18aaaSAndroid Build Coastguard Worker 1042*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 1043*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 1044*c2e18aaaSAndroid Build Coastguard Worker self._bin_folders = ['/opt/eclipse*', '/usr/bin/'] 1045*c2e18aaaSAndroid Build Coastguard Worker self._bin_paths = self._get_possible_bin_paths() 1046*c2e18aaaSAndroid Build Coastguard Worker self._init_installed_path(installed_path) 1047*c2e18aaaSAndroid Build Coastguard Worker self.cmd = [constant.NOHUP, self._installed_path.replace(' ', r'\ ')] 1048*c2e18aaaSAndroid Build Coastguard Worker 1049*c2e18aaaSAndroid Build Coastguard Worker 1050*c2e18aaaSAndroid Build Coastguard Workerclass IdeMacEclipse(IdeEclipse): 1051*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of Eclipse launching utilities for OS Mac. 1052*c2e18aaaSAndroid Build Coastguard Worker 1053*c2e18aaaSAndroid Build Coastguard Worker For example: 1054*c2e18aaaSAndroid Build Coastguard Worker 1. Check if Eclipse is installed. 1055*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an Eclipse. 1056*c2e18aaaSAndroid Build Coastguard Worker """ 1057*c2e18aaaSAndroid Build Coastguard Worker 1058*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 1059*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 1060*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name = 'eclipse' 1061*c2e18aaaSAndroid Build Coastguard Worker self._bin_folders = [os.path.expanduser('~/eclipse/**')] 1062*c2e18aaaSAndroid Build Coastguard Worker self._bin_paths = self._get_possible_bin_paths() 1063*c2e18aaaSAndroid Build Coastguard Worker self._init_installed_path(installed_path) 1064*c2e18aaaSAndroid Build Coastguard Worker self.cmd = [self._installed_path.replace(' ', r'\ ')] 1065*c2e18aaaSAndroid Build Coastguard Worker 1066*c2e18aaaSAndroid Build Coastguard Worker 1067*c2e18aaaSAndroid Build Coastguard Workerclass IdeCLion(IdeBase): 1068*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of CLion launching utilities. 1069*c2e18aaaSAndroid Build Coastguard Worker 1070*c2e18aaaSAndroid Build Coastguard Worker For example: 1071*c2e18aaaSAndroid Build Coastguard Worker 1. Check if CLion is installed. 1072*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an CLion. 1073*c2e18aaaSAndroid Build Coastguard Worker """ 1074*c2e18aaaSAndroid Build Coastguard Worker 1075*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 1076*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 1077*c2e18aaaSAndroid Build Coastguard Worker self._ide_name = constant.IDE_CLION 1078*c2e18aaaSAndroid Build Coastguard Worker 1079*c2e18aaaSAndroid Build Coastguard Worker def apply_optional_config(self): 1080*c2e18aaaSAndroid Build Coastguard Worker """Override to do nothing.""" 1081*c2e18aaaSAndroid Build Coastguard Worker 1082*c2e18aaaSAndroid Build Coastguard Worker def _get_config_root_paths(self): 1083*c2e18aaaSAndroid Build Coastguard Worker """Override to do nothing.""" 1084*c2e18aaaSAndroid Build Coastguard Worker 1085*c2e18aaaSAndroid Build Coastguard Worker 1086*c2e18aaaSAndroid Build Coastguard Workerclass IdeLinuxCLion(IdeCLion): 1087*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of CLion launching utilities for OS Linux. 1088*c2e18aaaSAndroid Build Coastguard Worker 1089*c2e18aaaSAndroid Build Coastguard Worker For example: 1090*c2e18aaaSAndroid Build Coastguard Worker 1. Check if CLion is installed. 1091*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an CLion. 1092*c2e18aaaSAndroid Build Coastguard Worker """ 1093*c2e18aaaSAndroid Build Coastguard Worker 1094*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 1095*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 1096*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name = 'clion.sh' 1097*c2e18aaaSAndroid Build Coastguard Worker # TODO(b/141288011): Handle /opt/clion-*/bin to let users choose a 1098*c2e18aaaSAndroid Build Coastguard Worker # preferred version of CLion in the future. 1099*c2e18aaaSAndroid Build Coastguard Worker self._bin_folders = ['/opt/clion-stable/bin'] 1100*c2e18aaaSAndroid Build Coastguard Worker self._bin_paths = self._get_possible_bin_paths() 1101*c2e18aaaSAndroid Build Coastguard Worker self._init_installed_path(installed_path) 1102*c2e18aaaSAndroid Build Coastguard Worker 1103*c2e18aaaSAndroid Build Coastguard Worker 1104*c2e18aaaSAndroid Build Coastguard Workerclass IdeMacCLion(IdeCLion): 1105*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of Android Studio launching utilities for OS Mac. 1106*c2e18aaaSAndroid Build Coastguard Worker 1107*c2e18aaaSAndroid Build Coastguard Worker For example: 1108*c2e18aaaSAndroid Build Coastguard Worker 1. Check if Android Studio is installed. 1109*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an Android Studio. 1110*c2e18aaaSAndroid Build Coastguard Worker """ 1111*c2e18aaaSAndroid Build Coastguard Worker 1112*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 1113*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 1114*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name = 'clion' 1115*c2e18aaaSAndroid Build Coastguard Worker self._bin_folders = ['/Applications/CLion.app/Contents/MacOS/CLion'] 1116*c2e18aaaSAndroid Build Coastguard Worker self._bin_paths = self._get_possible_bin_paths() 1117*c2e18aaaSAndroid Build Coastguard Worker self._init_installed_path(installed_path) 1118*c2e18aaaSAndroid Build Coastguard Worker 1119*c2e18aaaSAndroid Build Coastguard Worker 1120*c2e18aaaSAndroid Build Coastguard Workerclass IdeVSCode(IdeBase): 1121*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of VSCode launching utilities. 1122*c2e18aaaSAndroid Build Coastguard Worker 1123*c2e18aaaSAndroid Build Coastguard Worker For example: 1124*c2e18aaaSAndroid Build Coastguard Worker 1. Check if VSCode is installed. 1125*c2e18aaaSAndroid Build Coastguard Worker 2. Launch an VSCode. 1126*c2e18aaaSAndroid Build Coastguard Worker """ 1127*c2e18aaaSAndroid Build Coastguard Worker 1128*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 1129*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 1130*c2e18aaaSAndroid Build Coastguard Worker self._ide_name = constant.IDE_VSCODE 1131*c2e18aaaSAndroid Build Coastguard Worker 1132*c2e18aaaSAndroid Build Coastguard Worker def apply_optional_config(self): 1133*c2e18aaaSAndroid Build Coastguard Worker """Override to do nothing.""" 1134*c2e18aaaSAndroid Build Coastguard Worker 1135*c2e18aaaSAndroid Build Coastguard Worker def _get_config_root_paths(self): 1136*c2e18aaaSAndroid Build Coastguard Worker """Override to do nothing.""" 1137*c2e18aaaSAndroid Build Coastguard Worker 1138*c2e18aaaSAndroid Build Coastguard Worker 1139*c2e18aaaSAndroid Build Coastguard Workerclass IdeLinuxVSCode(IdeVSCode): 1140*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of VSCode launching utilities for OS Linux.""" 1141*c2e18aaaSAndroid Build Coastguard Worker 1142*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 1143*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 1144*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name = 'code' 1145*c2e18aaaSAndroid Build Coastguard Worker self._bin_folders = ['/usr/bin'] 1146*c2e18aaaSAndroid Build Coastguard Worker self._bin_paths = self._get_possible_bin_paths() 1147*c2e18aaaSAndroid Build Coastguard Worker self._init_installed_path(installed_path) 1148*c2e18aaaSAndroid Build Coastguard Worker 1149*c2e18aaaSAndroid Build Coastguard Worker 1150*c2e18aaaSAndroid Build Coastguard Workerclass IdeMacVSCode(IdeVSCode): 1151*c2e18aaaSAndroid Build Coastguard Worker """Class offers a set of VSCode launching utilities for OS Mac.""" 1152*c2e18aaaSAndroid Build Coastguard Worker 1153*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, installed_path=None, config_reset=False): 1154*c2e18aaaSAndroid Build Coastguard Worker super().__init__(installed_path, config_reset) 1155*c2e18aaaSAndroid Build Coastguard Worker self._bin_file_name = 'code' 1156*c2e18aaaSAndroid Build Coastguard Worker self._bin_folders = ['/usr/local/bin'] 1157*c2e18aaaSAndroid Build Coastguard Worker self._bin_paths = self._get_possible_bin_paths() 1158*c2e18aaaSAndroid Build Coastguard Worker self._init_installed_path(installed_path) 1159*c2e18aaaSAndroid Build Coastguard Worker 1160*c2e18aaaSAndroid Build Coastguard Worker 1161*c2e18aaaSAndroid Build Coastguard Workerdef get_ide_util_instance(ide='j'): 1162*c2e18aaaSAndroid Build Coastguard Worker """Get an IdeUtil class instance for launching IDE. 1163*c2e18aaaSAndroid Build Coastguard Worker 1164*c2e18aaaSAndroid Build Coastguard Worker Args: 1165*c2e18aaaSAndroid Build Coastguard Worker ide: A key character of IDE to be launched. Default ide='j' is to 1166*c2e18aaaSAndroid Build Coastguard Worker launch IntelliJ. 1167*c2e18aaaSAndroid Build Coastguard Worker 1168*c2e18aaaSAndroid Build Coastguard Worker Returns: 1169*c2e18aaaSAndroid Build Coastguard Worker An IdeUtil class instance. 1170*c2e18aaaSAndroid Build Coastguard Worker """ 1171*c2e18aaaSAndroid Build Coastguard Worker conf = project_config.ProjectConfig.get_instance() 1172*c2e18aaaSAndroid Build Coastguard Worker if not conf.is_launch_ide: 1173*c2e18aaaSAndroid Build Coastguard Worker return None 1174*c2e18aaaSAndroid Build Coastguard Worker is_mac = (android_dev_os.AndroidDevOS.MAC == android_dev_os.AndroidDevOS. 1175*c2e18aaaSAndroid Build Coastguard Worker get_os_type()) 1176*c2e18aaaSAndroid Build Coastguard Worker tool = IdeUtil(conf.ide_installed_path, ide, conf.config_reset, is_mac) 1177*c2e18aaaSAndroid Build Coastguard Worker if not tool.is_ide_installed(): 1178*c2e18aaaSAndroid Build Coastguard Worker ipath = conf.ide_installed_path or tool.get_default_path() 1179*c2e18aaaSAndroid Build Coastguard Worker err = _NO_LAUNCH_IDE_CMD.format(constant.IDE_NAME_DICT[ide], ipath) 1180*c2e18aaaSAndroid Build Coastguard Worker logging.error(err) 1181*c2e18aaaSAndroid Build Coastguard Worker stack_trace = common_util.remove_user_home_path(err) 1182*c2e18aaaSAndroid Build Coastguard Worker logs = '%s exists? %s' % (common_util.remove_user_home_path(ipath), 1183*c2e18aaaSAndroid Build Coastguard Worker os.path.exists(ipath)) 1184*c2e18aaaSAndroid Build Coastguard Worker aidegen_metrics.ends_asuite_metrics(constant.IDE_LAUNCH_FAILURE, 1185*c2e18aaaSAndroid Build Coastguard Worker stack_trace, 1186*c2e18aaaSAndroid Build Coastguard Worker logs) 1187*c2e18aaaSAndroid Build Coastguard Worker raise errors.IDENotExistError(err) 1188*c2e18aaaSAndroid Build Coastguard Worker return tool 1189*c2e18aaaSAndroid Build Coastguard Worker 1190*c2e18aaaSAndroid Build Coastguard Worker 1191*c2e18aaaSAndroid Build Coastguard Workerdef _get_ide(installed_path=None, ide='j', config_reset=False, is_mac=False): 1192*c2e18aaaSAndroid Build Coastguard Worker """Get IDE to be launched according to the ide input and OS type. 1193*c2e18aaaSAndroid Build Coastguard Worker 1194*c2e18aaaSAndroid Build Coastguard Worker Args: 1195*c2e18aaaSAndroid Build Coastguard Worker installed_path: The IDE installed path to be checked. 1196*c2e18aaaSAndroid Build Coastguard Worker ide: A key character of IDE to be launched. Default ide='j' is to 1197*c2e18aaaSAndroid Build Coastguard Worker launch IntelliJ. 1198*c2e18aaaSAndroid Build Coastguard Worker config_reset: A boolean, if true reset configuration data. 1199*c2e18aaaSAndroid Build Coastguard Worker 1200*c2e18aaaSAndroid Build Coastguard Worker Returns: 1201*c2e18aaaSAndroid Build Coastguard Worker A corresponding IDE instance. 1202*c2e18aaaSAndroid Build Coastguard Worker """ 1203*c2e18aaaSAndroid Build Coastguard Worker if is_mac: 1204*c2e18aaaSAndroid Build Coastguard Worker return _get_mac_ide(installed_path, ide, config_reset) 1205*c2e18aaaSAndroid Build Coastguard Worker return _get_linux_ide(installed_path, ide, config_reset) 1206*c2e18aaaSAndroid Build Coastguard Worker 1207*c2e18aaaSAndroid Build Coastguard Worker 1208*c2e18aaaSAndroid Build Coastguard Workerdef _get_mac_ide(installed_path=None, ide='j', config_reset=False): 1209*c2e18aaaSAndroid Build Coastguard Worker """Get IDE to be launched according to the ide input for OS Mac. 1210*c2e18aaaSAndroid Build Coastguard Worker 1211*c2e18aaaSAndroid Build Coastguard Worker Args: 1212*c2e18aaaSAndroid Build Coastguard Worker installed_path: The IDE installed path to be checked. 1213*c2e18aaaSAndroid Build Coastguard Worker ide: A key character of IDE to be launched. Default ide='j' is to 1214*c2e18aaaSAndroid Build Coastguard Worker launch IntelliJ. 1215*c2e18aaaSAndroid Build Coastguard Worker config_reset: A boolean, if true reset configuration data. 1216*c2e18aaaSAndroid Build Coastguard Worker 1217*c2e18aaaSAndroid Build Coastguard Worker Returns: 1218*c2e18aaaSAndroid Build Coastguard Worker A corresponding IDE instance. 1219*c2e18aaaSAndroid Build Coastguard Worker """ 1220*c2e18aaaSAndroid Build Coastguard Worker if ide == 'e': 1221*c2e18aaaSAndroid Build Coastguard Worker return IdeMacEclipse(installed_path, config_reset) 1222*c2e18aaaSAndroid Build Coastguard Worker if ide == 's': 1223*c2e18aaaSAndroid Build Coastguard Worker return IdeMacStudio(installed_path, config_reset) 1224*c2e18aaaSAndroid Build Coastguard Worker if ide == 'c': 1225*c2e18aaaSAndroid Build Coastguard Worker return IdeMacCLion(installed_path, config_reset) 1226*c2e18aaaSAndroid Build Coastguard Worker if ide == 'v': 1227*c2e18aaaSAndroid Build Coastguard Worker return IdeMacVSCode(installed_path, config_reset) 1228*c2e18aaaSAndroid Build Coastguard Worker return IdeMacIntelliJ(installed_path, config_reset) 1229*c2e18aaaSAndroid Build Coastguard Worker 1230*c2e18aaaSAndroid Build Coastguard Worker 1231*c2e18aaaSAndroid Build Coastguard Workerdef _get_linux_ide(installed_path=None, ide='j', config_reset=False): 1232*c2e18aaaSAndroid Build Coastguard Worker """Get IDE to be launched according to the ide input for OS Linux. 1233*c2e18aaaSAndroid Build Coastguard Worker 1234*c2e18aaaSAndroid Build Coastguard Worker Args: 1235*c2e18aaaSAndroid Build Coastguard Worker installed_path: The IDE installed path to be checked. 1236*c2e18aaaSAndroid Build Coastguard Worker ide: A key character of IDE to be launched. Default ide='j' is to 1237*c2e18aaaSAndroid Build Coastguard Worker launch IntelliJ. 1238*c2e18aaaSAndroid Build Coastguard Worker config_reset: A boolean, if true reset configuration data. 1239*c2e18aaaSAndroid Build Coastguard Worker 1240*c2e18aaaSAndroid Build Coastguard Worker Returns: 1241*c2e18aaaSAndroid Build Coastguard Worker A corresponding IDE instance. 1242*c2e18aaaSAndroid Build Coastguard Worker """ 1243*c2e18aaaSAndroid Build Coastguard Worker if ide == 'e': 1244*c2e18aaaSAndroid Build Coastguard Worker return IdeLinuxEclipse(installed_path, config_reset) 1245*c2e18aaaSAndroid Build Coastguard Worker if ide == 's': 1246*c2e18aaaSAndroid Build Coastguard Worker return IdeLinuxStudio(installed_path, config_reset) 1247*c2e18aaaSAndroid Build Coastguard Worker if ide == 'c': 1248*c2e18aaaSAndroid Build Coastguard Worker return IdeLinuxCLion(installed_path, config_reset) 1249*c2e18aaaSAndroid Build Coastguard Worker if ide == 'v': 1250*c2e18aaaSAndroid Build Coastguard Worker return IdeLinuxVSCode(installed_path, config_reset) 1251*c2e18aaaSAndroid Build Coastguard Worker return IdeLinuxIntelliJ(installed_path, config_reset) 1252