Skip to content

Commit 9d372b9

Browse files
authored
NEW (SFGE) @W-17015698@ Refactored CliMessaging submodule (#220)
1 parent 8e5a175 commit 9d372b9

File tree

20 files changed

+355
-542
lines changed

20 files changed

+355
-542
lines changed
Binary file not shown.

packages/code-analyzer-sfge-engine/sfge/src/main/java/com/salesforce/CliMessagerAppender.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import com.salesforce.config.SfgeConfigProvider;
44
import com.salesforce.messaging.CliMessager;
5-
import com.salesforce.messaging.EventKey;
5+
import com.salesforce.messaging.LogMessage.LogEventKey;
66
import java.io.Serializable;
77
import org.apache.logging.log4j.Level;
88
import org.apache.logging.log4j.core.Appender;
@@ -64,15 +64,12 @@ public void append(LogEvent event) {
6464
Level level = event.getLevel();
6565
if (Level.WARN.equals(level)) {
6666
if (this.shouldLogWarningsOnVerbose) {
67-
CliMessager.postMessage(
68-
"SFGE Warning as Info", EventKey.INFO_GENERAL, getEventMessage(event));
67+
CliMessager.postLogMessage("SFGE Warning as Debug", LogEventKey.DEBUG_GENERAL, getEventMessage(event));
6968
}
7069
} else if (Level.ERROR.equals(level)) {
71-
CliMessager.postMessage(
72-
"SFGE Error as Warning", EventKey.WARNING_GENERAL, getEventMessage(event));
70+
CliMessager.postLogMessage("SFGE Error as Warning", LogEventKey.WARNING_GENERAL, getEventMessage(event));
7371
} else if (Level.FATAL.equals(level)) {
74-
CliMessager.postMessage(
75-
"SFGE Fatal as Error", EventKey.ERROR_GENERAL, getEventMessage(event));
72+
CliMessager.postLogMessage("SFGE Fatal as Error", LogEventKey.ERROR_GENERAL, getEventMessage(event));
7673
}
7774
}
7875

packages/code-analyzer-sfge-engine/sfge/src/main/java/com/salesforce/Main.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212
import com.salesforce.exception.UnexpectedException;
1313
import com.salesforce.exception.UserActionException;
1414
import com.salesforce.graph.ops.GraphUtil;
15-
import com.salesforce.messaging.CliMessager;
1615
import com.salesforce.metainfo.MetaInfoCollector;
1716
import com.salesforce.metainfo.MetaInfoCollectorProvider;
1817
import com.salesforce.rules.AbstractRule;
1918
import com.salesforce.rules.AbstractRuleRunner;
2019
import com.salesforce.rules.RuleRunner;
2120
import com.salesforce.rules.Violation;
2221
import com.salesforce.rules.ops.ProgressListenerProvider;
22+
23+
import java.io.FileWriter;
24+
import java.io.IOException;
2325
import java.util.Arrays;
2426
import java.util.Collection;
2527
import java.util.List;
@@ -30,9 +32,9 @@
3032
/**
3133
* The main class, invoked by sfdx-scanner. The first arg should be either `catalog` or `execute`,
3234
* and determines which flow runs. <br>
33-
* For `catalog`, the second arg should be either `pathless` or `dfa`. Enabled rules matching that
34-
* type will be logged as a JSON. No meaningful environment variables exist for this flow. Exit code
35-
* 0 means success. Any other exit code means failure. <br>
35+
* For `catalog`, the second arg should be either `pathless`, `dfa`, or `all`. Enabled rules matching that
36+
* type will be written as a JSON to the file specified by the third arg. No meaningful environment variables
37+
* exist for this flow. Exit code 0 means success. Any other exit code means failure. <br>
3638
* For `execute`, the second arg should be the path to a JSON file whose contents are structured as:
3739
*
3840
* <ol>
@@ -43,6 +45,7 @@
4345
* within that file.
4446
* </ol>
4547
*
48+
* The third arg should be a file to which the results will be written as a JSON
4649
* The following exit codes are possible:
4750
*
4851
* <ol>
@@ -117,7 +120,7 @@ private int catalog(String... args) {
117120
return EXIT_WITH_INTERNAL_ERROR_NO_VIOLATIONS;
118121
}
119122
OutputFormatter formatter = new OutputFormatter();
120-
dependencies.printOutput(formatter.formatRuleJsons(rules));
123+
dependencies.writeOutput(formatter.formatRuleJsons(rules), cap.getOutfile());
121124
return EXIT_GOOD_RUN_NO_VIOLATIONS;
122125
}
123126

@@ -182,12 +185,9 @@ private int execute(String... args) {
182185
ProgressListenerProvider.get().completedAnalysis();
183186
} finally {
184187

185-
// No matter the outcome, share the results found so far
186-
dependencies.printOutput(CliMessager.getInstance().getAllMessagesWithFormatting());
187-
188188
final List<Violation> violations = result.getOrderedViolations();
189189
OutputFormatter formatter = new OutputFormatter();
190-
dependencies.printOutput(formatter.formatViolationJsons(violations));
190+
dependencies.writeOutput(formatter.formatViolationJsons(violations), eap.getOutfile());
191191

192192
// Check if any exceptions were thrown
193193
final List<Throwable> errorsThrown = result.getErrorsThrown();
@@ -260,8 +260,12 @@ void printError(String message) {
260260
System.err.println(message);
261261
}
262262

263-
void printOutput(String message) {
264-
System.out.println(message);
263+
void writeOutput(String output, String outfile) {
264+
try (FileWriter fileWriter = new FileWriter(outfile)) {
265+
fileWriter.write(output);
266+
} catch (IOException ex) {
267+
throw new RuntimeException(ex);
268+
}
265269
}
266270
}
267271
}

packages/code-analyzer-sfge-engine/sfge/src/main/java/com/salesforce/cli/CliArgParser.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,14 @@ public CLI_ACTION getCliAction(String... args) {
4343
}
4444

4545
public static class CatalogArgParser {
46-
private static final int ARG_COUNT = 2;
46+
private static final int ARG_COUNT = 3;
4747
// NOTE: This value must match the one for the RuleType enum declared in Constants.ts.
4848
private static final String PATHLESS = "pathless";
4949
// NOTE: This value must match the one for the RuleType enum declared in Constants.ts.
5050
private static final String DFA = "dfa";
5151

5252
private List<AbstractRule> selectedRules;
53+
private String outfile;
5354

5455
public CatalogArgParser() {
5556
selectedRules = new ArrayList<>();
@@ -81,19 +82,26 @@ public void parseArgs(String... args) throws RuleUtil.RuleNotFoundException {
8182
selectedRules = RuleUtil.getEnabledRules();
8283
break;
8384
}
85+
86+
outfile = args[2];
8487
}
8588

8689
public List<AbstractRule> getSelectedRules() {
8790
return selectedRules;
8891
}
92+
93+
public String getOutfile() {
94+
return outfile;
95+
}
8996
}
9097

9198
public static class ExecuteArgParser {
92-
private static int ARG_COUNT = 2;
99+
private static final int ARG_COUNT = 3;
93100

94101
private final List<String> projectDirs;
95102
private final List<RuleRunnerTarget> targets;
96103
private final List<AbstractRule> selectedRules;
104+
private String outfile;
97105

98106
private final Dependencies dependencies;
99107

@@ -129,6 +137,7 @@ public void parseArgs(String... args) {
129137
targets.addAll(input.targets);
130138
projectDirs.addAll(input.projectDirs);
131139
identifyRules(input.rulesToRun);
140+
outfile = args[2];
132141
}
133142

134143
public List<String> getProjectDirs() {
@@ -143,6 +152,10 @@ public List<AbstractRule> getSelectedRules() {
143152
return selectedRules;
144153
}
145154

155+
public String getOutfile() {
156+
return outfile;
157+
}
158+
146159
private ExecuteInput readInputFile(String fileName) {
147160
try {
148161
String inputJson = String.join("\n", readFile(fileName));

packages/code-analyzer-sfge-engine/sfge/src/main/java/com/salesforce/graph/ops/MethodUtil.java

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import com.salesforce.graph.visitor.ApexPathWalker;
2323
import com.salesforce.graph.visitor.DefaultNoOpPathVertexVisitor;
2424
import com.salesforce.messaging.CliMessager;
25-
import com.salesforce.messaging.EventKey;
25+
import com.salesforce.messaging.LogMessage;
2626
import com.salesforce.rules.AbstractRuleRunner.RuleRunnerTarget;
2727
import java.util.ArrayList;
2828
import java.util.Collections;
@@ -101,20 +101,20 @@ private static void addMessagesForTarget(RuleRunnerTarget target, List<MethodVer
101101
for (String targetMethod : target.getTargetMethods()) {
102102
Integer methodCount = methodCountByName.getOrDefault(targetMethod, 0);
103103
if (methodCount == 0) {
104-
CliMessager.getInstance()
105-
.addMessage(
106-
"Loading " + targetMethod + " vertices",
107-
EventKey.WARNING_NO_METHOD_TARGET_MATCHES,
108-
target.getTargetFile(),
109-
targetMethod);
104+
CliMessager.postLogMessage(
105+
"Loading " + targetMethod + " vertices",
106+
LogMessage.LogEventKey.WARNING_NO_METHOD_TARGET_MATCHES,
107+
target.getTargetFile(),
108+
targetMethod
109+
);
110110
} else if (methodCount > 1) {
111-
CliMessager.getInstance()
112-
.addMessage(
113-
"Loading " + targetMethod + " vertices",
114-
EventKey.WARNING_MULTIPLE_METHOD_TARGET_MATCHES,
115-
methodCount.toString(),
116-
target.getTargetFile(),
117-
targetMethod);
111+
CliMessager.postLogMessage(
112+
"Loading " + targetMethod + " vertices",
113+
LogMessage.LogEventKey.WARNING_MULTIPLE_METHOD_TARGET_MATCHES,
114+
methodCount.toString(),
115+
target.getTargetFile(),
116+
targetMethod
117+
);
118118
}
119119
}
120120
}
Lines changed: 10 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,27 @@
11
package com.salesforce.messaging;
22

3-
import java.util.ArrayList;
4-
import java.util.Arrays;
53
import java.util.List;
64

75
import com.google.common.collect.Lists;
86
import com.google.gson.Gson;
97

108
public class CliMessager {
11-
// The START string gives us something to scan for when we're processing output.
12-
private static final String START = "SF-START";
13-
// The END string lets us know when a message stops, which should prevent bugs involving multi-line output.
14-
private static final String END = "SF-END";
15-
169
private static final String REALTIME_START = "SFCA-REALTIME-START";
1710
private static final String REALTIME_END = "SFCA-REALTIME-END";
1811

19-
/* Deprecated: Don't maintain state in a class that's essentially used as a utility.*/
20-
@Deprecated
21-
private static final List<Message> MESSAGES = new ArrayList<>();
22-
23-
/**
24-
* Deprecated - switch to static invocation of {@link #postMessage(String, EventKey, String...)}
25-
*/
26-
@Deprecated
27-
public static CliMessager getInstance() {
28-
return LazyHolder.INSTANCE;
29-
}
30-
31-
/**
32-
* Add exception to pass onto Typescript layer.
33-
* Will be treated as an Error based on the properties set
34-
* in EventKey. Please make sure that EventKey is correct and is
35-
* in sync with messages/EventKeyTemplates.json
36-
*
37-
* @param exception to send to Typescript layer
38-
*/
39-
@Deprecated
40-
public void addMessage(MessagePassableException exception) {
41-
final EventKey eventKey = exception.getEventKey();
42-
addMessage(
43-
exception.getFullStacktrace(),
44-
eventKey,
45-
exception.getArgs());
46-
}
47-
48-
/**
49-
* Add message to pass onto Typescript layer.
50-
* Make sure EventKey is updated with messages/EventKeyTemplates.json
51-
* and has correct properties in the enum.
52-
*
53-
* @param internalLog Information for internal use. Will be logged but not displayed to user
54-
* @param eventKey EventKey to display to user
55-
* @param args String args passed to the EventKey to make the displayed message meaningful
56-
*/
57-
@Deprecated
58-
public void addMessage(String internalLog, EventKey eventKey, String... args) {
59-
final Message message = createMessage(internalLog, eventKey, args);
60-
MESSAGES.add(message);
61-
}
62-
63-
/**
64-
* Publish formatted stdout message to pass onto Typescript layer.
65-
* Make sure EventKey is updated with messages/EventKeyTemplates.json
66-
* and has correct properties in the enum.
67-
*
68-
* @param internalLog Information for internal use. Will be logged but not displayed to user
69-
* @param eventKey EventKey to display to user
70-
* @param args String args passed to the EventKey to make the displayed message meaningful
71-
*/
72-
public static void postMessage(String internalLog, EventKey eventKey, String... args) {
73-
final Message message = createMessage(internalLog, eventKey, args);
74-
final List<Message> messages = Lists.newArrayList(message);
12+
public static void postLogMessage(String internalLog, LogMessage.LogEventKey logEventKey, String... args) {
13+
final LogMessage logMessage = LogMessage.create(internalLog, logEventKey, args);
14+
final List<LogMessage> logMessages = Lists.newArrayList(logMessage);
7515

76-
final String messageAsJson = new Gson().toJson(messages);
77-
System.out.println(REALTIME_START + messageAsJson + REALTIME_END);
78-
}
79-
80-
private static Message createMessage(String internalLog, EventKey eventKey, String[] args) {
81-
// Developer error if eventKey was not added to exception and we'll get a bunch of NPEs
82-
assert eventKey != null : "EventKey must not be null";
83-
// Confirm that the correct number of arguments for the message has been provided
84-
// If this fails, this would be a developer error
85-
assert eventKey.getArgCount() == args.length : "EventKey expected " + eventKey.getArgCount() + " args, received " + args.length;
86-
87-
final Message message = new Message(
88-
eventKey.getMessageKey(),
89-
Arrays.asList(args),
90-
internalLog,
91-
eventKey.getMessageType(),
92-
eventKey.getMessageHandler(),
93-
eventKey.isVerbose());
94-
return message;
95-
}
96-
97-
/**
98-
* Convert all messages stored by the instance into a JSON-formatted string, enclosed in the start and end strings.
99-
* Java code can use this method to log the messages to console, and TypeScript code can seek the start and stop
100-
* strings to get an array of messages that can be deserialized.
101-
* @return
102-
*/
103-
@Deprecated
104-
public String getAllMessagesWithFormatting() {
105-
final String messagesAsJson = getMessagesAsJson();
106-
return START + messagesAsJson + END;
107-
}
108-
109-
@Deprecated
110-
private String getMessagesAsJson() {
111-
return new Gson().toJson(MESSAGES);
112-
}
113-
114-
/**
115-
* TO BE USED ONLY BY TESTS!
116-
*
117-
* @return all messages as JSON without formatting
118-
*/
119-
public String getAllMessages() {
120-
return getMessagesAsJson();
16+
final String messageAsJson = new Gson().toJson(logMessages);
17+
System.out.println(REALTIME_START + messageAsJson + REALTIME_END);
12118
}
12219

123-
/**
124-
* TO BE USED ONLY BY TESTS!
125-
* STAY AWAY!!
126-
*/
127-
public void resetMessages() {
128-
MESSAGES.clear();
129-
}
20+
public static void postProgressMessage(String internalLog, ProgressMessage.ProgressEventKey progressEventKey, int progressPercent, String... args) {
21+
final ProgressMessage progressMessage = ProgressMessage.create(internalLog, progressEventKey, progressPercent, args);
22+
final List<ProgressMessage> progressMessages = Lists.newArrayList(progressMessage);
13023

131-
private static final class LazyHolder {
132-
// Postpone initialization until first use
133-
private static final CliMessager INSTANCE = new CliMessager();
24+
final String messageAsJson = new Gson().toJson(progressMessages);
25+
System.out.println(REALTIME_START + messageAsJson + REALTIME_END);
13426
}
13527
}

0 commit comments

Comments
 (0)