Merge "AIDEGen: change the default behavior of launching IDE."
diff --git a/aidegen/aidegen_main.py b/aidegen/aidegen_main.py
index f7b1951..2f0e8e4 100644
--- a/aidegen/aidegen_main.py
+++ b/aidegen/aidegen_main.py
@@ -262,31 +262,55 @@
         _launch_ide(ide_util_obj, projects[0].project_absolute_path)
 
 
-def _launch_ide_by_module_contents(args, ide_util_obj, jlist=None, clist=None,
-                                   rlist=None, all_langs=False):
+def _launch_ide_by_module_contents(args, ide_util_obj, language, jlist=None,
+                                   clist=None, rlist=None, all_langs=False):
     """Deals with the suitable IDE launch action.
 
     The rules of AIDEGen launching IDE with languages are:
-      1. aidegen frameworks/base
-         aidegen frameworks/base -l j
-         launch Java projects of frameworks/base in IntelliJ.
-      2. aidegen frameworks/base -i c
-         aidegen frameworks/base -l c
-         launch C/C++ projects of frameworks/base in CLion.
-      3. aidegen frameworks/base -i s
-         launch Java projects of frameworks/base in Android Studio.
-         aidegen frameworks/base -i s -l c
-         launch C/C++ projects of frameworks/base in Android Studio.
-      4. aidegen frameworks/base -i j -l c
-         launch Java projects of frameworks/base in IntelliJ.
-      5. aidegen frameworks/base -i c -l j
-         launch C/C++ projects of frameworks/base in CLion.
-      6. aidegen external/rust/crates/protobuf -l r
-         launch Rust projects of external/rust/crates/protobuf in VS Code.
+      1. If no IDE or language is specific, the priority of the language is:
+         a) Java
+            aidegen frameworks/base
+            launch Java projects of frameworks/base in IntelliJ.
+         b) C/C++
+            aidegen hardware/interfaces/vibrator/aidl/default
+            launch C/C++ project of hardware/interfaces/vibrator/aidl/default
+            in CLion.
+         c) Rust
+            aidegen external/rust/crates/protobuf
+            launch Rust project of external/rust/crates/protobuf in VS Code.
+      2. If the IDE is specific, launch related projects in the IDE.
+         a) aidegen frameworks/base -i j
+            launch Java projects of frameworks/base in IntelliJ.
+            aidegen frameworks/base -i s
+            launch Java projects of frameworks/base in Android Studio.
+            aidegen frameworks/base -i e
+            launch Java projects of frameworks/base in Eclipse.
+         b) aidegen frameworks/base -i c
+            launch C/C++ projects of frameworks/base in CLion.
+         c) aidegen external/rust/crates/protobuf -i v
+            launch Rust project of external/rust/crates/protobuf in VS Code.
+      3. If the launguage is specific, launch relative language projects in the
+         relative IDE.
+         a) aidegen frameworks/base -l j
+            launch Java projects of frameworks/base in IntelliJ.
+         b) aidegen frameworks/base -l c
+            launch C/C++ projects of frameworks/base in CLion.
+         c) aidegen external/rust/crates/protobuf -l r
+            launch Rust projects of external/rust/crates/protobuf in VS Code.
+      4. Both of the IDE and language are specific, launch the IDE with the
+         relative language projects. If the IDE conflicts with the language, the
+         IDE is prior to the language.
+         a) aidegen frameworks/base -i j -l j
+            launch Java projects of frameworks/base in IntelliJ.
+         b) aidegen frameworks/base -i s -l c
+            launch C/C++ projects of frameworks/base in Android Studio.
+         c) aidegen frameworks/base -i c -l j
+            launch C/C++ projects of frameworks/base in CLion.
 
     Args:
         args: A list of system arguments.
         ide_util_obj: An ide_util instance.
+        language: A string of the language to be edited in the IDE.
         jlist: A list of Java build targets.
         clist: A list of C/C++ build targets.
         rlist: A list of Rust build targets.
@@ -296,17 +320,14 @@
         _launch_vscode(ide_util_obj, project_info.ProjectInfo.modules_info,
                        jlist, clist, rlist)
         return
-    if not jlist and not clist:
-        logging.warning('\nThere is neither java nor C/C++ module needs to be'
-                        ' opened')
+    if not (jlist or clist or rlist):
+        print(constant.WARN_MSG.format(
+            common_util.COLORED_INFO('Warning:'), _NO_ANY_PROJECT_EXIST))
         return
-
-    language, _ = common_util.determine_language_ide(
-        args.language[0], args.ide[0])
-    if (jlist and not clist) or (language == constant.JAVA):
+    if language == constant.JAVA:
         _create_and_launch_java_projects(ide_util_obj, jlist)
         return
-    if (clist and not jlist) or (language == constant.C_CPP):
+    if language == constant.C_CPP:
         native_project_info.NativeProjectInfo.generate_projects(clist)
         native_project_file = native_util.generate_clion_projects(clist)
         if native_project_file:
@@ -334,7 +355,6 @@
         root_dir = common_util.get_android_root_dir()
         abs_paths.extend(_get_rust_project_paths(rtargets, root_dir))
     if not (jtargets or ctargets or rtargets):
-        message = _NO_ANY_PROJECT_EXIST
         print(constant.WARN_MSG.format(
             common_util.COLORED_INFO('Warning:'), _NO_ANY_PROJECT_EXIST))
         return
@@ -505,18 +525,20 @@
     config = project_config.ProjectConfig(args)
     config.init_environment()
     targets = config.targets
-    # Called ide_util for pre-check the IDE existence state.
-    ide_util_obj = ide_util.get_ide_util_instance(
-        constant.IDE_DICT[config.ide_name])
     project_info.ProjectInfo.modules_info = module_info.AidegenModuleInfo()
     cc_module_info = native_module_info.NativeModuleInfo()
     jtargets, ctargets, rtargets = native_util.get_java_cc_and_rust_projects(
         project_info.ProjectInfo.modules_info, cc_module_info, targets)
+    config.language, config.ide_name = common_util.determine_language_ide(
+        args.language[0], args.ide[0], jtargets, ctargets, rtargets)
+    # Called ide_util for pre-check the IDE existence state.
+    ide_util_obj = ide_util.get_ide_util_instance(
+        constant.IDE_DICT[config.ide_name])
     all_langs = config.ide_name == constant.IDE_VSCODE
     # Backward compatible strategy, when both java and C/C++ module exist,
     # check the preferred target from the user and launch single one.
-    _launch_ide_by_module_contents(
-        args, ide_util_obj, jtargets, ctargets, rtargets, all_langs)
+    _launch_ide_by_module_contents(args, ide_util_obj, config.language,
+                                   jtargets, ctargets, rtargets, all_langs)
 
 
 if __name__ == '__main__':
diff --git a/aidegen/aidegen_main_unittest.py b/aidegen/aidegen_main_unittest.py
index 63aa593..7c8950c 100644
--- a/aidegen/aidegen_main_unittest.py
+++ b/aidegen/aidegen_main_unittest.py
@@ -222,7 +222,7 @@
         mock_print.return_value = None
 
     @mock.patch.object(project_config.ProjectConfig, 'init_environment')
-    @mock.patch('logging.warning')
+    @mock.patch('builtins.print')
     @mock.patch.object(aidegen_main, '_launch_vscode')
     @mock.patch.object(aidegen_main, '_launch_native_projects')
     @mock.patch.object(native_util, 'generate_clion_projects')
@@ -230,26 +230,27 @@
                        'generate_projects')
     @mock.patch.object(aidegen_main, '_create_and_launch_java_projects')
     def test_launch_ide_by_module_contents(self, mock_j, mock_c_prj, mock_genc,
-                                           mock_c, mock_vs, mock_log,
+                                           mock_c, mock_vs, mock_print,
                                            mock_init):
         """Test _launch_ide_by_module_contents with different conditions."""
         args = aidegen_main._parse_args(['', '-i', 's'])
         mock_init.return_value = None
         self._init_project_config(args)
         ide_obj = 'ide_obj'
-        test_both = False
-        aidegen_main._launch_ide_by_module_contents(args, ide_obj, None,
-                                                    None, None, test_both)
+        test_all = False
+        lang = constant.JAVA
+        aidegen_main._launch_ide_by_module_contents(args, ide_obj, lang, None,
+                                                    None, None, test_all)
         self.assertFalse(mock_vs.called)
-        self.assertTrue(mock_log.called)
+        self.assertTrue(mock_print.called)
         self.assertFalse(mock_j.called)
         self.assertFalse(mock_c_prj.called)
         self.assertFalse(mock_genc.called)
         self.assertFalse(mock_c.called)
 
-        test_both = True
-        aidegen_main._launch_ide_by_module_contents(args, ide_obj, None,
-                                                    None, None, test_both)
+        test_all = True
+        aidegen_main._launch_ide_by_module_contents(args, ide_obj, lang, None,
+                                                    None, None, test_all)
         self.assertTrue(mock_vs.called)
         self.assertFalse(mock_j.called)
         self.assertFalse(mock_genc.called)
@@ -258,7 +259,7 @@
 
         test_j = ['a', 'b', 'c']
         test_c = ['1', '2', '3']
-        aidegen_main._launch_ide_by_module_contents(args, ide_obj, test_j,
+        aidegen_main._launch_ide_by_module_contents(args, ide_obj, lang, test_j,
                                                     test_c)
         self.assertFalse(mock_vs.called)
         self.assertTrue(mock_j.called)
@@ -272,7 +273,8 @@
         args = aidegen_main._parse_args(['', '-l', 'c'])
         mock_init.return_value = None
         self._init_project_config(args)
-        aidegen_main._launch_ide_by_module_contents(args, ide_obj, test_j,
+        lang = constant.C_CPP
+        aidegen_main._launch_ide_by_module_contents(args, ide_obj, lang, test_j,
                                                     test_c)
         self.assertTrue(mock_c_prj.called)
         self.assertFalse(mock_vs.called)
@@ -285,8 +287,8 @@
         mock_genc.reset_mock()
         mock_j.reset_mock()
         test_none = None
-        aidegen_main._launch_ide_by_module_contents(args, ide_obj, test_none,
-                                                    test_c)
+        aidegen_main._launch_ide_by_module_contents(args, ide_obj, lang,
+                                                    test_none, test_c)
         self.assertFalse(mock_vs.called)
         self.assertTrue(mock_genc.called)
         self.assertTrue(mock_c.called)
@@ -296,7 +298,8 @@
         mock_c.reset_mock()
         mock_genc.reset_mock()
         mock_j.reset_mock()
-        aidegen_main._launch_ide_by_module_contents(args, ide_obj, test_j,
+        lang = constant.JAVA
+        aidegen_main._launch_ide_by_module_contents(args, ide_obj, lang, test_j,
                                                     test_none)
         self.assertFalse(mock_vs.called)
         self.assertTrue(mock_j.called)
@@ -309,7 +312,8 @@
         mock_genc.reset_mock()
         mock_c_prj.reset_mock()
         mock_j.reset_mock()
-        aidegen_main._launch_ide_by_module_contents(args, ide_obj, test_j,
+        lang = constant.C_CPP
+        aidegen_main._launch_ide_by_module_contents(args, ide_obj, lang, test_j,
                                                     test_c)
         self.assertFalse(mock_vs.called)
         self.assertFalse(mock_j.called)
@@ -324,7 +328,9 @@
         mock_c_prj.reset_mock()
         mock_j.reset_mock()
         os.environ[constant.AIDEGEN_TEST_MODE] = 'true'
-        aidegen_main._launch_ide_by_module_contents(args, None, test_j, test_c)
+        lang = constant.JAVA
+        aidegen_main._launch_ide_by_module_contents(args, None, lang, test_j,
+                                                    test_c)
         self.assertFalse(mock_vs.called)
         self.assertTrue(mock_j.called)
         self.assertFalse(mock_c.called)
@@ -518,7 +524,7 @@
         self.assertTrue(mock_native.called)
         self.assertTrue(mock_get_project.called)
         mock_launch_ide.assert_called_with(
-            args, ide, config.targets, [], [], True)
+            args, ide, constant.JAVA, config.targets, [], [], True)
 
         mock_config.mock_reset()
         mock_get_ide.mock_reset()
@@ -536,7 +542,7 @@
         self.assertTrue(mock_native.called)
         self.assertTrue(mock_get_project.called)
         mock_launch_ide.assert_called_with(
-            args, ide, config.targets, [], [], False)
+            args, ide, constant.JAVA, config.targets, [], [], False)
 
 
 if __name__ == '__main__':
diff --git a/aidegen/lib/common_util.py b/aidegen/lib/common_util.py
index e7a527c..1d2643a 100644
--- a/aidegen/lib/common_util.py
+++ b/aidegen/lib/common_util.py
@@ -736,16 +736,31 @@
     return None
 
 
-def determine_language_ide(lang, ide):
+def determine_language_ide(lang, ide, jlist=None, clist=None, rlist=None):
     """Determines the language and IDE by the input language and IDE arguments.
 
