Merge "AIDEGen: Write the link resources info into .project file."
diff --git a/aidegen/lib/eclipse_project_file_gen.py b/aidegen/lib/eclipse_project_file_gen.py
new file mode 100644
index 0000000..7c6efa4
--- /dev/null
+++ b/aidegen/lib/eclipse_project_file_gen.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""It is an AIDEGen sub task: generate the .project file for Eclipse."""
+
+import os
+
+from aidegen import constant
+from aidegen.lib import common_util
+
+
+class EclipseConf():
+ """Class to generate project file under the module path for Eclipse.
+
+ Attributes:
+ module_abspath: The absolute path of the target project.
+ module_name: The name of the target project.
+ jar_module_paths: A dict records a mapping of jar file and module path.
+ r_java_paths: A list contains the relative folder paths of the R.java
+ files.
+ project_file: The absolutely path of .project file.
+ template_project_content: A string of a template project_file content.
+ project_content: A string ready to be written into project_file.
+ """
+ # Constants of .project file
+ _TEMPLATE_PROJECT_FILE = os.path.join(constant.AIDEGEN_ROOT_PATH,
+ 'templates/eclipse/project.xml')
+ _PROJECT_LINK = (' <link><name>{}</name><type>2</type>'
+ '<location>{}</location></link>\n')
+ _PROJECT_FILENAME = '.project'
+
+ def __init__(self, project):
+ """Initialize class.
+
+ Args:
+ project: A ProjectInfo instance.
+ """
+ self.module_abspath = project.project_absolute_path
+ self.module_name = project.module_name
+ self.jar_module_paths = project.source_path['jar_module_path']
+ self.r_java_paths = list(project.source_path['r_java_path'])
+ # Related value for generating .project.
+ self.project_file = os.path.join(self.module_abspath,
+ self._PROJECT_FILENAME)
+ self.template_project_content = common_util.read_file_content(
+ self._TEMPLATE_PROJECT_FILE)
+ self.project_content = ''
+
+ def _gen_r_link(self):
+ """Generate the link resources of the R paths.
+
+ E.g.
+ <link>
+ <name>dependencies/out/target/common/R</name>
+ <type>2</type>
+ <location>{ANDROID_ROOT_PATH}/out/target/common/R</location>
+ </link>
+
+ Returns: A set contains R paths link resources strings.
+ """
+ return {self._gen_link(rpath) for rpath in self.r_java_paths}
+
+ def _gen_src_links(self, relpaths):
+ """Generate the link resources from relpaths.
+
+ Args:
+ relpaths: A list of module paths which are relative to
+ ANDROID_BUILD_TOP.
+ e.g. ['relpath/to/module1', 'relpath/to/module2', ...]
+
+ Returns: A set includes all unique link resources.
+ """
+ return {self._gen_link(relpath) for relpath in relpaths}
+
+ @classmethod
+ def _gen_link(cls, relpath):
+ """Generate a link resource from a relative path.
+
+ E.g.
+ <link>
+ <name>dependencies/path/to/relpath</name>
+ <type>2</type>
+ <location>/absolute/path/to/relpath</location>
+ </link>
+
+ Args:
+ relpath: A string of a relative path to Android_BUILD_TOP.
+
+ Returns: A string of link resource.
+ """
+ alias_name = os.path.join(constant.KEY_DEP, relpath)
+ abs_path = os.path.join(constant.ANDROID_ROOT_PATH, relpath)
+ return cls._PROJECT_LINK.format(alias_name, abs_path)
+
+ def _create_project_content(self):
+ """Create the project file .project under the module."""
+ # links is a set to save unique link resources.
+ links = self._gen_src_links(self.jar_module_paths.values())
+ links.update(self._gen_r_link())
+ self.project_content = self.template_project_content.format(
+ PROJECTNAME=self.module_name,
+ LINKEDRESOURCES=''.join(sorted(list(links))))
+
+ def generate_project_file(self):
+ """Generate .project file of the target module."""
+ self._create_project_content()
+ common_util.file_generate(self.project_file, self.project_content)
diff --git a/aidegen/lib/eclipse_project_file_gen_unittest.py b/aidegen/lib/eclipse_project_file_gen_unittest.py
new file mode 100644
index 0000000..e63d89b
--- /dev/null
+++ b/aidegen/lib/eclipse_project_file_gen_unittest.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Unittests for generate project file of Eclipse."""
+
+import os
+import unittest
+from unittest import mock
+
+from aidegen import constant
+from aidegen import unittest_constants
+from aidegen.lib.common_util import read_file_content
+from aidegen.lib.eclipse_project_file_gen import EclipseConf
+
+
+# pylint: disable=protected-access
+class EclipseConfUnittests(unittest.TestCase):
+ """Unit tests for generate_project_file.py"""
+ _ROOT_PATH = '/android/root'
+ _PROJECT_RELPATH = 'module/path'
+ _PROJECT_ABSPATH = os.path.join(_ROOT_PATH, _PROJECT_RELPATH)
+ _PROJECT_NAME = 'test'
+ _LINK_TEMPLATE = (' <link><name>%s</name><type>2</type>'
+ '<location>%s</location></link>\n')
+ _TEST_DATA_PATH = unittest_constants.TEST_DATA_PATH
+ _PROJECT_SAMPLE = os.path.join(_TEST_DATA_PATH, 'eclipse.project')
+
+ def test_gen_link(self):
+ """Test get_link return a correct link resource config."""
+ constant.ANDROID_ROOT_PATH = self._ROOT_PATH
+ name = os.path.join(constant.KEY_DEP, self._PROJECT_RELPATH)
+ expected_link = self._LINK_TEMPLATE % (name, self._PROJECT_ABSPATH)
+ generated_link = EclipseConf._gen_link(self._PROJECT_RELPATH)
+ self.assertEqual(generated_link, expected_link)
+
+ @mock.patch('aidegen.lib.project_info.ProjectInfo')
+ def test_create_project_content(self, mock_project_info):
+ """Test _create_project_content."""
+ constant.ANDROID_ROOT_PATH = self._ROOT_PATH
+ mock_project_info.project_absolute_path = self._PROJECT_ABSPATH
+ mock_project_info.module_name = self._PROJECT_NAME
+ mock_project_info.source_path = {
+ 'jar_module_path': {
+ '': self._PROJECT_RELPATH
+ },
+ 'r_java_path': {constant.CENTRAL_R_PATH}
+ }
+ expected_content = read_file_content(self._PROJECT_SAMPLE)
+ eclipse_config = EclipseConf(mock_project_info)
+ eclipse_config._create_project_content()
+ generated_content = eclipse_config.project_content
+ self.assertEqual(generated_content, expected_content)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/aidegen/lib/project_file_gen.py b/aidegen/lib/project_file_gen.py
index 108da52..5cadfbc 100644
--- a/aidegen/lib/project_file_gen.py
+++ b/aidegen/lib/project_file_gen.py
@@ -30,6 +30,7 @@
from aidegen import constant
from aidegen.lib import common_util
+from aidegen.lib.eclipse_project_file_gen import EclipseConf
# FACET_SECTION is a part of iml, which defines the framework of the project.
_FACET_SECTION = '''\
@@ -90,9 +91,6 @@
_ECLIP_EXTENSION = '.classpath'
_ECLIP_SRC_TOKEN = '@SRC@'
_ECLIP_LIB_TOKEN = '@LIB@'
-_ECLIP_PROJECT_PATH = os.path.join(_ROOT_DIR, 'templates/eclipse/project.xml')
-_ECLIP_PROJECT_NAME_TOKEN = '@PROJECTNAME@'
-_ECLIP_PROJECT_EXTENSION = '.project'
# b/121256503: Prevent duplicated iml names from breaking IDEA.
# Use a map to cache in-using(already used) iml project file names.
@@ -200,18 +198,19 @@
def _generate_eclipse_project_file(project_info):
- """Generates Eclipse project file.
+ """Generates Eclipse project files.
Args:
project_info: ProjectInfo instance.
"""
- module_path = project_info.project_absolute_path
- module_name = get_unique_iml_name(module_path)
- _generate_eclipse_project(module_name, module_path)
+ eclipse_configure = EclipseConf(project_info)
+ eclipse_configure.generate_project_file()
source_dict = dict.fromkeys(
list(project_info.source_path['source_folder_path']), False)
source_dict.update(
dict.fromkeys(list(project_info.source_path['test_folder_path']), True))
+ source_dict.update(
+ dict.fromkeys(list(project_info.source_path['r_java_path']), True))
project_info.iml_path = _generate_classpath(
project_info.project_absolute_path, list(sorted(source_dict)),
list(project_info.source_path['jar_path']))
@@ -514,19 +513,6 @@
return classpath_path
-def _generate_eclipse_project(project_name, module_path):
- """Generate .project file of Eclipse.
-
- Args:
- project_name: A string of the project name.
- module_path: Absolute path of the module.
- """
- template = common_util.read_file_content(_ECLIP_PROJECT_PATH)
- template = template.replace(_ECLIP_PROJECT_NAME_TOKEN, project_name)
- eclipse_project = os.path.join(module_path, _ECLIP_PROJECT_EXTENSION)
- common_util.file_generate(eclipse_project, template)
-
-
def _get_dependencies_name(module_name):
"""Get module's dependencies iml name which will be written in module.xml.
diff --git a/aidegen/lib/project_info.py b/aidegen/lib/project_info.py
index 8753519..9c97800 100644
--- a/aidegen/lib/project_info.py
+++ b/aidegen/lib/project_info.py
@@ -72,6 +72,8 @@
jar_path: A set contains the jar file paths.
jar_module_path: A dictionary contains the jar file and
the module's path mapping.
+ r_java_path: A set contains the relative path to the
+ R.java files.
"""
modules_info = {}
@@ -88,7 +90,7 @@
the given target has a higher priority than project path.
"""
rel_path, abs_path = get_related_paths(module_info, target)
- target = self._get_target_name(target, abs_path)
+ self.module_name = self._get_target_name(target, abs_path)
self.project_module_names = set(module_info.get_module_names(rel_path))
self.project_relative_path = rel_path
self.project_absolute_path = abs_path
@@ -97,7 +99,7 @@
self._init_source_path()
self.dep_modules = self.get_dep_modules()
self._filter_out_modules()
- self._display_convert_make_files_message(module_info, target)
+ self._display_convert_make_files_message(module_info, self.module_name)
def _set_default_modues(self):
"""Append default hard-code modules, source paths and jar files.
@@ -120,7 +122,8 @@
'source_folder_path': set(),
'test_folder_path': set(),
'jar_path': set(),
- 'jar_module_path': dict()
+ 'jar_module_path': dict(),
+ 'r_java_path': set()
}
def _display_convert_make_files_message(self, module_info, target):
diff --git a/aidegen/lib/source_locator.py b/aidegen/lib/source_locator.py
index 755f898..3064a1e 100644
--- a/aidegen/lib/source_locator.py
+++ b/aidegen/lib/source_locator.py
@@ -128,6 +128,7 @@
module.locate_sources_path()
dependencies['source_folder_path'].update(module.src_dirs)
dependencies['test_folder_path'].update(module.test_dirs)
+ dependencies['r_java_path'].update(module.r_java_paths)
_append_jars_as_dependencies(dependencies, module)
if module.build_targets:
rebuild_targets |= module.build_targets
@@ -253,6 +254,7 @@
self.src_dirs = set()
self.test_dirs = set()
self.jar_files = set()
+ self.r_java_paths = set()
self.referenced_by_jar = False
self.build_targets = set()
self.missing_jars = set()
@@ -298,9 +300,9 @@
self.build_targets.add(_AAPT2_SRCJAR % self.module_name)
# In case the central R folder been deleted, uses the intermediate
# folder as the dependency to R.java.
- self.src_dirs.add(r_src_dir)
+ self.r_java_paths.add(r_src_dir)
# Add the central R as a default source folder.
- self.src_dirs.add(constant.CENTRAL_R_PATH)
+ self.r_java_paths.add(constant.CENTRAL_R_PATH)
def _init_module_path(self):
"""Inintialize self.module_path."""
diff --git a/aidegen/lib/source_locator_unittest.py b/aidegen/lib/source_locator_unittest.py
index 97fd8c9..f1823a3 100644
--- a/aidegen/lib/source_locator_unittest.py
+++ b/aidegen/lib/source_locator_unittest.py
@@ -150,10 +150,10 @@
"""Test locate_sources_path handling."""
# Test collect source path.
module_info = dict(_MODULE_INFO)
- result_src_list = set(['packages/apps/test/src/main/java',
- constant.CENTRAL_R_PATH])
+ result_src_list = set(['packages/apps/test/src/main/java'])
result_test_list = set(['packages/apps/test/tests'])
result_jar_list = set()
+ result_r_path = set([constant.CENTRAL_R_PATH])
constant.ANDROID_ROOT_PATH = uc.TEST_DATA_PATH
module_data = source_locator.ModuleData(_MODULE_NAME, module_info,
_MODULE_DEPTH)
@@ -161,6 +161,7 @@
self.assertEqual(module_data.src_dirs, result_src_list)
self.assertEqual(module_data.test_dirs, result_test_list)
self.assertEqual(module_data.jar_files, result_jar_list)
+ self.assertEqual(module_data.r_java_paths, result_r_path)
# Test find jar files.
jar_file = ('out/soong/.intermediates/packages/apps/test/test/'
@@ -219,32 +220,34 @@
depth_by_source = 2
module_info = dict(_MODULE_INFO)
module_info['depth'] = 2
- result_src_list = set(['packages/apps/test/src/main/java',
- constant.CENTRAL_R_PATH])
+ result_src_list = set(['packages/apps/test/src/main/java'])
result_test_list = set(['packages/apps/test/tests'])
result_jar_list = set()
+ result_r_path = set([constant.CENTRAL_R_PATH])
module_data = source_locator.ModuleData(_MODULE_NAME, module_info,
depth_by_source)
module_data.locate_sources_path()
self.assertEqual(module_data.src_dirs, result_src_list)
self.assertEqual(module_data.test_dirs, result_test_list)
self.assertEqual(module_data.jar_files, result_jar_list)
+ self.assertEqual(module_data.r_java_paths, result_r_path)
# Test find source folder when module's depth smaller than the --depth
# value from command line.
depth_by_source = 3
module_info = dict(_MODULE_INFO)
module_info['depth'] = 2
- result_src_list = set(['packages/apps/test/src/main/java',
- constant.CENTRAL_R_PATH])
+ result_src_list = set(['packages/apps/test/src/main/java'])
result_test_list = set(['packages/apps/test/tests'])
result_jar_list = set()
+ result_r_path = set([constant.CENTRAL_R_PATH])
module_data = source_locator.ModuleData(_MODULE_NAME, module_info,
depth_by_source)
module_data.locate_sources_path()
self.assertEqual(module_data.src_dirs, result_src_list)
self.assertEqual(module_data.test_dirs, result_test_list)
self.assertEqual(module_data.jar_files, result_jar_list)
+ self.assertEqual(module_data.r_java_paths, result_r_path)
@mock.patch('aidegen.lib.project_info.ProjectInfo')
@mock.patch('atest.atest_utils.build')
@@ -267,6 +270,7 @@
'test_folder_path': set(),
'jar_path': set(),
'jar_module_path': dict(),
+ 'r_java_path': set(),
}
# Show warning when the jar not exists after build the module.
result_jar = set()
@@ -290,13 +294,15 @@
shutil.rmtree(test_root_path)
# Test collects source and test folders.
- result_source = set(['packages/apps/test/src/main/java',
- constant.CENTRAL_R_PATH])
+ result_source = set(['packages/apps/test/src/main/java'])
result_test = set(['packages/apps/test/tests'])
+ result_r_path = set([constant.CENTRAL_R_PATH])
self.assertEqual(mock_project_info.source_path['source_folder_path'],
result_source)
self.assertEqual(mock_project_info.source_path['test_folder_path'],
result_test)
+ self.assertEqual(mock_project_info.source_path['r_java_path'],
+ result_r_path)
# Test loading jar from dependencies parameter.
default_jar = os.path.join(_MODULE_PATH, 'test.jar')
diff --git a/aidegen/templates/eclipse/project.xml b/aidegen/templates/eclipse/project.xml
index 2b19250..a41fa48 100644
--- a/aidegen/templates/eclipse/project.xml
+++ b/aidegen/templates/eclipse/project.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
- <name>@PROJECTNAME@</name>
+ <name>{PROJECTNAME}</name>
<comment></comment>
<projects>
</projects>
@@ -14,4 +14,7 @@
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
+ <linkedResources>
+{LINKEDRESOURCES}
+ </linkedResources>
</projectDescription>
diff --git a/aidegen/test_data/eclipse.project b/aidegen/test_data/eclipse.project
new file mode 100644
index 0000000..d5ca893
--- /dev/null
+++ b/aidegen/test_data/eclipse.project
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>test</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+ <linkedResources>
+ <link><name>dependencies/module/path</name><type>2</type><location>/android/root/module/path</location></link>
+ <link><name>dependencies/out/target/common/R</name><type>2</type><location>/android/root/out/target/common/R</location></link>
+
+ </linkedResources>
+</projectDescription>