in src/com/facebook/buck/command/intellij.py [0:0]
def write_modules(modules):
"""Writes one XML file for each module."""
for module in modules:
# Build up the XML.
module_type = 'JAVA_MODULE'
if 'isIntelliJPlugin' in module and module['isIntelliJPlugin']:
module_type = 'PLUGIN_MODULE'
xml = MODULE_XML_START % {
'type': module_type,
}
# Android facet, if appropriate.
if module.get('hasAndroidFacet') == True:
if 'keystorePath' in module:
keystore = 'file://$MODULE_DIR$/%s' % module['keystorePath']
else:
keystore = ''
if 'androidManifest' in module:
android_manifest = module['androidManifest']
else:
android_manifest = '/AndroidManifest.xml'
is_library_project = module['isAndroidLibraryProject']
android_params = {
'android_manifest': android_manifest,
'res': '/res',
'is_android_library_project': str(is_library_project).lower(),
'run_proguard': 'false',
'module_gen_path': module['moduleGenPath'],
'proguard_config': '/proguard.cfg',
'keystore': keystore,
'libs_path' : '/%s' % module.get('nativeLibs', 'libs'),
}
xml += ANDROID_FACET % android_params
# Source code and libraries component.
xml += '\n <component name="NewModuleRootManager" inherit-compiler-output="true">'
# Empirically, if there are multiple source folders, then the <content> element for the
# buck-out/android/gen folder should be listed before the other source folders.
num_source_folders = len(module['sourceFolders'])
if num_source_folders > 1:
xml = add_buck_android_source_folder(xml, module)
# Source folders.
xml += '\n <content url="file://$MODULE_DIR$">'
for source_folder in module['sourceFolders']:
if 'packagePrefix' in source_folder:
package_prefix = 'packagePrefix="%s" ' % source_folder['packagePrefix']
else:
package_prefix = ''
xml += '\n <sourceFolder url="%(url)s" isTestSource="%(is_test_source)s" %(package_prefix)s/>' % {
'url': source_folder['url'],
'is_test_source': str(source_folder['isTestSource']).lower(),
'package_prefix': package_prefix
}
for exclude_folder in module['excludeFolders']:
xml += '\n <excludeFolder url="%s" />' % exclude_folder['url']
xml += '\n </content>'
xml = add_annotation_generated_source_folder(xml, module)
# Empirically, if there is one source folder, then the <content> element for the
# buck-out/android/gen folder should be listed after the other source folders.
if num_source_folders <= 1:
xml = add_buck_android_source_folder(xml, module)
# Dependencies.
dependencies = module['dependencies']
module_name = module['name']
# We need to filter out some of the modules in the dependency list:
# (1) The module may list itself as a dependency with scope="TEST", which is bad.
# (2) The module may list another module as a dependency with both COMPILE and TEST scopes, in
# which case the COMPILE scope should win.
# compile_dependencies will be the set of names of dependent modules that do not have scope="TEST"
compile_dependencies = filter(lambda dep: dep['type'] == 'module' and
((not ('scope' in dep)) or dep['scope'] != 'TEST'),
dependencies)
compile_dependencies = map(lambda dep: dep['moduleName'], compile_dependencies)
compile_dependencies = set(compile_dependencies)
# Filter dependencies to satisfy (1) and (2) defined above.
filtered_dependencies = []
for dep in dependencies:
if dep['type'] != 'module':
# Non-module dependencies should still be included.
filtered_dependencies.append(dep)
else:
# dep must be a module
dep_module_name = dep['moduleName']
if dep_module_name == module_name:
# Exclude self-references!
continue
elif 'scope' in dep and dep['scope'] == 'TEST':
# If this is a scope="TEST" module and the module is going to be included as
# a scope="COMPILE" module, then exclude it.
if not (dep_module_name in compile_dependencies):
filtered_dependencies.append(dep)
else:
# Non-test modules should still be included.
filtered_dependencies.append(dep)
# Now that we have filtered the dependencies, we can convert the remaining ones directly into
# XML.
excluded_deps_names = set()
if module_type == 'PLUGIN_MODULE':
# all the jars below are parts of IntelliJ SDK and even though they are required
# for language plugins to work standalone, they cannot be included as the plugin
# module dependency because they would clash with IntelliJ
excluded_deps_names = set([
'annotations', # org/intellij/lang/annotations, org/jetbrains/annotations
'extensions', # com/intellij/openapi/extensions/
'idea', # org/intellij, com/intellij
'jdom', # org/jdom
'junit', # junit/
'light_psi_all', # light psi library
'openapi', # com/intellij/openapi
'picocontainer', # org/picocontainer
'trove4j', # gnu/trove
'util', # com/intellij/util
])
for dep in filtered_dependencies:
if 'scope' in dep:
dep_scope = 'scope="%s" ' % dep['scope']
else:
dep_scope = ''
dep_type = dep['type']
if dep_type == 'library':
if dep['name'] in excluded_deps_names:
continue
xml += '\n <orderEntry type="library" exported="" %sname="%s" level="project" />' % (dep_scope, dep['name'])
elif dep_type == 'module':
dep_module_name = dep['moduleName']
# TODO(mbolin): Eliminate this special-case for jackson. It exists because jackson is not
# an ordinary module: it is a module that functions as a library. Project.java should add it
# as such in project.json to eliminate this special case.
if dep_module_name == 'module_first_party_orca_third_party_jackson':
exported = 'exported="" '
else:
exported = ''
xml += '\n <orderEntry type="module" module-name="%s" %s%s/>' % (dep_module_name, exported, dep_scope)
elif dep_type == 'inheritedJdk':
xml += '\n <orderEntry type="inheritedJdk" />'
elif dep_type == 'jdk':
xml += '\n <orderEntry type="jdk" jdkName="%s" jdkType="%s" />' % (dep['jdkName'], dep['jdkType'])
elif dep_type == 'sourceFolder':
xml += '\n <orderEntry type="sourceFolder" forTests="false" />'
# Close source code and libraries component.
xml += '\n </component>'
# Close XML.
xml += MODULE_XML_END
# Write the module to a file.
write_file_if_changed(module['pathToImlFile'], xml)