+    If IDE and language are undefined, the priority of the language is:
+      1. Java
+      2. C/C++
+      3. Rust
+
     Args:
         lang: A character represents the input language.
         ide: A character represents the input IDE.
+        jlist: A list of Android Java projects, the default value is None.
+        clist: A list of Android C/C++ projects, the default value is None.
+        clist: A list of Android Rust projects, the default value is None.
 
     Returns:
         A tuple of the determined language and IDE name strings.
     """
+    if ide == _IDE_UNDEFINED and lang == constant.LANG_UNDEFINED:
+        if jlist:
+            lang = constant.LANG_JAVA
+        elif clist:
+            lang = constant.LANG_CC
+        elif rlist:
+            lang = constant.LANG_RUST
     if lang in (constant.LANG_UNDEFINED, constant.LANG_JAVA):
         if ide == _IDE_UNDEFINED:
             ide = _IDE_INTELLIJ
diff --git a/aidegen/lib/common_util_unittest.py b/aidegen/lib/common_util_unittest.py
index 29e2679..2c40b28 100644
--- a/aidegen/lib/common_util_unittest.py
+++ b/aidegen/lib/common_util_unittest.py
@@ -395,6 +395,15 @@
         lang = 'u'
         self.assertEqual((constant.JAVA, constant.IDE_INTELLIJ),
                          common_util.determine_language_ide(lang, ide))
+        self.assertEqual((constant.JAVA, constant.IDE_INTELLIJ),
+                         common_util.determine_language_ide(
+                             lang, ide, ['some_module']))
+        self.assertEqual((constant.C_CPP, constant.IDE_CLION),
+                         common_util.determine_language_ide(
+                             lang, ide, None, ['some_module']))
+        self.assertEqual((constant.RUST, constant.IDE_VSCODE),
+                         common_util.determine_language_ide(
+                             lang, ide, None, None, ['some_module']))
         lang = 'j'
         self.assertEqual((constant.JAVA, constant.IDE_INTELLIJ),
                          common_util.determine_language_ide(lang, ide))
diff --git a/aidegen/lib/project_config.py b/aidegen/lib/project_config.py
index e3649c7..eaa75d5 100644
--- a/aidegen/lib/project_config.py
+++ b/aidegen/lib/project_config.py
@@ -73,8 +73,8 @@
         Args:
             An argparse.Namespace object holds parsed args.
         """
