Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
eba5cf6
@W-10184957@: Implemented telemetry.
jfeingold35 May 19, 2022
10e5ce3
@W-10184957@: Integrated feedback from code review.
jfeingold35 May 20, 2022
6afb360
@W-10184957@: Integrated feedback from code review.
jfeingold35 May 23, 2022
323f2e1
Merge pull request #695 from forcedotcom/d/W-10184957-b
jfeingold35 Jun 1, 2022
2d76393
@W-10127077@: adds --verbose-violations flag to provide more verbose …
gkjung Jun 3, 2022
415fe3c
Merge pull request #712 from forcedotcom/d/W-10127077
gkjung Jun 3, 2022
5a0c065
@W-10759090@: Implemented method-level targeting for SFGE, and messag…
jfeingold35 Jun 1, 2022
f526cb5
@W-10759090@: Added unit test coverage for inner classes.
jfeingold35 Jun 1, 2022
6980d4b
@W-10759090@: Added help text documenting new feature.
jfeingold35 Jun 3, 2022
9735b1d
@W-10759090@: Supplemental PR to integrate cli-messaging into pmd-cat…
jfeingold35 Jun 3, 2022
539e265
@W-10759090@: Refactored CLI result handler into separate class for b…
jfeingold35 Jun 7, 2022
8882d41
@W-10759090@: Consolidated SFGE input into single file.
jfeingold35 Jun 7, 2022
5912f12
Merge pull request #710 from forcedotcom/d/W-10759090-c
jfeingold35 Jun 7, 2022
ea1d970
@W-11120894@: Added proper cloning for EngineDirective nodes.
jfeingold35 Jun 6, 2022
be56832
@W-11120894@: Integrated feedback from code review.
jfeingold35 Jun 9, 2022
c1924cf
Merge pull request #715 from forcedotcom/d/W-11120894
jfeingold35 Jun 9, 2022
c049364
@W-10759090@: Resolved issues identified in QA.
jfeingold35 Jun 13, 2022
d0ffb19
Merge pull request #721 from forcedotcom/d/W-10759090-supp-2b
jfeingold35 Jun 13, 2022
ca93a43
Adding cli-messaging to sfge and pmd-cataloger so that they can be bu…
rmohan20 Jun 10, 2022
7f5a7c5
Removing settings.gradle on subprojects to keep up with gradle standa…
rmohan20 Jun 13, 2022
eb7df99
Merge pull request #720 from forcedotcom/rm/gradle-dependency
rmohan20 Jun 13, 2022
b135d4d
@d/W-11267130@: violation messages use <br> instead of \n in html
gkjung Jun 15, 2022
a4c5e19
newline change only applies when flag used
gkjung Jun 15, 2022
9b3a269
added test for html verbose-violations message format
gkjung Jun 16, 2022
182afac
feedback from PR
gkjung Jun 16, 2022
0f1c6e7
Merge pull request #724 from forcedotcom/d/W-11267130
gkjung Jun 16, 2022
5d716cf
@W-11267235@: violation messages use a semicolon instead of a line br…
gkjung Jun 15, 2022
c4018c5
Merge pull request #723 from forcedotcom/d/W-11267235
gkjung Jun 16, 2022
e603277
RetireJs updates + package number update to 3.2.0
rmohan20 Jun 21, 2022
f30a914
@W-11321290@ Updating retireJs local repo again for 3.2.0
rmohan20 Jun 22, 2022
5b6d712
Merge pull request #731 from forcedotcom/rm/retireJs-3.2.0
rmohan20 Jun 22, 2022
8c07620
Merge branch 'dev-3' into rm/releaseUpdates-3.2.0
rmohan20 Jun 22, 2022
b976639
Merge pull request #727 from forcedotcom/rm/releaseUpdates-3.2.0
rmohan20 Jun 22, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions cli-messaging/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
plugins {
java
}

version = "1.0"
java.sourceCompatibility = JavaVersion.VERSION_1_8
group = "com.salesforce.messaging"

repositories {
mavenCentral()
}

dependencies {
implementation ("com.googlecode.json-simple:json-simple:1.1.1") {
exclude("junit")
}
implementation("com.google.code.gson:gson:2.3")
testImplementation("junit", "junit", "4.12")
implementation("com.google.guava:guava:28.0-jre")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}

tasks.getByName<Test>("test") {
useJUnitPlatform()
}
Binary file added cli-messaging/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 5 additions & 0 deletions cli-messaging/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
1 change: 1 addition & 0 deletions cli-messaging/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = "cli-messaging"
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
package sfdc.sfdx.scanner.messaging;

