/* * Copyright 2015-present Facebook, Inc. * * 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. */ package com.facebook.buck.ide.intellij; import com.facebook.buck.ide.intellij.model.IjLibrary; import com.facebook.buck.ide.intellij.model.IjModule; import com.facebook.buck.ide.intellij.model.IjProjectConfig; import com.facebook.buck.io.MorePaths; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.util.MoreCollectors; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; import org.stringtemplate.v4.ST; /** Writes the serialized representations of IntelliJ project components to disk. */ public class IjProjectWriter { private IjProjectTemplateDataPreparer projectDataPreparer; private IjProjectConfig projectConfig; private ProjectFilesystem projectFilesystem; public IjProjectWriter( IjProjectTemplateDataPreparer projectDataPreparer, IjProjectConfig projectConfig, ProjectFilesystem projectFilesystem) { this.projectDataPreparer = projectDataPreparer; this.projectConfig = projectConfig; this.projectFilesystem = projectFilesystem; } public void write(IJProjectCleaner cleaner) throws IOException { projectFilesystem.mkdirs(IjProjectPaths.IDEA_CONFIG_DIR); writeProjectSettings(cleaner, projectConfig); for (IjModule module : projectDataPreparer.getModulesToBeWritten()) { Path generatedModuleFile = writeModule(module); cleaner.doNotDelete(generatedModuleFile); } for (IjLibrary library : projectDataPreparer.getLibrariesToBeWritten()) { Path generatedLibraryFile = writeLibrary(library); cleaner.doNotDelete(generatedLibraryFile); } Path indexFile = writeModulesIndex(); cleaner.doNotDelete(indexFile); } private Path writeModule(IjModule module) throws IOException { Path path = module.getModuleImlFilePath(); ST moduleContents = StringTemplateFile.MODULE_TEMPLATE.getST(); moduleContents.add("contentRoot", projectDataPreparer.getContentRoot(module)); moduleContents.add("dependencies", projectDataPreparer.getDependencies(module)); moduleContents.add( "generatedSourceFolders", projectDataPreparer.getGeneratedSourceFolders(module)); moduleContents.add("androidFacet", projectDataPreparer.getAndroidProperties(module)); moduleContents.add("sdk", module.getModuleType().getSdkName(projectConfig).orElse(null)); moduleContents.add("sdkType", module.getModuleType().getSdkType(projectConfig)); moduleContents.add( "languageLevel", JavaLanguageLevelHelper.convertLanguageLevelToIjFormat( module.getLanguageLevel().orElse(null))); moduleContents.add("moduleType", module.getModuleType().getImlModuleType()); moduleContents.add( "metaInfDirectory", module .getMetaInfDirectory() .map((dir) -> module.getModuleBasePath().relativize(dir)) .orElse(null)); StringTemplateFile.writeToFile(projectFilesystem, moduleContents, path); return path; } private void writeProjectSettings(IJProjectCleaner cleaner, IjProjectConfig projectConfig) throws IOException { Optional<String> sdkName = projectConfig.getProjectJdkName(); Optional<String> sdkType = projectConfig.getProjectJdkType(); if (!sdkName.isPresent() || !sdkType.isPresent()) { return; } Path path = IjProjectPaths.IDEA_CONFIG_DIR.resolve("misc.xml"); ST contents = StringTemplateFile.MISC_TEMPLATE.getST(); String languageLevelInIjFormat = getLanguageLevelFromConfig(); contents.add("languageLevel", languageLevelInIjFormat); contents.add("jdk15", getJdk15FromLanguageLevel(languageLevelInIjFormat)); contents.add("jdkName", sdkName.get()); contents.add("jdkType", sdkType.get()); StringTemplateFile.writeToFile(projectFilesystem, contents, path); cleaner.doNotDelete(path); } private String getLanguageLevelFromConfig() { Optional<String> languageLevelFromConfig = projectConfig.getProjectLanguageLevel(); if (languageLevelFromConfig.isPresent()) { return languageLevelFromConfig.get(); } else { String languageLevel = projectConfig.getJavaBuckConfig().getDefaultJavacOptions().getSourceLevel(); return JavaLanguageLevelHelper.convertLanguageLevelToIjFormat(languageLevel); } } private static boolean getJdk15FromLanguageLevel(String languageLevel) { boolean jdkUnder15 = "JDK_1_3".equals(languageLevel) || "JDK_1_4".equals(languageLevel); return !jdkUnder15; } private Path writeLibrary(IjLibrary library) throws IOException { Path path = IjProjectPaths.LIBRARIES_DIR.resolve(library.getName() + ".xml"); ST contents = StringTemplateFile.LIBRARY_TEMPLATE.getST(); contents.add("name", library.getName()); contents.add( "binaryJars", library .getBinaryJars() .stream() .map(MorePaths::pathWithUnixSeparators) .collect(MoreCollectors.toImmutableSortedSet())); contents.add( "classPaths", library .getClassPaths() .stream() .map(MorePaths::pathWithUnixSeparators) .collect(MoreCollectors.toImmutableSortedSet())); contents.add( "sourceJars", library .getSourceJars() .stream() .map(MorePaths::pathWithUnixSeparators) .collect(MoreCollectors.toImmutableSortedSet())); contents.add("javadocUrls", library.getJavadocUrls()); //TODO(mkosiba): support res and assets for aar. StringTemplateFile.writeToFile(projectFilesystem, contents, path); return path; } private Path writeModulesIndex() throws IOException { projectFilesystem.mkdirs(IjProjectPaths.IDEA_CONFIG_DIR); Path path = IjProjectPaths.IDEA_CONFIG_DIR.resolve("modules.xml"); ST moduleIndexContents = StringTemplateFile.MODULE_INDEX_TEMPLATE.getST(); moduleIndexContents.add("modules", projectDataPreparer.getModuleIndexEntries()); StringTemplateFile.writeToFile(projectFilesystem, moduleIndexContents, path); return path; } }