def _create_idea_project(self, outdir, module_pool): targets = self.context.targets() blob = self.generate_targets_map(targets) aop_sources_dir = os.path.join(self.get_options().annotation_generated_sources_dir) aop_tests_dir = os.path.join(self.get_options().annotation_generated_test_sources_dir) annotation_processing = IdeaProject.AnnotationProcessing( enabled=self.get_options().annotation_processing_enabled, sources_dir=aop_sources_dir, test_sources_dir=aop_tests_dir, processors=self.get_options().annotation_processor, codegen_processors=self.get_options().internal_codegen_processor, ) return IdeaProject( blob, output_directory=outdir, workdir=self.gen_project_workdir, context=self.context, maven_style=self.get_options().maven_style, exclude_folders=self.get_options().exclude_folders, annotation_processing=annotation_processing, bash=self.bash, java_encoding=self.java_encoding, java_maximum_heap_size=self.java_maximum_heap_size, pants_workdir=self.get_options().pants_workdir, generate_root_module=self.get_options().loose_files, prune_libraries=self.get_options().prune_libraries, module_pool=module_pool, debug_port=self.jvm.get_options().debug_port, provided_module_dependencies=self.get_options().provided_module_dependencies, )
def test_java_language_level(self): blob = { 'jvm_platforms': { 'platforms': { '1.7': { 'source_level': '1.7' }, 'the-best': { 'source_level': '1.8.34._5' }, 'not-the-best': { 'source_level': '1.6.1.3_12' }, } }, 'targets': { 'squarepants/faketarget': { 'platform': 'the-best' }, 'squarepants/shamtarget': { 'platform': 'not-the-best' }, } } project = IdeaProject(blob, '.', '.', None) self.assertEqual( 'JDK_1_8', project._java_language_level( blob['targets']['squarepants/faketarget'])) self.assertEqual( 'JDK_1_6', project._java_language_level( blob['targets']['squarepants/shamtarget']))
def gen_project_name(self): """Computes the name for the generated project, and a sha1 digest of its loaded module names. The project name is computed to be a comma-separated list of the top-5 alphabetically sorted modules which have no dependees which are also being loaded. That is, the project name is derived from the modules which are identified as leaf modules in the context of the modules being loaded. :return: A tuple of (modules_sha, project_name) """ def get_module(target): return target.address.spec_path def is_independent(target): return not self.context.build_graph.dependents_of(target.address) all_loaded_modules = sorted({get_module(target) for target in self.context.targets()}) hasher = sha1() for m in all_loaded_modules: hasher.update(m) module_sha = hasher.hexdigest()[:8] independents = self.context.targets(is_independent) modules = {IdeaProject.find_closest_maven_module(t.address.spec_path) for t in independents} modules = sorted(filter(None, modules)) project_name = modules[0].replace('/', '-') if not (ord('a') <= ord(project_name[0].lower()) <= ord('z')): project_name = 'project-with-{count}-modules'.format(count=len(modules)) elif len(modules) > 1: project_name = '{name}-plus-{count}'.format(name=project_name, count=len(modules)-1) return module_sha, project_name
def test_java_language_level(self): blob = { "jvm_platforms": { "platforms": { "1.7": {"source_level": "1.7"}, "the-best": {"source_level": "1.8.34._5"}, "not-the-best": {"source_level": "1.6.1.3_12"}, } }, "targets": { "squarepants/faketarget": {"platform": "the-best"}, "squarepants/shamtarget": {"platform": "not-the-best"}, }, } project = IdeaProject(blob, ".", ".", None) self.assertEqual("JDK_1_8", project._java_language_level(blob["targets"]["squarepants/faketarget"])) self.assertEqual("JDK_1_6", project._java_language_level(blob["targets"]["squarepants/shamtarget"]))
def create_module(name, dependencies=None, libraries=None): module = IdeaProject.Module(None, directory=name, name=name, targets=set()) if dependencies: module.dependencies.update(dependencies) if libraries: for conf in libraries: module.libraries[conf].update(libraries[conf]) return module
def _create_module_pool(self, existing_modules): if not self.get_options().module_pool: return None module_type_pattern = re.compile(r'^(?P<generic_modules>gen-\d+$)|(?P<specific_modules>\.pants\.d-)') module_types = dict(generic_modules=[], specific_modules=[]) for filename in existing_modules: name, _ = os.path.splitext(filename) m = module_type_pattern.match(name) if m: module_types[m.lastgroup].append(name) return IdeaProject.ModulePool(steal_names=self.get_options().module_pool_steal_names, **module_types)
def test_module_pool_stealing(self): pool = IdeaProject.ModulePool(generic_modules=('2', '1', '3'), specific_modules=('b', 'c', 'a'), steal_names=True) self.assertEquals('1', pool.module_for('foobar')) self.assertEquals('1', pool.module_for('foobar')) self.assertEquals('2', pool.module_for('cantaloupe')) self.assertEquals('3', pool.module_for('the-third-number')) self.assertEquals('2', pool.module_for('cantaloupe')) # The specific modules are stored in an unordered set, so we can't depend on the order. no_more = pool.module_for('no-more-gen-modules') self.assertIn(no_more, 'abc') self.assertEquals(no_more, pool.module_for('no-more-gen-modules')) self.assertIn(pool.module_for('this-will-not-explode'), 'abc') self.assertNotEquals(no_more, pool.module_for('this-will-not-explode'))
def test_module_pool_no_stealing(self): pool = IdeaProject.ModulePool(generic_modules=('2', '1', '3'), specific_modules=('b', 'c', 'a'), steal_names=False) self.assertEquals('1', pool.module_for('foobar')) self.assertEquals('1', pool.module_for('foobar')) self.assertEquals('2', pool.module_for('cantaloupe')) self.assertEquals('3', pool.module_for('the-third-number')) self.assertEquals('2', pool.module_for('cantaloupe')) self.assertEquals('no-more-gen-modules', pool.module_for('no-more-gen-modules')) self.assertEquals('no-more-gen-modules', pool.module_for('no-more-gen-modules')) with self.assertRaises(IdeaProject.ModulePool.NoAvailableModules): pool.module_for('this-will-explode', create_if_necessary=False)
def test_module_pool_preferential(self): pool = IdeaProject.ModulePool(generic_modules=('2', '1', '3'), specific_modules=('b', 'c', 'a'), steal_names=True) self.assertEquals('1', pool.module_for('foobar')) self.assertEquals('c', pool.module_for('c')) self.assertEquals('2', pool.module_for('the-third-module')) self.assertEquals('3', pool.module_for('the-third-number')) self.assertEquals('a', pool.module_for('a')) self.assertEquals('b', pool.module_for('process-of-elimination')) self.assertEquals('c', pool.module_for('c')) self.assertEquals('had-to-make-a-new-one', pool.module_for('had-to-make-a-new-one')) # 'b' has been stolen, and there are no specific or generic modules left, so this forces a new # generic module to be generated. self.assertEquals('gen-0000', pool.module_for('b'))
def test_module_dependencies(self): blob = { 'jvm_platforms': { 'platforms': { '1.7': { 'source_level': '1.7' }, }, 'default_platform': '1.7', }, 'targets': { 'foo/a:a': { 'roots': [{ 'source_root': 'foo/a/src/main/java' }] }, 'foo/b:b': { 'targets': [ 'foo/a:a', ], 'roots': [{ 'source_root': 'foo/b/src/main/java' }] }, 'foo/c:c': { 'roots': [{ 'source_root': 'foo/c/src/main/java' }] }, 'foo/d:d': { 'roots': [{ 'source_root': 'foo/d/src/main/java' }] }, 'foo/e:e': { 'targets': [ 'foo/c:c', 'foo/d:d', ] }, 'foo/f:f': { 'targets': [ 'foo/e:e', ] }, 'foo:foo': { 'targets': [ 'foo/b:b', 'foo/f:f', ], 'roots': [{ 'source_root': 'foo/src/main/java' }] }, 'foo/cycle:cycle': { 'targets': [ 'foo/cycle:cycle', ] }, 'bar:bar': { 'targets': [ 'foo:foo', ], 'roots': [{ 'source_root': 'bar/src/main/java' }] } } } for target in blob['targets'].values(): target['pants_target_type'] = 'java_library' def module_dependencies(spec): modules, _ = project._compute_module_and_library_dependencies( blob['targets'][spec]) return modules project = IdeaProject(blob, '.', '.', None, maven_style=True) self.assertEqual(set(), module_dependencies('foo/a:a')) self.assertEqual({'foo-a'}, module_dependencies('foo/b:b')) self.assertEqual({'foo-c', 'foo-d'}, module_dependencies('foo/e:e')) self.assertEqual({'foo-c', 'foo-d'}, module_dependencies('foo/f:f')) # foo/a:a isn't included because it's a transitive dependency of foo/b:b, and foo/b:b has source # roots. Transitive dependencies are only "collapsed" if the intermediary dependency has no # source roots (and thus no module to correspond to). self.assertEqual({'foo-b', 'foo-c', 'foo-d'}, module_dependencies('foo:foo')) self.assertEqual(set(), module_dependencies('foo/cycle:cycle')) self.assertEqual({'foo'}, module_dependencies('bar:bar'))
def assert_simplifies_to(expected, modules): IdeaProject._simplify_module_dependency_graph(modules, prune_libraries=True) assert_modules_equal(expected, modules)
def assert_simplifies_to(expected, modules): IdeaProject._simplify_module_dependency_graph(modules, prune_libraries=True) assert_modules_equal(expected, modules)