/* * SonarLint for Eclipse * Copyright (C) 2015-2017 SonarSource SA * sonarlint@sonarsource.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.sonarlint.eclipse.cdt.internal; import java.util.Collection; import java.util.Map; import javax.annotation.Nullable; public class BuildWrapperJsonFactory { private static final String COMPILER = "clang"; public String create(Collection<ConfiguredFile> files, String baseDirPath) { StringBuilder builder = new StringBuilder(); builder.append("{" + "\"version\":0," + "\"captures\":["); boolean first = true; for (ConfiguredFile file : files) { if (first) { first = false; } else { builder.append(","); } writeFile(builder, baseDirPath, file.path(), file.includes(), file.symbols()); } builder.append("]}"); return builder.toString(); } private static void writeFile(StringBuilder builder, String baseDirPath, String filePath, String[] includes, Map<String, String> symbols) { String probeStdout = probeStdout(symbols); String probeStderr = probeStderr(includes); writeCompilerProbe(builder, filePath, probeStdout, probeStderr); builder.append(","); writeCompilerProbe(builder, filePath, probeStdout, probeStderr); builder.append(","); builder.append("{") .append("\"compiler\":\"" + COMPILER + "\",") .append("\"cwd\":" + quote(baseDirPath) + ",") .append("\"executable\":" + quote(filePath) + ",") .append("\"cmd\":[") .append("\"clang\"") .append("," + quote(filePath) + "") .append("]}"); } private static String probeStderr(String[] includes) { StringBuilder builder = new StringBuilder("#include <...> search starts here:\n"); for (String include : includes) { builder.append(" ").append(include).append("\n"); } builder.append("End of search list.\n"); return builder.toString(); } private static String probeStdout(Map<String, String> symbols) { StringBuilder builder = new StringBuilder(); for (Map.Entry<String, String> symbol : symbols.entrySet()) { builder.append("#define " + symbol.getKey() + " " + symbol.getValue()).append("\n"); } return builder.toString(); } private static void writeCompilerProbe(StringBuilder builder, String compilerKey, String stdout, String stderr) { builder .append("{") .append("\"compiler\":\"").append(COMPILER).append("\",") .append("\"executable\":").append(quote(compilerKey)).append(",") .append("\"stdout\":").append(quote(stdout)).append(",") .append("\"stderr\":").append(quote(stderr)) .append("}"); } private static String quote(@Nullable String string) { if (string == null || string.length() == 0) { return "\"\""; } char c; int i; int len = string.length(); StringBuilder sb = new StringBuilder(len + 4); String t; sb.append('"'); for (i = 0; i < len; i += 1) { c = string.charAt(i); switch (c) { case '\\': case '"': sb.append('\\'); sb.append(c); break; case '\b': sb.append("\\b"); break; case '\t': sb.append("\\t"); break; case '\n': sb.append("\\n"); break; case '\f': sb.append("\\f"); break; case '\r': sb.append("\\r"); break; default: if (c < ' ') { t = "000" + Integer.toHexString(c); sb.append("\\u" + t.substring(t.length() - 4)); } else { sb.append(c); } } } sb.append('"'); return sb.toString(); } }