import com.google.gson.Gson;
package com.salesforce.messaging;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SfdxMessager {
import com.google.gson.Gson;

public class CliMessager {
// The START string gives us something to scan for when we're processing output.
private static final String START = "SFDX-START";
// The END string lets us know when a message stops, which should prevent bugs involving multi-line output.
private static final String END = "SFDX-END";

private static final List<Message> MESSAGES = new ArrayList<>();

private static SfdxMessager INSTANCE = null;

public static SfdxMessager getInstance() {
if (INSTANCE == null) {
INSTANCE = new SfdxMessager();
}
return INSTANCE;
public static CliMessager getInstance() {
return LazyHolder.INSTANCE;
}

/**
Expand All @@ -31,7 +26,7 @@ public static SfdxMessager getInstance() {
*
* @param exception to send to Typescript layer
*/
public void addMessage(SfdxScannerException exception) {
public void addMessage(MessagePassableException exception) {
final EventKey eventKey = exception.getEventKey();
addMessage(
exception.getFullStacktrace(),
Expand Down Expand Up @@ -65,7 +60,12 @@ public void addMessage(String internalLog, EventKey eventKey, String... args) {
MESSAGES.add(message);
}


/**
* Convert all messages stored by the instance into a JSON-formatted string, enclosed in the start and end strings.
* Java code can use this method to log the messages to console, and TypeScript code can seek the start and stop
* strings to get an array of messages that can be deserialized.
* @return
*/
public String getAllMessagesWithFormatting() {
final String messagesAsJson = getMessagesAsJson();
return START + messagesAsJson + END;
Expand All @@ -75,7 +75,6 @@ private String getMessagesAsJson() {
return new Gson().toJson(MESSAGES);
}


/**
* TO BE USED ONLY BY TESTS!
*
Expand All @@ -93,15 +92,8 @@ public void resetMessages() {
MESSAGES.clear();
}

enum MessageHandler {
UX,
INTERNAL
}

enum MessageType {
INFO,
WARNING,
ERROR
private static final class LazyHolder {
// Postpone initialization until first use
private static final CliMessager INSTANCE = new CliMessager();
}
}

Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package sfdc.sfdx.scanner.messaging;
import static sfdc.sfdx.scanner.messaging.SfdxMessager.*;
package com.salesforce.messaging;
import static com.salesforce.messaging.Message.*;

public enum EventKey {
// MAKE SURE messageKey OF EVERY VALUE ADDED HERE HAS AN ENTRY IN 'messages/EventKeyTemplates.js'!
// MAKE SURE `messageKey` OF EVERY VALUE ADDED HERE HAS AN ENTRY IN 'messages/EventKeyTemplates.js'!
INFO_GENERAL_INTERNAL_LOG("info.generalInternalLog", 1, MessageType.INFO, MessageHandler.INTERNAL, true),
WARNING_INVALID_CAT_SKIPPED("warning.invalidCategorySkipped", 1, MessageType.WARNING, MessageHandler.UX, true),
WARNING_INVALID_RULESET_SKIPPED("warning.invalidRulesetSkipped", 1, MessageType.WARNING, MessageHandler.UX, true),
Expand All @@ -19,13 +19,15 @@ public enum EventKey {
ERROR_EXTERNAL_MULTIPLE_RULE_DESC("error.external.multipleRuleDesc", 2, MessageType.ERROR, MessageHandler.UX, false),
ERROR_EXTERNAL_RECURSION_LIMIT("error.external.recursionLimitReached", 2, MessageType.ERROR, MessageHandler.UX, false),
ERROR_EXTERNAL_XML_NOT_READABLE("error.external.xmlNotReadable", 2, MessageType.ERROR, MessageHandler.UX, false),
ERROR_EXTERNAL_XML_NOT_PARSABLE("error.external.xmlNotParsable", 2, MessageType.ERROR, MessageHandler.UX, false);

String messageKey;
int argCount;
MessageType messageType;
MessageHandler messageHandler;
boolean verbose;//true: only when verbose is true, false: ignores verbose flag and always prints
ERROR_EXTERNAL_XML_NOT_PARSABLE("error.external.xmlNotParsable", 2, MessageType.ERROR, MessageHandler.UX, false),
WARNING_MULTIPLE_METHOD_TARGET_MATCHES("warning.multipleMethodTargetMatches", 3, MessageType.WARNING, MessageHandler.UX, false),
WARNING_NO_METHOD_TARGET_MATCHES("warning.noMethodTargetMatches", 2, MessageType.WARNING, MessageHandler.UX, false);

final String messageKey;
final int argCount;
final MessageType messageType;
final MessageHandler messageHandler;
final boolean verbose;//true: only when verbose is true, false: ignores verbose flag and always prints

EventKey(String messageKey, int argCount, MessageType messageType, MessageHandler messageHandler, boolean verbose) {
this.messageKey = messageKey;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,25 @@
package sfdc.sfdx.scanner.messaging;
package com.salesforce.messaging;

import com.google.gson.Gson;
import static sfdc.sfdx.scanner.messaging.SfdxMessager.*;
import java.time.Instant;
import java.util.List;

public class Message {
private String messageKey;
private List<String> args;
private String internalLog;
private MessageType type;
private MessageHandler handler;
private boolean verbose;
private long time;
final private String messageKey;
final private List<String> args;
final private String internalLog;
final private MessageType type;
final private MessageHandler handler;
final private boolean verbose;
final private long time;

Message(String messageKey, List<String> args, String internalLog, MessageType type, MessageHandler handler, boolean verbose) {
this.messageKey = messageKey;
this.args = args;
this.internalLog = internalLog;
this.type = type;
this.handler = handler;
this.time = Instant.now().toEpochMilli();
this.verbose = verbose;
}

String toJson() {
return new Gson().toJson(this);
this.time = Instant.now().toEpochMilli();
}

public String getMessageKey() {
Expand All @@ -40,4 +34,14 @@ public String getInternalLog() {
return internalLog;
}

enum MessageHandler {
UX,
INTERNAL
}

enum MessageType {
INFO,
WARNING,
ERROR
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
package sfdc.sfdx.scanner.messaging;
package com.salesforce.messaging;

import com.google.common.base.Throwables;
import sfdc.sfdx.scanner.messaging.EventKey;

import java.util.Arrays;

/**
* Internal exception representation.
* Extends RuntimeException to avoid declaring everywhere
* Handles capability to plug into SfdxMessager
* Handles capability to plug into CliMessager
*/
public class SfdxScannerException extends RuntimeException {
public class MessagePassableException extends RuntimeException {

private final EventKey eventKey;
private final String[] args;

public SfdxScannerException(EventKey eventKey, String... args) {
public MessagePassableException(EventKey eventKey, String... args) {
this(eventKey, null, args);
}

public SfdxScannerException(EventKey eventKey, Throwable throwable, String... args) {
public MessagePassableException(EventKey eventKey, Throwable throwable, String... args) {
super(throwable);

this.eventKey = eventKey;
Expand All @@ -40,7 +39,7 @@ public String getFullStacktrace() {

@Override
public String toString() {
return "SfdxScannerException{" +
return "MessagePassableException{" +
"eventKey=" + eventKey +
", args=" + Arrays.toString(args) +
'}';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package sfdc.sfdx.scanner.messaging;
package com.salesforce.messaging;

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
Expand All @@ -12,7 +12,7 @@
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import static sfdc.sfdx.scanner.messaging.SfdxMessager.*;
import static com.salesforce.messaging.Message.*;

import java.io.IOException;
import java.nio.file.Files;
Expand Down
2 changes: 2 additions & 0 deletions messages/EventKeyTemplates.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ module.exports = {
"pmdSkippedFile": "PMD failed to evaluate against file '%s'. Message: %s",
"pmdSuppressedViolation": "PMD suppressed violation against file '%s'. Message: %s. Suppression Type: %s. User Message: %s",
"unexpectedPmdNodeType": "Encountered unexpected PMD node of type '%s'",
"multipleMethodTargetMatches": "Total of %s methods in file %s matched name #%s",
"noMethodTargetMatches": "No methods in file %s matched name #%s()",
"pmdConfigError": "PMD failed to evaluate rule '%s'. Message: %s"
},
"error": {
Expand Down
7 changes: 6 additions & 1 deletion messages/run-dfa.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ module.exports = {
"sevthresholdDescription": "throws an error when violations of specific severity (or more severe) are detected, invokes --normalize-severity",
"sevthresholdDescriptionLong": "Throws an error if violations are found with equal or greater severity than provided value. Values are 1 (high), 2 (moderate), and 3 (low). Exit code is the most severe violation. Using this flag also invokes the --normalize-severity flag",
"targetDescription": "location of source code",
"targetDescriptionLong": "Source code location. May use glob patterns. Multiple values can be specified as a comma-separated list"
"targetDescriptionLong": "Source code location. May use glob patterns, or specify individual methods with #-syntax. Multiple values can be specified as a comma-separated list"
},
"validations": {
"methodLevelTargetCannotBeGlob": "Method-level targets supplied to --target cannot be globs",
"methodLevelTargetMustBeRealFile": "Method-level target %s must be a real file",
"projectdirCannotBeGlob": "--projectdir cannot specify globs",
"projectdirMustBeDir": "--projectdir must specify directories",
"projectdirMustExist": "--projectdir must specify existing paths"
Expand All @@ -37,6 +39,9 @@ module.exports = {
Unix example: $ sfdx scanner:run:dfa --target './**/*.cls,!./**/IgnoreMe.cls' ...
Windows example: > sfdx scanner:run:dfa --target ".\\**\\*.cls,!.\\**\\IgnoreMe.cls" ...
Evaluate rules against all .cls files below the current directory, except for IgnoreMe.cls.
Individual methods within a file may be targeted by suffixing the file's path with a hash (#), and a semi-colon-delimited list of method names. This syntax is incompatible with globs and directories.
E.g., $ sfdx scanner:run:dfa --target "./File1.cls#Method1;Method2,./File2.cls#Method3" ...
Evaluates rules against ALL methods named Method1 or Method2 in File1.cls, and ALL methods named Method3 in File2.cls.
Use --normalize-severity to output a normalized (across all engines) severity (1 [high], 2 [moderate], and 3 [low]) in addition to the engine specific severity (when shown).
E.g., $ sfdx scanner:run:dfa --target "/some-project/" --projectdir "/some-project/" --format csv --normalize-severity
Use --severity-threshold to throw a non-zero exit code when rule violations of a specific normalized severity (or greater) are found. For this example, if there are any rule violations with a severity of 2 or more (which includes 1-high and 2-moderate), the exit code will be equal to the severity of the most severe violation.
Expand Down
6 changes: 5 additions & 1 deletion messages/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ module.exports = {
'eslintConfigDescription': 'location of eslintrc config to customize eslint engine',
'eslintConfigDescriptionLong': 'Location of eslintrc to customize eslint engine',
'pmdConfigDescription': 'location of PMD rule reference XML file to customize rule selection',
'pmdConfigDescriptionLong': 'Location of PMD rule reference XML file to customize rule selection'
'pmdConfigDescriptionLong': 'Location of PMD rule reference XML file to customize rule selection',
"verboseViolationsDescription": "retire-js violation messages include more details",
"verboseViolationsDescriptionLong": "retire-js violation messages contain details about each vulnerability (e.g. summary, CVE, urls, etc.)"

},
"validations": {
"methodLevelTargetingDisallowed": "Target '%s' is invalid, as this command does not support method-level targeting",
"outfileFormatMismatch": "Your chosen format %s does not appear to match your output file type of %s.",
"outfileMustBeValid": "--outfile must be a well-formed filepath.",
"outfileMustBeSupportedType": "--outfile must be of a supported type. Current options are: .csv; .xml; .json; .html; .sarif.",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@salesforce/sfdx-scanner",
"description": "Static code scanner that applies quality and security rules to Apex code, and provides feedback.",
"version": "3.1.2",
"version": "3.2.0",
"author": "ISV SWAT",
"bugs": "https://github.com/forcedotcom/sfdx-scanner/issues",
"dependencies": {
Expand Down
1 change: 1 addition & 0 deletions pmd-cataloger/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ tasks.register<Copy>("installPmd") {
}

dependencies {
implementation(project(":cli-messaging"))
implementation ("com.googlecode.json-simple:json-simple:1.1.1") {
exclude("junit")
}
Expand Down
2 changes: 0 additions & 2 deletions pmd-cataloger/settings.gradle.kts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package sfdc.sfdx.scanner.pmd;

import sfdc.sfdx.scanner.messaging.EventKey;
import sfdc.sfdx.scanner.messaging.SfdxMessager;
import sfdc.sfdx.scanner.messaging.SfdxScannerException;
import com.salesforce.messaging.EventKey;
import com.salesforce.messaging.CliMessager;
import com.salesforce.messaging.MessagePassableException;

import java.util.*;

Expand Down Expand Up @@ -57,7 +57,7 @@ private void addPathForLanguage(String path, String language, String sourceJar)
addCategoryPathForLanguage(path, language, sourceJar);
categoryToSourceJar.put(path, sourceJar);
} else {
SfdxMessager.getInstance().addMessage("Adding path " + path + " for language " + language, EventKey.WARNING_XML_DROPPED, path);
CliMessager.getInstance().addMessage("Adding path " + path + " for language " + language, EventKey.WARNING_XML_DROPPED, path);
}
}
}
Expand All @@ -81,7 +81,7 @@ private void addPath(String path, String language, String sourceJar, Map<String,
}

if (jarWithConflict != null) {
throw new SfdxScannerException(EventKey.ERROR_EXTERNAL_DUPLICATE_XML_PATH, path, sourceJar, jarWithConflict);
throw new MessagePassableException(EventKey.ERROR_EXTERNAL_DUPLICATE_XML_PATH, path, sourceJar, jarWithConflict);
}

if (pathsByLanguage.containsKey(language)) {
Expand Down
Loading