-        self.language, self.ide_name = common_util.determine_language_ide(
-            args.language[0], args.ide[0])
+        self.language = constant.LANGUAGE_NAME_DICT[args.language[0]]
+        self.ide_name = constant.IDE_NAME_DICT[args.ide[0]]
         self.is_launch_ide = not args.no_launch
         self.depth = args.depth
         self.full_repo = args.android_tree
diff --git a/aidegen/lib/project_config_unittest.py b/aidegen/lib/project_config_unittest.py
index 563b06d..d1533c7 100644
--- a/aidegen/lib/project_config_unittest.py
+++ b/aidegen/lib/project_config_unittest.py
@@ -62,7 +62,7 @@
         """Test __init__ method without launching IDE."""
         args = aidegen_main._parse_args(['a', '-n', '-s'])
         config = project_config.ProjectConfig(args)
-        self.assertEqual(config.ide_name, constant.IDE_INTELLIJ)
+        self.assertEqual(config.ide_name, constant.IDE_UNDEFINED)
         self.assertFalse(config.is_launch_ide)
         self.assertEqual(config.depth, 0)
         self.assertFalse(config.full_repo)
@@ -73,7 +73,7 @@
         self.assertFalse(config.config_reset)
         self.assertEqual(config.exclude_paths, None)
         config_obj = project_config.ProjectConfig.get_instance()
-        self.assertEqual(config_obj.ide_name, constant.IDE_INTELLIJ)
+        self.assertEqual(config_obj.ide_name, constant.IDE_UNDEFINED)
         self.assertFalse(config_obj.is_launch_ide)
         self.assertEqual(config_obj.depth, 0)
         self.assertFalse(config_obj.full_repo)
@@ -88,11 +88,11 @@
         """Test __init__ method with different arguments."""
         args = aidegen_main._parse_args([])
         config = project_config.ProjectConfig(args)
-        self.assertEqual(config.ide_name, constant.IDE_INTELLIJ)
+        self.assertEqual(config.ide_name, constant.IDE_UNDEFINED)
         self.assertEqual(config.targets, [''])
         config_obj = project_config.ProjectConfig.get_instance()
         self.assertEqual(config_obj.targets, [''])
-        self.assertEqual(config_obj.ide_name, constant.IDE_INTELLIJ)
+        self.assertEqual(config_obj.ide_name, constant.IDE_UNDEFINED)
         target = 'tradefed'
         args = aidegen_main._parse_args([target])
         config = project_config.ProjectConfig(args)