Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

prettier-plugin-apex

Package Overview
Dependencies
Maintainers
2
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prettier-plugin-apex - npm Package Compare versions

Comparing version 1.0.0-alpha.9 to 1.0.0-beta.1

src/constants.js

35

CHANGELOG.md
## Unreleased
## 1.0.0-beta.1
- Add support for Anonymous Code block with `--apex-anonymous` option.
- CLI/Option change:
- `use-standalone-server` option is now `apex-standalone-parser`,
and it is now a choice between `none` and `built-in`.
- `server-port` option is now `apex-standalone-port`.
- Add `apex-verify-ast` option.
- Fix dangling comments being printed incorrectly for Triggers ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/13)).
Thanks to @praksb, @ntotten and @vazexqi for their help on getting jorje fixed.
- Fix SOQL unary expression not generating space before next expression.
- Add support for SOQL WHERE Calculation Expression ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/34)).
- Add support for parameter modifiers ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/37)).
- Add support for `while` loop without body ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/33)).
- Add support for `for` loop without body ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/36)).
- Add support for Java expressions/typerefs ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/35)).
- Fix Package Version Expression.
- Fix Unicode characters being printed incorrectly ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/51)).
- Workaround for certain cases of AST verification failing ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/38)).
- Fix overlapping node with comment when comment contains special characters.
- Fix awkward breaks for long method call chain ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/53)),
- Remove breaks in Map types ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/57)).
- Fix binary/boolean expressions breaking after operation despite available space ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/40)).
- Fix leading comment to SOQL inner query being misindentified as trailing comment to previous column clause ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/58)).
- Fix awkward breaks for multiline binaryish expressions ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/21)).
- Fix formatting for Apex types containing expressions but do not add groups and/or breaks.
- Fix SOQL/SOSL boolean expressions having extra parentheses ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/56)).
- Fix ternary expressions not breaking correctly ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/29)).
- Fix comments not being indented in binaryish expressions ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/14)).
- Fix array index indentation surrounding variable expressions and method call expressions.
- Fix unstable IfBlock trailing comments.
- Fix unstable NameValueParameter trailing comments.
- Fix unstable WhereOpExpr trailing comments.
## 1.0.0-alpha.9
- Fix trailing comments after class names not being printed ([issue](https://github.com/dangmai/prettier-plugin-apex/issues/20)).

@@ -3,0 +38,0 @@ - Add new lines in empty blocks for Enum.

5

package.json
{
"name": "prettier-plugin-apex",
"version": "1.0.0-alpha.9",
"version": "1.0.0-beta.1",
"description": "Salesforce Apex plugin for Prettier",

@@ -18,2 +18,3 @@ "main": "src/index.js",

"scripts": {
"coverage": "codecov",
"pretest": "npm run lint",

@@ -23,3 +24,2 @@ "test": "jest",

"stop-server": "node bin/stop-apex-server.js",
"execute": "node src/execute.js",
"lint": "eslint \"{src,tests_config}/**/*.js\"",

@@ -35,2 +35,3 @@ "prettier": "prettier --write \"{src,tests_config}/**/*.js\""

"devDependencies": {
"codecov": "^3.5.0",
"eslint": "^5.15.1",

@@ -37,0 +38,0 @@ "eslint-config-airbnb-base": "^13.1.0",

40

README.md

@@ -1,2 +0,2 @@

# Prettier Apex [![Build Status](https://travis-ci.org/dangmai/prettier-plugin-apex.svg)](https://travis-ci.org/dangmai/prettier-plugin-apex) [![npm](https://img.shields.io/npm/v/prettier-plugin-apex.svg)](https://www.npmjs.com/package/prettier-plugin-apex)
# Prettier Apex [![Build Status](https://travis-ci.org/dangmai/prettier-plugin-apex.svg)](https://travis-ci.org/dangmai/prettier-plugin-apex) [![npm](https://img.shields.io/npm/v/prettier-plugin-apex.svg)](https://www.npmjs.com/package/prettier-plugin-apex) [![codecov](https://codecov.io/gh/dangmai/prettier-plugin-apex/branch/master/graph/badge.svg)](https://codecov.io/gh/dangmai/prettier-plugin-apex) [![Join the chat at https://gitter.im/prettier-plugin-apex/community](https://badges.gitter.im/prettier-plugin-apex/community.svg)](https://gitter.im/prettier-plugin-apex/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

@@ -60,2 +60,38 @@ ![Prettier Banner](https://raw.githubusercontent.com/prettier/prettier-logo/master/images/prettier-banner-light.png)

### Tip
#### Initial run
If you are formatting a big code base for the first time,
please make sure that you have some form of version control in place,
so that you can revert any change if necessary.
You should also run Prettier with the `--apex-verify-ast` argument. For example:
```bash
prettier --write "/path/to/project/**/*.{trigger,cls}" --apex-verify-ast
```
This will guarantee that the behavior of your code did not change because of
the format.
Note that this argument does degrade performance, so after the initial commit
feel free to stop using it in your day to day operation, provided that you only
format a small amount of code each time (for example, on a file save).
#### Anonymous Apex
You can also format anonymous Apex with this program by using the
`--apex-anonymous` flag.
For example:
```bash
prettier --write "/path/to/project/anonymous/**/*.cls" --apex-anonymous
```
Note that Prettier will treat any Apex file that it finds using the glob above
as anonymous code blocks,
so it is recommended that you collect all of your anonymous Apex files into
one directory and limit the use of `--apex-anonymous` only in that directory.
### Configuration

@@ -103,3 +139,3 @@

# In a separate console
prettier --use-standalone-server --write "/path/to/project/**/*.{trigger,cls}"
prettier --apex-standalone-parser built-in --write "/path/to/project/**/*.{trigger,cls}"

@@ -106,0 +142,0 @@ # After you are done, stop the server (if installed globally)

@@ -10,5 +10,5 @@ /* eslint no-param-reassign: 0, no-plusplus: 0, no-else-return: 0, consistent-return: 0 */

const childNodesCacheKey = require("private").makeUniqueKey();
const values = require("./values");
const constants = require("./constants");
const apexNames = values.APEX_NAMES;
const apexTypes = constants.APEX_TYPES;

@@ -52,7 +52,7 @@ function getSortedChildNodes(node, resultArray) {

// that difference.
if (ast[apexNames.PARSER_OUTPUT].unit.loc) {
return ast[apexNames.PARSER_OUTPUT].unit.loc;
if (ast[apexTypes.PARSER_OUTPUT].unit.loc) {
return ast[apexTypes.PARSER_OUTPUT].unit.loc;
}
if (ast[apexNames.PARSER_OUTPUT].unit.body.loc) {
return ast[apexNames.PARSER_OUTPUT].unit.body.loc;
if (ast[apexTypes.PARSER_OUTPUT].unit.body.loc) {
return ast[apexTypes.PARSER_OUTPUT].unit.body.loc;
}

@@ -68,3 +68,3 @@ throw new Error(

if (comment.location.endIndex < getRootNodeLocation(ast).startIndex) {
comment.followingNode = ast[apexNames.PARSER_OUTPUT].unit;
comment.followingNode = ast[apexTypes.PARSER_OUTPUT].unit;
return;

@@ -94,6 +94,6 @@ }

const declarationUnits = [
apexNames.CLASS_DECLARATION,
apexNames.TRIGGER_DECLARATION_UNIT,
apexNames.ENUM_DECLARATION,
apexNames.INTERFACE_DECLARATION,
apexTypes.CLASS_DECLARATION,
apexTypes.TRIGGER_DECLARATION_UNIT,
apexTypes.ENUM_DECLARATION,
apexTypes.INTERFACE_DECLARATION,
];

@@ -226,8 +226,8 @@ if (

function attach(ast, sourceCode) {
const comments = ast[apexNames.PARSER_OUTPUT].hiddenTokenMap
const comments = ast[apexTypes.PARSER_OUTPUT].hiddenTokenMap
.map(item => item[1])
.filter(
item =>
item["@class"] === apexNames.INLINE_COMMENT ||
item["@class"] === apexNames.BLOCK_COMMENT,
item["@class"] === apexTypes.INLINE_COMMENT ||
item["@class"] === apexTypes.BLOCK_COMMENT,
);

@@ -237,3 +237,3 @@ const tiesToBreak = [];

comments.forEach(comment => {
decorateComment(ast[apexNames.PARSER_OUTPUT].unit, comment, ast);
decorateComment(ast[apexTypes.PARSER_OUTPUT], comment, ast);

@@ -261,3 +261,3 @@ const pn = comment.precedingNode;

} else if (pn) {
if (en && en["@class"] === apexNames.BLOCK_STATEMENT && !fn) {
if (en && en["@class"] === apexTypes.BLOCK_STATEMENT && !fn) {
// Special case: this is a trailing comment in a block statement

@@ -350,6 +350,6 @@ breakTies(tiesToBreak, sourceCode);

// from prettier to buffer the output
if (comment["@class"] === apexNames.INLINE_COMMENT) {
if (comment["@class"] === apexTypes.INLINE_COMMENT) {
if (
(leadingSpace.length > 0 && numberOfNewLines === 0) ||
parentNode["@class"] === apexNames.LOCATION_IDENTIFIER
parentNode["@class"] === apexTypes.LOCATION_IDENTIFIER
) {

@@ -393,3 +393,3 @@ parts.push(lineSuffix(concat([" ", print(commentPath)])));

}
if (comment["@class"] === apexNames.INLINE_COMMENT) {
if (comment["@class"] === apexTypes.INLINE_COMMENT) {
parts.push(lineSuffix(print(commentPath)));

@@ -403,11 +403,5 @@ } else {

function allowTrailingComments(apexClass) {
const allowedTypes = [
apexNames.CLASS_DECLARATION,
apexNames.INTERFACE_DECLARATION,
apexNames.METHOD_DECLARATION,
apexNames.ENUM_DECLARATION,
apexNames.VARIABLE_DECLARATION,
apexNames.LOCATION_IDENTIFIER,
];
let trailingCommentsAllowed = allowedTypes.includes(apexClass);
let trailingCommentsAllowed = constants.ALLOW_TRAILING_COMMENT.includes(
apexClass,
);
const separatorIndex = apexClass.indexOf("$");

@@ -417,3 +411,3 @@ if (separatorIndex !== -1) {

trailingCommentsAllowed =
trailingCommentsAllowed || parentClass === apexNames.STATEMENT;
trailingCommentsAllowed || parentClass === apexTypes.STATEMENT;
}

@@ -444,3 +438,3 @@ return trailingCommentsAllowed;

allowTrailingComments(value["@class"]) ||
comment["@class"] === apexNames.BLOCK_COMMENT
comment["@class"] === apexTypes.BLOCK_COMMENT
))

@@ -447,0 +441,0 @@ ) {

const parse = require("./parser");
const print = require("./printer");
const { massageAstNode } = require("./util");

@@ -31,2 +32,3 @@ const languages = [

locEnd,
preprocess: text => text.trim(),
},

@@ -38,2 +40,3 @@ };

print,
massageAstNode,
},

@@ -43,10 +46,20 @@ };

const options = {
useStandaloneServer: {
type: "boolean",
apexStandaloneParser: {
type: "choice",
category: "Global",
default: false,
default: "none",
choices: [
{
value: "none",
description: "Do not use a standalone parser",
},
{
value: "built-in",
description: "Use the built in standalone parser",
},
],
description:
"Use a standalone server to speed up the parsing process. This server needs to be started and stopped separately from the Prettier process",
"Use a standalone process to speed up parsing. This process needs to be started and stopped separately from the Prettier process",
},
serverPort: {
apexStandalonePort: {
type: "int",

@@ -56,4 +69,17 @@ category: "Global",

description:
"The standalone server port to connect to. Only applicable if useStandaloneServer is true",
"The standalone server port to connect to. Only applicable if apexStandaloneParser is true",
},
apexVerifyAst: {
type: "boolean",
category: "Global",
default: false,
description:
"Verify that the abstract syntax trees for the formatted code is the same as the unformatted code. This heavily degrades performance, but is recommended for initial runs on big code bases",
},
apexAnonymous: {
type: "boolean",
category: "Global",
default: false,
description: "Treat the code as anonymous Apex",
},
};

@@ -60,0 +86,0 @@

@@ -9,5 +9,10 @@ const { argv } = require("yargs");

port: argv.p || 2113,
anonymous: argv.n || false,
};
const args = ["-f", "json", "-i"];
if (options.anonymous) {
args.push("-a");
delete options.anonymous;
}

@@ -14,0 +19,0 @@ const nail = nailgunClient.exec("net.dangmai.serializer.Apex", args, options);

@@ -8,7 +8,8 @@ /* eslint no-param-reassign: 0 no-underscore-dangle: 0 */

const attachComments = require("./comments").attach;
const values = require("./values");
const constants = require("./constants");
const { findNextUncommentedCharacter } = require("./util");
const apexNames = values.APEX_NAMES;
const apexTypes = constants.APEX_TYPES;
function parseTextWithSpawn(text) {
function parseTextWithSpawn(text, anonymous) {
let serializerBin = path.join(__dirname, "../vendor/apex-ast-serializer/bin");

@@ -20,3 +21,7 @@ if (process.platform === "win32") {

}
const executionResult = spawnSync(serializerBin, ["-f", "json", "-i"], {
const args = ["-f", "json", "-i"];
if (anonymous) {
args.push("-a");
}
const executionResult = spawnSync(serializerBin, args, {
input: text,

@@ -34,5 +39,8 @@ });

function parseTextWithNailgun(text, serverPort) {
function parseTextWithNailgun(text, serverPort, anonymous) {
const ngClientLocation = path.join(__dirname, "ng-client.js");
const args = [ngClientLocation, "-a", "localhost", "-p", serverPort];
if (anonymous) {
args.push("-n");
}
const executionResult = childProcess.spawnSync(process.argv[0], args, {

@@ -83,14 +91,98 @@ input: text,

function handleInnerQueryLocation(location, sourceCode, commentNodes) {
const resultLocation = {};
resultLocation.startIndex = findNextUncommentedCharacter(
sourceCode,
"(",
location.startIndex,
commentNodes,
/* backwards */ true,
);
resultLocation.endIndex = findNextUncommentedCharacter(
sourceCode,
")",
location.startIndex,
commentNodes,
/* backwards */ false,
);
return resultLocation;
}
function handleNodeEndedWithCharacter(endCharacter) {
return (location, sourceCode, commentNodes) => {
const resultLocation = {};
resultLocation.startIndex = location.startIndex;
resultLocation.endIndex = findNextUncommentedCharacter(
sourceCode,
endCharacter,
location.endIndex,
commentNodes,
/* backwards */ false,
);
return resultLocation;
};
}
function handleAnonymousUnitLocation(location, sourceCode) {
return {
startIndex: 0,
endIndex: sourceCode.length,
};
}
// We need to generate the location for a node differently based on the node
// type. This object holds a String => Function mapping in order to do that.
const locationGenerationHandler = {};
const identityFunction = location => location;
locationGenerationHandler[apexTypes.QUERY] = identityFunction;
locationGenerationHandler[apexTypes.VARIABLE_EXPRESSION] = identityFunction;
locationGenerationHandler[apexTypes.INNER_CLASS_MEMBER] = identityFunction;
locationGenerationHandler[apexTypes.INNER_INTERFACE_MEMBER] = identityFunction;
locationGenerationHandler[apexTypes.INNER_ENUM_MEMBER] = identityFunction;
locationGenerationHandler[apexTypes.METHOD_MEMBER] = identityFunction;
locationGenerationHandler[apexTypes.IF_ELSE_BLOCK] = identityFunction;
locationGenerationHandler[apexTypes.NAME_VALUE_PARAMETER] = identityFunction;
locationGenerationHandler[
apexTypes.WHERE_OPERATION_EXPRESSION
] = identityFunction;
locationGenerationHandler[
apexTypes.SELECT_INNER_QUERY
] = handleInnerQueryLocation;
locationGenerationHandler[
apexTypes.ANONYMOUS_BLOCK_UNIT
] = handleAnonymousUnitLocation;
locationGenerationHandler[
apexTypes.PROPERTY_MEMBER
] = handleNodeEndedWithCharacter("}");
locationGenerationHandler[
apexTypes.SWITCH_STATEMENT
] = handleNodeEndedWithCharacter("}");
locationGenerationHandler[
apexTypes.VARIABLE_DECLARATION_STATEMENT
] = handleNodeEndedWithCharacter(";");
locationGenerationHandler[
apexTypes.FIELD_MEMBER
] = handleNodeEndedWithCharacter(";");
locationGenerationHandler[
apexTypes.NEW_KEY_VALUE
] = handleNodeEndedWithCharacter(")");
locationGenerationHandler[apexTypes.QUERY] = handleNodeEndedWithCharacter("]");
/**
* Sometimes jorje lies about a node location, so we will fix it here before
* using that information. We do it by enforcing that a parent node start
* Generate and/or fix node locations, because jorje sometimes either provides
* wrong location information or a node, or doesn't provide any information at
* all.
* We will fix it here by enforcing that a parent node start
* index is always <= any child node start index, and a parent node end index
* is always >= any child node end index.
* @param node the node being visited.
* @param sourceCode the entire source code.
* @param commentNodes all the comment nodes.
* @return the corrected node.
*/
function fixNodeLocation(node) {
function handleNodeLocation(node, sourceCode, commentNodes) {
let currentLocation;
Object.keys(node).forEach(key => {
if (typeof node[key] === "object") {
const location = fixNodeLocation(node[key]);
const location = handleNodeLocation(node[key], sourceCode, commentNodes);
if (location && currentLocation) {

@@ -109,2 +201,11 @@ if (currentLocation.startIndex > location.startIndex) {

});
const apexClass = node["@class"];
if (apexClass && apexClass in locationGenerationHandler && currentLocation) {
node.loc = locationGenerationHandler[apexClass](
currentLocation,
sourceCode,
commentNodes,
);
}
if (node.loc && currentLocation) {

@@ -123,3 +224,3 @@ if (node.loc.startIndex > currentLocation.startIndex) {

if (currentLocation) {
return currentLocation;
return Object.assign({}, currentLocation);
}

@@ -136,36 +237,2 @@ if (node.loc) {

/**
* Certain node types do not get their endIndex reported from the jorje compiler,
* or the number they report is not the end of the entire block,
* so we'll have to figure it out by hand here.
* This method mutates the node that was passed in, and assumes that `lastNodeLoc`
* is set on it.
* @param node the node to look at
* @param sourceCode the entire source code
* @param lineIndexes the indexes of the lines
*/
function generateEndIndexForNode(node, sourceCode, lineIndexes) {
switch (node["@class"]) {
case apexNames.PROPERTY_MEMBER:
case apexNames.SWITCH_STATEMENT:
node.lastNodeLoc.endIndex = sourceCode.indexOf(
"}",
node.lastNodeLoc.endIndex,
);
node.lastNodeLoc.endLine =
lineIndexes.findIndex(index => index > node.lastNodeLoc.endIndex) - 1;
break;
case apexNames.VARIABLE_DECLARATION_STATEMENT:
node.lastNodeLoc.endIndex = sourceCode.indexOf(
";",
node.lastNodeLoc.endIndex,
);
node.lastNodeLoc.endLine =
lineIndexes.findIndex(index => index > node.lastNodeLoc.endIndex) - 1;
break;
default:
}
return node;
}
/**
* Generate metadata about empty lines for statement nodes.

@@ -175,9 +242,3 @@ * This method is called recursively while visiting each node in the tree.

* @param node the node being visited
* @param sourceCode the entire source code
* @param lineIndexes the indexes of the lines in the source code
* @param emptyLineLocations a list of lines that are empty in the source code
* @param emptyLineNodeMap a map of empty line to the node that is attached to
* that line. Usually it is the statement right before it; however for certain
* node type (e.g. IfElseBlock) that contains BlockStatement, it'll be the
* outermost node (e.g. IfElseBlock instead of BlockStatement)
* @param allowTrailingEmptyLine whether trailing empty line is allowed

@@ -191,6 +252,3 @@ * for this node. This helps when dealing with statements that contain other

node,
sourceCode,
lineIndexes,
emptyLineLocations,
emptyLineNodeMap,
allowTrailingEmptyLine,

@@ -200,6 +258,6 @@ ) {

let allowTrailingEmptyLineWithin;
const isSpecialClass = values.TRAILING_EMPTY_LINE_AFTER_LAST_NODE.includes(
const isSpecialClass = constants.TRAILING_EMPTY_LINE_AFTER_LAST_NODE.includes(
apexClass,
);
const trailingEmptyLineAllowed = values.ALLOW_TRAILING_EMPTY_LINE.includes(
const trailingEmptyLineAllowed = constants.ALLOW_TRAILING_EMPTY_LINE.includes(
apexClass,

@@ -214,3 +272,2 @@ );

}
let lastNodeLoc;
Object.keys(node).forEach(key => {

@@ -221,74 +278,63 @@ if (typeof node[key] === "object") {

}
const nodeLoc = generateExtraMetadata(
generateExtraMetadata(
node[key],
sourceCode,
lineIndexes,
emptyLineLocations,
emptyLineNodeMap,
allowTrailingEmptyLineWithin,
);
if (
nodeLoc &&
(!lastNodeLoc || nodeLoc.endIndex > lastNodeLoc.endIndex)
) {
// This might not be the same node that `isLastNodeInArray` refers to,
// since this searches for node in child objects instead of just child
// arrays
lastNodeLoc = nodeLoc;
} else if (!nodeLoc && !lastNodeLoc) {
lastNodeLoc = _getNodeLocation(node);
}
}
});
if (isSpecialClass && lastNodeLoc) {
// Store the last node information for some special node types, so that
// we can add trailing empty lines after them.
node.lastNodeLoc = lastNodeLoc;
generateEndIndexForNode(node, sourceCode, lineIndexes);
}
const nodeLoc = _getNodeLocation(node);
if (
apexClass &&
(nodeLoc || node.lastNodeLoc) &&
nodeLoc &&
allowTrailingEmptyLine &&
!node.isLastNodeInArray
) {
// There's a chance that multiple statements exist on 1 line,
// so we only want to tag one of them as having a trailing empty line.
// We do that by applying the trailing empty line only after the last node.
// e.g. `if (a === 1) {} else {}\n\n`,the empty line should be applied
// after the `else`, not the `if`. We keep track of which
// nodes have trailingEmptyLine turned on for a certain line, then turn
// it off for all but the last one.
const nextLine = isSpecialClass
? node.lastNodeLoc.endLine + 1
: nodeLoc.endLine + 1;
const nextLine = nodeLoc.endLine + 1;
const nextEmptyLine = emptyLineLocations.indexOf(nextLine);
if (trailingEmptyLineAllowed && nextEmptyLine !== -1) {
node.trailingEmptyLine = true;
}
}
return nodeLoc;
}
if (emptyLineNodeMap[nextLine]) {
const nodeMapEndIndex = emptyLineNodeMap[nextLine].lastNodeLoc
? emptyLineNodeMap[nextLine].lastNodeLoc.endIndex
: _getNodeLocation(emptyLineNodeMap[nextLine]).endIndex;
const thisEndIndex = node.lastNodeLoc
? node.lastNodeLoc.endIndex
: nodeLoc.endIndex;
if (nodeMapEndIndex > thisEndIndex) {
node.trailingEmptyLine = false;
/**
* jorje sometimes gives us different ASTs depending on the white spaces
* between keywords (#38), which makes it very difficult to know how many
* nested expressions there are in a method call or a variable expression.
* This method is used to calculate that number.
* After this method is called on a node that contains a `dottedExpr`,
* that node will contain a `numberOfDottedExpressions` property.
* @param node the current node being visited.
*/
function generateDottedExpressionMetadata(node) {
Object.keys(node).forEach(key => {
if (typeof node[key] === "object") {
node[key] = generateDottedExpressionMetadata(node[key]);
}
if (key === "dottedExpr") {
node.numberOfDottedExpressions = 1;
if (node.names) {
node.numberOfDottedExpressions = node.names.length;
}
if (node.dottedExpr && node.dottedExpr.value) {
if (node.dottedExpr.value.numberOfDottedExpressions) {
node.numberOfDottedExpressions +=
node.dottedExpr.value.numberOfDottedExpressions;
} else if (
node.dottedExpr.value["@class"] === apexTypes.ARRAY_EXPRESSION &&
node.dottedExpr.value.expr.numberOfDottedExpressions
) {
node.numberOfDottedExpressions +=
node.dottedExpr.value.expr.numberOfDottedExpressions;
} else {
emptyLineNodeMap[nextLine].trailingEmptyLine = false;
emptyLineNodeMap[nextLine] = node;
node.numberOfDottedExpressions += 1;
}
} else {
emptyLineNodeMap[nextLine] = node;
}
}
}
if (lastNodeLoc) {
return lastNodeLoc;
}
return nodeLoc;
});
return node;
}

@@ -302,3 +348,9 @@

const nodeLoc = _getNodeLocation(node);
if (nodeLoc) {
if (nodeLoc && !("startLine" in nodeLoc)) {
// The location node that we manually generate do not contain startLine
// information, so we will create them here.
nodeLoc.startLine =
lineIndexes.findIndex(index => index > nodeLoc.startIndex) - 1;
}
if (nodeLoc && !("endLine" in nodeLoc)) {
nodeLoc.endLine =

@@ -311,5 +363,10 @@ lineIndexes.findIndex(index => index > nodeLoc.endIndex) - 1;

}
// Edge case: Trigger Declaration Unit.
// Somehow jorje thinks this node ends after the word `trigger`.
}
if (nodeLoc && !("column" in nodeLoc)) {
nodeLoc.column =
nodeLoc.startIndex -
lineIndexes[
lineIndexes.findIndex(index => index > nodeLoc.startIndex) - 1
];
}
Object.keys(node).forEach(key => {

@@ -357,9 +414,12 @@ if (typeof node[key] === "object") {

function parse(sourceCode, _, options) {
sourceCode = sourceCode.trim();
const lineIndexes = getLineIndexes(sourceCode);
let serializedAst;
if (options.useStandaloneServer) {
serializedAst = parseTextWithNailgun(sourceCode, options.serverPort);
if (options.apexStandaloneParser === "built-in") {
serializedAst = parseTextWithNailgun(
sourceCode,
options.apexStandalonePort,
options.apexAnonymous,
);
} else {
serializedAst = parseTextWithSpawn(sourceCode);
serializedAst = parseTextWithSpawn(sourceCode, options.apexAnonymous);
}

@@ -370,6 +430,6 @@ let ast = {};

if (
ast[apexNames.PARSER_OUTPUT] &&
ast[apexNames.PARSER_OUTPUT].parseErrors.length > 0
ast[apexTypes.PARSER_OUTPUT] &&
ast[apexTypes.PARSER_OUTPUT].parseErrors.length > 0
) {
const errors = ast[apexNames.PARSER_OUTPUT].parseErrors.map(
const errors = ast[apexTypes.PARSER_OUTPUT].parseErrors.map(
err => `${err.message}. ${err.detailMessage}`,

@@ -379,13 +439,15 @@ );

}
const commentNodes = ast[apexTypes.PARSER_OUTPUT].hiddenTokenMap
.map(item => item[1])
.filter(
node =>
node["@class"] === apexTypes.BLOCK_COMMENT ||
node["@class"] === apexTypes.INLINE_COMMENT,
);
ast = resolveAstReferences(ast, {});
fixNodeLocation(ast);
handleNodeLocation(ast, sourceCode, commentNodes);
ast = resolveLineIndexes(ast, lineIndexes);
generateExtraMetadata(
ast,
sourceCode,
lineIndexes,
getEmptyLineLocations(sourceCode),
{},
true,
);
ast = generateDottedExpressionMetadata(ast);
generateExtraMetadata(ast, getEmptyLineLocations(sourceCode), true);
attachComments(ast, sourceCode);

@@ -392,0 +454,0 @@ }

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc