From: Antoine Vinot Date: Tue, 8 Nov 2022 11:14:43 +0000 (+0100) Subject: SONAR-17560 Add Sarif deserialization X-Git-Tag: 9.8.0.63668~126 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=59df4a4ad498fa1ce6df396c0b7a6afb70b7ec83;p=sonarqube.git SONAR-17560 Add Sarif deserialization --- diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/ArtifactLocation.java b/sonar-core/src/main/java/org/sonar/core/sarif/ArtifactLocation.java index b9839979c74..f12413c339d 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/ArtifactLocation.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/ArtifactLocation.java @@ -1,33 +1,45 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; import com.google.gson.annotations.SerializedName; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; public class ArtifactLocation { - private static final String URI_BASE_ID = "%SRCROOT"; @SerializedName("uri") private final String uri; @SerializedName("uriBaseId") private final String uriBaseId; - private ArtifactLocation(String uriBaseId, String uri) { + public ArtifactLocation(@Nullable String uriBaseId, String uri) { this.uriBaseId = uriBaseId; this.uri = uri; } - public static ArtifactLocation of(String uri) { - return new ArtifactLocation(URI_BASE_ID, uri); - } - public String getUri() { return uri; } + @CheckForNull public String getUriBaseId() { return uriBaseId; } diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/CodeFlow.java b/sonar-core/src/main/java/org/sonar/core/sarif/CodeFlow.java index 0ee64717140..887ba202215 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/CodeFlow.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/CodeFlow.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Driver.java b/sonar-core/src/main/java/org/sonar/core/sarif/Driver.java index cbbbe3b32a3..aaa8d9faac2 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/Driver.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/Driver.java @@ -1,16 +1,30 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; import com.google.gson.annotations.SerializedName; import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; public class Driver { - private static final String TOOL_NAME = "SonarQube"; - private static final String ORGANIZATION_NAME = "SonarSource"; @SerializedName("name") private final String name; @@ -21,11 +35,7 @@ public class Driver { @SerializedName("rules") private final Set rules; - public Driver(String semanticVersion, Set rules) { - this(TOOL_NAME, ORGANIZATION_NAME, semanticVersion, rules); - } - - private Driver(String name, String organization, String semanticVersion, Set rules) { + private Driver(String name, @Nullable String organization, @Nullable String semanticVersion, Set rules) { this.name = name; this.organization = organization; this.semanticVersion = semanticVersion; @@ -36,10 +46,12 @@ public class Driver { return name; } + @CheckForNull public String getOrganization() { return organization; } + @CheckForNull public String getSemanticVersion() { return semanticVersion; } @@ -47,4 +59,42 @@ public class Driver { public Set getRules() { return rules; } + + public static DriverBuilder builder() { + return new DriverBuilder(); + } + + public static final class DriverBuilder { + private String name; + private String organization; + private String semanticVersion; + private Set rules; + + private DriverBuilder() { + } + + public DriverBuilder name(String name) { + this.name = name; + return this; + } + + public DriverBuilder organization(String organization) { + this.organization = organization; + return this; + } + + public DriverBuilder semanticVersion(String semanticVersion) { + this.semanticVersion = semanticVersion; + return this; + } + + public DriverBuilder rules(Set rules) { + this.rules = rules; + return this; + } + + public Driver build() { + return new Driver(name, organization, semanticVersion, rules); + } + } } diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Location.java b/sonar-core/src/main/java/org/sonar/core/sarif/Location.java index c2a334c9bd9..ae1db296947 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/Location.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/Location.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/LocationWrapper.java b/sonar-core/src/main/java/org/sonar/core/sarif/LocationWrapper.java index 2c551204713..91fa55680fe 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/LocationWrapper.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/LocationWrapper.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/PartialFingerprints.java b/sonar-core/src/main/java/org/sonar/core/sarif/PartialFingerprints.java index 67cbbdef1d6..ffef750f531 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/PartialFingerprints.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/PartialFingerprints.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/PhysicalLocation.java b/sonar-core/src/main/java/org/sonar/core/sarif/PhysicalLocation.java index c4c1e833944..0d9b7582c84 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/PhysicalLocation.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/PhysicalLocation.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/PropertiesBag.java b/sonar-core/src/main/java/org/sonar/core/sarif/PropertiesBag.java index 1f44afc39ac..949f3fea3ef 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/PropertiesBag.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/PropertiesBag.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Region.java b/sonar-core/src/main/java/org/sonar/core/sarif/Region.java index 8fd89fa4c41..e909fceb9c3 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/Region.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/Region.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; @@ -45,10 +59,10 @@ public class Region { } public static final class RegionBuilder { - private int startLine; - private int endLine; - private int startColumn; - private int endColumn; + private Integer startLine; + private Integer endLine; + private Integer startColumn; + private Integer endColumn; public RegionBuilder startLine(int startLine) { this.startLine = startLine; diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Result.java b/sonar-core/src/main/java/org/sonar/core/sarif/Result.java index 3815da4a480..60f980de875 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/Result.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/Result.java @@ -1,14 +1,30 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; import com.google.gson.annotations.SerializedName; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; -import org.sonar.api.rule.RuleKey; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; public class Result { @SerializedName("ruleId") @@ -16,19 +32,19 @@ public class Result { @SerializedName("message") private final WrappedText message; @SerializedName("locations") - private final Set locations; + private final LinkedHashSet locations; @SerializedName("partialFingerprints") private final PartialFingerprints partialFingerprints; @SerializedName("codeFlows") private final List codeFlows; - - private Result(RuleKey ruleKey, String message, Location location, String primaryLocationLineHash, List codeFlows) { - this.ruleId = ruleKey.toString(); + private Result(String ruleId, String message, LinkedHashSet locations, + @Nullable String primaryLocationLineHash, @Nullable List codeFlows) { + this.ruleId = ruleId; this.message = WrappedText.of(message); - this.locations = Set.of(location); - this.partialFingerprints = new PartialFingerprints(primaryLocationLineHash); - this.codeFlows = List.copyOf(codeFlows); + this.locations = locations; + this.partialFingerprints = primaryLocationLineHash == null ? null : new PartialFingerprints(primaryLocationLineHash); + this.codeFlows = codeFlows == null ? null : List.copyOf(codeFlows); } public String getRuleId() { @@ -43,10 +59,12 @@ public class Result { return locations; } + @CheckForNull public PartialFingerprints getPartialFingerprints() { return partialFingerprints; } + @CheckForNull public List getCodeFlows() { return codeFlows; } @@ -56,17 +74,17 @@ public class Result { } public static final class ResultBuilder { - private RuleKey ruleKey; + private String ruleId; private String message; - private Location location; + private LinkedHashSet locations; private String hash; private List codeFlows; private ResultBuilder() { } - public ResultBuilder ruleKey(RuleKey ruleKey) { - this.ruleKey = ruleKey; + public ResultBuilder ruleId(String ruleId) { + this.ruleId = ruleId; return this; } @@ -75,8 +93,8 @@ public class Result { return this; } - public ResultBuilder locations(Location location) { - this.location = location; + public ResultBuilder locations(Set locations) { + this.locations = new LinkedHashSet<>(locations); return this; } @@ -91,7 +109,7 @@ public class Result { } public Result build() { - return new Result(ruleKey, message, location, hash, codeFlows); + return new Result(ruleId, message, locations, hash, codeFlows); } } } diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Rule.java b/sonar-core/src/main/java/org/sonar/core/sarif/Rule.java index ce234118159..eb4e140ae64 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/Rule.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/Rule.java @@ -1,13 +1,26 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; import com.google.gson.annotations.SerializedName; import java.util.Objects; -import org.sonar.api.rule.RuleKey; public class Rule { @SerializedName("id") @@ -23,12 +36,12 @@ public class Rule { @SerializedName("properties") private final PropertiesBag properties; - public Rule(RuleKey ruleKey, String ruleName, String ruleDescription, PropertiesBag properties) { - id = ruleKey.toString(); - name = ruleKey.toString(); - shortDescription = WrappedText.of(ruleName); - fullDescription = WrappedText.of(ruleName); - help = WrappedText.of(ruleDescription); + private Rule(String id, String name, WrappedText shortDescription, WrappedText fullDescription, WrappedText help, PropertiesBag properties) { + this.id = id; + this.name = name; + this.shortDescription = shortDescription; + this.fullDescription = fullDescription; + this.help = help; this.properties = properties; } @@ -73,4 +86,53 @@ public class Rule { return Objects.hash(id); } + public static RuleBuilder builder() { + return new RuleBuilder(); + } + + public static final class RuleBuilder { + private String id; + private String name; + private WrappedText shortDescription; + private WrappedText fullDescription; + private WrappedText help; + private PropertiesBag properties; + + private RuleBuilder() { + } + + public RuleBuilder id(String id) { + this.id = id; + return this; + } + + public RuleBuilder name(String name) { + this.name = name; + return this; + } + + public RuleBuilder shortDescription(String shortDescription) { + this.shortDescription = WrappedText.of(shortDescription); + return this; + } + + public RuleBuilder fullDescription(String fullDescription) { + this.fullDescription = WrappedText.of(fullDescription); + return this; + } + + public RuleBuilder help(String help) { + this.help = WrappedText.of(help); + return this; + } + + public RuleBuilder properties(PropertiesBag properties) { + this.properties = properties; + return this; + } + + public Rule build() { + return new Rule(id, name, shortDescription, fullDescription, help, properties); + } + } } diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Run.java b/sonar-core/src/main/java/org/sonar/core/sarif/Run.java index ae8cc0a78e4..ebcf81055fa 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/Run.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/Run.java @@ -1,21 +1,31 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; -import com.google.common.annotations.VisibleForTesting; import com.google.gson.annotations.SerializedName; import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; public class Run { - @VisibleForTesting - public static final String LANGUAGE_EN_US = "en-us"; - @VisibleForTesting - public static final String COLUMN_KIND = "utf16CodeUnits"; - @SerializedName("tool") private final Tool tool; @SerializedName("results") @@ -25,21 +35,19 @@ public class Run { @SerializedName("columnKind") private final String columnKind; - public Run(Tool tool, Set results) { - this(tool, results, LANGUAGE_EN_US, COLUMN_KIND); - } - - private Run(Tool tool, Set results, String language, String columnKind) { + private Run(Tool tool, Set results, @Nullable String language, @Nullable String columnKind) { this.tool = tool; this.results = Set.copyOf(results); this.language = language; this.columnKind = columnKind; } + @CheckForNull public String getLanguage() { return language; } + @CheckForNull public String getColumnKind() { return columnKind; } @@ -51,4 +59,43 @@ public class Run { public Set getResults() { return results; } + + public static RunBuilder builder() { + return new RunBuilder(); + } + + public static final class RunBuilder { + private Tool tool; + private Set results; + private String language; + private String columnKind; + + private RunBuilder() { + } + + public RunBuilder tool(Tool tool) { + this.tool = tool; + return this; + } + + public RunBuilder results(Set results) { + this.results = results; + return this; + } + + public RunBuilder language(String language) { + this.language = language; + return this; + } + + public RunBuilder columnKind(String columnKind) { + this.columnKind = columnKind; + return this; + } + + public Run build() { + return new Run(tool, results, language, columnKind); + } + } + } diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Sarif210.java b/sonar-core/src/main/java/org/sonar/core/sarif/Sarif210.java index d19c386461f..0df616af2e2 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/Sarif210.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/Sarif210.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; @@ -11,8 +25,6 @@ import java.util.Set; public class Sarif210 { - @VisibleForTesting - public static final String SARIF_SCHEMA_URL = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"; @VisibleForTesting public static final String SARIF_VERSION = "2.1.0"; @@ -23,13 +35,9 @@ public class Sarif210 { @SerializedName("runs") private final Set runs; - public Sarif210(Run run) { - this(SARIF_SCHEMA_URL, SARIF_VERSION, run); - } - - private Sarif210(String schema, String version, Run run) { + public Sarif210(String schema, Run run) { this.schema = schema; - this.version = version; + this.version = SARIF_VERSION; this.runs = Set.of(run); } diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializer.java b/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializer.java index 62c2452d896..1f984da096e 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializer.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializer.java @@ -1,49 +1,29 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; -import com.google.common.annotations.VisibleForTesting; -import com.google.gson.Gson; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.Base64; -import java.util.zip.GZIPOutputStream; -import javax.inject.Inject; -import org.sonar.api.ce.ComputeEngineSide; +import java.nio.file.Path; -import static java.nio.charset.StandardCharsets.UTF_8; +public interface SarifSerializer { -@ComputeEngineSide -public class SarifSerializer { - private final Gson gson; + String serialize(Sarif210 sarif210); - @Inject - public SarifSerializer() { - this(new Gson()); - } - - @VisibleForTesting - SarifSerializer(Gson gson) { - this.gson = gson; - } - - public String serializeAndEncode(Sarif210 sarif210) { - String serializedSarif = gson.toJson(sarif210); - return compressToGzipAndEncodeBase64(serializedSarif); - } - - private static String compressToGzipAndEncodeBase64(String input) { - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - GZIPOutputStream gzipStream = new GZIPOutputStream(outputStream)) { - gzipStream.write(input.getBytes(UTF_8)); - gzipStream.finish(); - return Base64.getEncoder().encodeToString(outputStream.toByteArray()); - } catch (IOException e) { - throw new UncheckedIOException(String.format("Failed to compress and encode the input: %s", input), e); - } - } + Sarif210 deserialize(Path sarifPath); } diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializerImpl.java b/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializerImpl.java new file mode 100644 index 00000000000..3f33419cb87 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/sarif/SarifSerializerImpl.java @@ -0,0 +1,70 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT 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.sonar.core.sarif; + +import com.google.common.annotations.VisibleForTesting; +import com.google.gson.Gson; +import com.google.gson.JsonIOException; +import com.google.gson.JsonSyntaxException; +import java.io.IOException; +import java.io.Reader; +import java.nio.file.Path; +import javax.inject.Inject; +import org.sonar.api.ce.ComputeEngineSide; +import org.sonar.api.scanner.ScannerSide; + +import static java.lang.String.format; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.nio.file.Files.newBufferedReader; + +@ScannerSide +@ComputeEngineSide +public class SarifSerializerImpl implements SarifSerializer { + private static final String SARIF_REPORT_ERROR = "Failed to read SARIF report at '%s'"; + private static final String SARIF_JSON_SYNTAX_ERROR = SARIF_REPORT_ERROR + ": invalid JSON syntax"; + + private final Gson gson; + + @Inject + public SarifSerializerImpl() { + this(new Gson()); + } + + @VisibleForTesting + SarifSerializerImpl(Gson gson) { + this.gson = gson; + } + + @Override + public String serialize(Sarif210 sarif210) { + return gson.toJson(sarif210); + } + + @Override + public Sarif210 deserialize(Path reportPath) { + try (Reader reader = newBufferedReader(reportPath, UTF_8)) { + return gson.fromJson(reader, Sarif210.class); + } catch (JsonIOException | IOException e) { + throw new IllegalStateException(format(SARIF_REPORT_ERROR, reportPath), e); + } catch (JsonSyntaxException e) { + throw new IllegalStateException(format(SARIF_JSON_SYNTAX_ERROR, reportPath), e); + } + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/ThreadFlow.java b/sonar-core/src/main/java/org/sonar/core/sarif/ThreadFlow.java index 45d75c0bdc0..e8cd950fda6 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/ThreadFlow.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/ThreadFlow.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/Tool.java b/sonar-core/src/main/java/org/sonar/core/sarif/Tool.java index 3990f8447f8..7a10feea395 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/Tool.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/Tool.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; diff --git a/sonar-core/src/main/java/org/sonar/core/sarif/WrappedText.java b/sonar-core/src/main/java/org/sonar/core/sarif/WrappedText.java index ddf259342f6..06539aaa6d0 100644 --- a/sonar-core/src/main/java/org/sonar/core/sarif/WrappedText.java +++ b/sonar-core/src/main/java/org/sonar/core/sarif/WrappedText.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; diff --git a/sonar-core/src/test/java/org/sonar/core/sarif/RuleTest.java b/sonar-core/src/test/java/org/sonar/core/sarif/RuleTest.java index e579f8c3571..6714bbcb3e1 100644 --- a/sonar-core/src/test/java/org/sonar/core/sarif/RuleTest.java +++ b/sonar-core/src/test/java/org/sonar/core/sarif/RuleTest.java @@ -1,17 +1,28 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; import java.util.Set; -import org.apache.commons.lang.RandomStringUtils; import org.junit.Test; -import org.sonar.api.rule.RuleKey; -import org.sonar.core.sarif.PropertiesBag; -import org.sonar.core.sarif.Rule; +import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; @@ -19,34 +30,51 @@ public class RuleTest { @Test public void equals_matchOnlyOnId() { - Rule rule1 = createRule("rep1", "rule1"); - Rule rule1Bis = createRule("rep1", "rule1"); - Rule rule2 = withRuleId(rule1, "rep1", "rule2"); + Rule rule1 = createRule(); + Rule rule1Bis = createRule(rule1.getId()) ; + Rule rule2 = withRuleId(rule1, rule1.getId() + randomAlphanumeric(3)); assertThat(rule1).isEqualTo(rule1Bis).isNotEqualTo(rule2); } @Test public void equals_notMatchWithNull(){ - Rule rule1 = createRule("rep1", "rule2"); + Rule rule1 = createRule(); assertThat(rule1).isNotEqualTo(null); } @Test public void equals_matchWithSameObject(){ - Rule rule1 = createRule("rep5", "rule2"); + Rule rule1 = createRule(); assertThat(rule1).isEqualTo(rule1); } - private static Rule withRuleId(Rule rule, String repoName, String ruleName) { - return new Rule(RuleKey.of(repoName, ruleName), rule.getName(), rule.getFullDescription().getText(), rule.getProperties()); + private static Rule withRuleId(Rule rule, String id) { + return Rule.builder() + .id(id) + .name(rule.getName()) + .shortDescription(rule.getName()) + .fullDescription(rule.getName()) + .help(rule.getFullDescription().getText()) + .properties(rule.getProperties()) + .build(); } - private static Rule createRule(String repoName, String ruleName) { - return new Rule(RuleKey.of(repoName, ruleName), RandomStringUtils.randomAlphanumeric(5), RandomStringUtils.randomAlphanumeric(5), - PropertiesBag.of(RandomStringUtils.randomAlphanumeric(3), Set.of(RandomStringUtils.randomAlphanumeric(4)))); + private static Rule createRule() { + return createRule(randomAlphanumeric(5)); + } + + private static Rule createRule(String id) { + return Rule.builder() + .id(id) + .name(randomAlphanumeric(5)) + .shortDescription(randomAlphanumeric(5)) + .fullDescription(randomAlphanumeric(10)) + .help(randomAlphanumeric(10)) + .properties(PropertiesBag.of(randomAlphanumeric(3), Set.of(randomAlphanumeric(4)))) + .build(); } } diff --git a/sonar-core/src/test/java/org/sonar/core/sarif/Sarif210SerializationDeserializationTest.java b/sonar-core/src/test/java/org/sonar/core/sarif/Sarif210SerializationDeserializationTest.java index ef40fe8dcd5..e603ada42e9 100644 --- a/sonar-core/src/test/java/org/sonar/core/sarif/Sarif210SerializationDeserializationTest.java +++ b/sonar-core/src/test/java/org/sonar/core/sarif/Sarif210SerializationDeserializationTest.java @@ -1,7 +1,21 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; diff --git a/sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerTest.java b/sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerTest.java index e239a5e859f..8350226ce75 100644 --- a/sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerTest.java +++ b/sonar-core/src/test/java/org/sonar/core/sarif/SarifSerializerTest.java @@ -1,43 +1,161 @@ /* - * Copyright (C) 2017-2022 SonarSource SA - * All rights reserved + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA * mailto:info AT sonarsource DOT 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.sonar.core.sarif; -import com.google.gson.Gson; -import org.sonar.core.sarif.Sarif210; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Set; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static java.util.Objects.requireNonNull; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.fail; @RunWith(MockitoJUnitRunner.class) public class SarifSerializerTest { - private static final String SARIF_JSON = "{\"message\" : \"A sarif in json format as String.\"}"; - private static final String SARIF_JSON_ENCODED = "H4sIAAAAAAAAAKtWyk0tLk5MT1VSsFJQclQoTizKTFPIzFPIKs7PU0jLL8pNLFFILFYILinKzEvXU6oFACgK7/YxAAAA"; + private static final String SARIF_JSON = "{\"version\":\"2.1.0\",\"$schema\":\"http://json.schemastore.org/sarif-2.1.0-rtm.4\",\"runs\":[{\"results\":[]}]}"; - @Mock - private Gson gson; + private final SarifSerializerImpl serializer = new SarifSerializerImpl(); - @InjectMocks - private SarifSerializer serializer; + @Test + public void serialize() { + Run.builder().results(Set.of()).build(); + Sarif210 sarif210 = new Sarif210("http://json.schemastore.org/sarif-2.1.0-rtm.4", Run.builder().results(Set.of()).build()); + + String result = serializer.serialize(sarif210); + + assertThat(result).isEqualTo(SARIF_JSON); + } + + @Test + public void deserialize() throws URISyntaxException { + URL sarifResource = requireNonNull(getClass().getResource("eslint-sarif210.json")); + Path sarif = Paths.get(sarifResource.toURI()); + + Sarif210 deserializationResult = serializer.deserialize(sarif); + + verifySarif(deserializationResult); + } @Test - public void serializeAndEncode_should_compressInGZipAndEncodeBase64() { - when(gson.toJson(any(Sarif210.class))).thenReturn(SARIF_JSON); - Sarif210 sarif210 = mock(Sarif210.class); + public void deserialize_shouldFail_whenFileCantBeFound() { + String file = "wrongPathToFile"; + Path sarif = Paths.get(file); + + assertThatThrownBy(() -> serializer.deserialize(sarif)) + .isInstanceOf(IllegalStateException.class) + .hasMessage(String.format("Failed to read SARIF report at '%s'", file)); + } + + @Test + public void deserialize_shouldFail_whenJsonSyntaxIsIncorrect() throws URISyntaxException { + URL sarifResource = requireNonNull(getClass().getResource("invalid-json-syntax.json")); + Path sarif = Paths.get(sarifResource.toURI()); + + assertThatThrownBy(() -> serializer.deserialize(sarif)) + .isInstanceOf(IllegalStateException.class) + .hasMessage(String.format("Failed to read SARIF report at '%s': invalid JSON syntax", sarif)); + } + + private void verifySarif(Sarif210 deserializationResult) { + Sarif210 expected = buildExpectedSarif210(); + + assertThat(deserializationResult).isNotNull(); + assertThat(deserializationResult).usingRecursiveComparison().ignoringFields("runs").isEqualTo(expected); + + Run run = getRun(deserializationResult); + Run expectedRun = getRun(expected); + assertThat(run).usingRecursiveComparison().ignoringFields("results", "tool.driver.rules").isEqualTo(expectedRun); + + Result result = getResult(run); + Result expectedResult = getResult(expectedRun); + assertThat(result).usingRecursiveComparison().isEqualTo(expectedResult); - String encoded = serializer.serializeAndEncode(sarif210); + Rule rule = getRule(run); + Rule expectedRule = getRule(expectedRun); + assertThat(rule).usingRecursiveComparison().ignoringFields("properties").isEqualTo(expectedRule); + } + + private static Sarif210 buildExpectedSarif210() { + return new Sarif210("http://json.schemastore.org/sarif-2.1.0-rtm.4", buildExpectedRun()); + } + + private static Run buildExpectedRun() { + Tool tool = new Tool(buildExpectedDriver()); + return Run.builder() + .tool(tool) + .results(Set.of(buildExpectedResult())).build(); + } + + private static Driver buildExpectedDriver() { + return Driver.builder() + .name("ESLint") + .rules(Set.of(buildExpectedRule())) + .build(); + } + + private static Rule buildExpectedRule() { + return Rule.builder() + .id("no-unused-vars") + .shortDescription("disallow unused variables") + .build(); + } + + private static Result buildExpectedResult() { + return Result.builder() + .ruleId("no-unused-vars") + .locations(Set.of(buildExpectedLocation())) + .message("'x' is assigned a value but never used.") + .level("error") + .build(); + } + + private static Location buildExpectedLocation() { + ArtifactLocation artifactLocation = new ArtifactLocation(null, "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js"); + PhysicalLocation physicalLocation = PhysicalLocation.of(artifactLocation, buildExpectedRegion()); + return Location.of(physicalLocation); + } + + private static Region buildExpectedRegion() { + return Region.builder() + .startLine(1) + .startColumn(5) + .build(); + } + + private static Run getRun(Sarif210 sarif210) { + return sarif210.getRuns().stream().findFirst().orElseGet(() -> fail("runs property is missing")); + } + + private static Result getResult(Run run) { + return run.getResults().stream().findFirst().orElseGet(() -> fail("results property is missing")); + } - assertThat(encoded).isEqualTo(SARIF_JSON_ENCODED); + private static Rule getRule(Run run) { + return run.getTool().getDriver().getRules().stream().findFirst().orElseGet(() -> fail("rules property is missing")); } } diff --git a/sonar-core/src/test/resources/org/sonar/core/sarif/eslint-sarif210.json b/sonar-core/src/test/resources/org/sonar/core/sarif/eslint-sarif210.json new file mode 100644 index 00000000000..3d7d3445738 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/sarif/eslint-sarif210.json @@ -0,0 +1,57 @@ +{ + "version": "2.1.0", + "$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.4", + "runs": [ + { + "tool": { + "driver": { + "name": "ESLint", + "informationUri": "https://eslint.org", + "rules": [ + { + "id": "no-unused-vars", + "shortDescription": { + "text": "disallow unused variables" + }, + "helpUri": "https://eslint.org/docs/rules/no-unused-vars", + "properties": { + "category": "Variables" + } + } + ] + } + }, + "artifacts": [ + { + "location": { + "uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js" + } + } + ], + "results": [ + { + "level": "error", + "message": { + "text": "'x' is assigned a value but never used." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js", + "index": 0 + }, + "region": { + "startLine": 1, + "startColumn": 5 + } + } + } + ], + "ruleId": "no-unused-vars", + "ruleIndex": 0 + } + ] + } + ] +} diff --git a/sonar-core/src/test/resources/org/sonar/core/sarif/invalid-json-syntax.json b/sonar-core/src/test/resources/org/sonar/core/sarif/invalid-json-syntax.json new file mode 100644 index 00000000000..eff20eb286a --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/sarif/invalid-json-syntax.json @@ -0,0 +1,8 @@ +{ + "version": "2.1.0", + "$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.4", + "runs": + { + + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchComponents.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchComponents.java index 9241acae7ab..41144e68466 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchComponents.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/BatchComponents.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.List; import org.sonar.core.component.DefaultResourceTypes; import org.sonar.core.config.CorePropertyDefinitions; +import org.sonar.core.sarif.SarifSerializerImpl; import org.sonar.scanner.cpd.JavaCpdBlockIndexerSensor; import org.sonar.scanner.deprecated.test.TestPlanBuilder; import org.sonar.scanner.externalissue.ExternalIssuesImportSensor; @@ -53,6 +54,7 @@ public class BatchComponents { // External issues components.add(ExternalIssuesImportSensor.class); components.add(ExternalIssuesImportSensor.properties()); + components.add(SarifSerializerImpl.class); return components; }