JSDoc type added in `src/common/util.js` (#6788)
* JSDoc type added in `src/common/util.js` * skip can return false * Add TBD for false - 1 not allowed * Define typedef SkipOptions * Use method generic for node param * Define node param for setLocStart and setLocEnd * Copy idx param to local variable * Add @returns false * Update Utility functions docs * hasNewline param index: allow only number * Add condition * Add function keyword to docs * Add prettier-ignore * Improve condition * Remove TBD comment * Use single quotes * Add type to oldIndex * Use singleline JSDocsmaster
parent
65563e0a55
commit
f059d7a31b
|
@ -228,28 +228,31 @@ defaultOptions: {
|
|||
|
||||
A `util` module from Prettier core is considered a private API and is not meant to be consumed by plugins. Instead, the `util-shared` module provides the following limited set of utility functions for plugins:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```ts
|
||||
getMaxContinuousCount(str: string, target: string): number;
|
||||
getStringWidth(text: string): number;
|
||||
getAlignmentSize(value: string, tabWidth: number, startIndex: number): number;
|
||||
getIndentSize(value: string, tabWidth: number): number;
|
||||
skip(chars: string|RegExp): number;
|
||||
skipWhitespace(text: string, index: number, options: object): number;
|
||||
skipSpaces(text: string, index: number, options: object): number;
|
||||
skipToLineEnd(text: string, index: number, options: object): number;
|
||||
skipEverythingButNewLine(text: string, index: number, options: object): number;
|
||||
skipInlineComment(text: string, index: number): number;
|
||||
skipTrailingComment(text: string, index: number): number;
|
||||
skipNewline(text: string, index: number, options: object): number;
|
||||
hasNewline(text: string, index: number, options: object): boolean;
|
||||
hasNewlineInRange(text: string, start: number, start: number): boolean;
|
||||
hasSpaces(text: string, index: number, options: object): number;
|
||||
makeString(rawContent: string, enclosingQuote: string, unescapeUnnecessaryEscapes: boolean): string;
|
||||
getNextNonSpaceNonCommentCharacterIndex(text: string, node: object, options: object): number;
|
||||
isNextLineEmptyAfterIndex(text: string, index: number): boolean;
|
||||
isNextLineEmpty(text: string, node: object, options: object): boolean;
|
||||
isPreviousLineEmpty(text: string, node: object, options: object): boolean;
|
||||
mapDoc(doc: object, callback: function): void;
|
||||
type Quote = '"' | "'";
|
||||
type SkipOptions = { backwards?: boolean };
|
||||
function getMaxContinuousCount(str: string, target: string): number;
|
||||
function getStringWidth(text: string): number;
|
||||
function getAlignmentSize(value: string, tabWidth: number, startIndex?: number): number;
|
||||
function getIndentSize(value: string, tabWidth: number): number;
|
||||
function skip(chars: string | RegExp): (text: string, index: number | false, opts?: SkipOptions) => number | false;
|
||||
function skipWhitespace(text: string, index: number | false, opts?: SkipOptions): number | false;
|
||||
function skipSpaces(text: string, index: number | false, opts?: SkipOptions): number | false;
|
||||
function skipToLineEnd(text: string, index: number | false, opts?: SkipOptions): number | false;
|
||||
function skipEverythingButNewLine(text: string, index: number | false, opts?: SkipOptions): number | false;
|
||||
function skipInlineComment(text: string, index: number | false): number | false;
|
||||
function skipTrailingComment(text: string, index: number | false): number | false;
|
||||
function skipNewline(text: string, index: number | false, opts?: SkipOptions): number | false;
|
||||
function hasNewline(text: string, index: number, opts?: SkipOptions): boolean;
|
||||
function hasNewlineInRange(text: string, start: number, end: number): boolean;
|
||||
function hasSpaces(text: string, index: number, opts?: SkipOptions): boolean;
|
||||
function makeString(rawContent: string, enclosingQuote: Quote, unescapeUnnecessaryEscapes?: boolean): string;
|
||||
function getNextNonSpaceNonCommentCharacterIndex<N>(text: string, node: N, locEnd: (node: N) => number): number | false;
|
||||
function isNextLineEmptyAfterIndex(text: string, index: number): boolean;
|
||||
function isNextLineEmpty<N>(text: string, node: N, locEnd: (node: N) => number): boolean;
|
||||
function isPreviousLineEmpty<N>(text: string, node: N, locStart: (node: N) => number): boolean;
|
||||
function mapDoc(doc: object, callback: function): void;
|
||||
```
|
||||
|
||||
### Tutorials
|
||||
|
|
|
@ -38,6 +38,14 @@ function getPenultimate(arr) {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {{backwards?: boolean}} SkipOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string | RegExp} chars
|
||||
* @returns {(text: string, index: number | false, opts?: SkipOptions) => number | false}
|
||||
*/
|
||||
function skip(chars) {
|
||||
return (text, index, opts) => {
|
||||
const backwards = opts && opts.backwards;
|
||||
|
@ -74,11 +82,28 @@ function skip(chars) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
|
||||
*/
|
||||
const skipWhitespace = skip(/\s/);
|
||||
/**
|
||||
* @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
|
||||
*/
|
||||
const skipSpaces = skip(" \t");
|
||||
/**
|
||||
* @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
|
||||
*/
|
||||
const skipToLineEnd = skip(",; \t");
|
||||
/**
|
||||
* @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
|
||||
*/
|
||||
const skipEverythingButNewLine = skip(/[^\r\n]/);
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number | false} index
|
||||
* @returns {number | false}
|
||||
*/
|
||||
function skipInlineComment(text, index) {
|
||||
if (index === false) {
|
||||
return false;
|
||||
|
@ -94,6 +119,11 @@ function skipInlineComment(text, index) {
|
|||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number | false} index
|
||||
* @returns {number | false}
|
||||
*/
|
||||
function skipTrailingComment(text, index) {
|
||||
if (index === false) {
|
||||
return false;
|
||||
|
@ -108,6 +138,12 @@ function skipTrailingComment(text, index) {
|
|||
// This one doesn't use the above helper function because it wants to
|
||||
// test \r\n in order and `skip` doesn't support ordering and we only
|
||||
// want to skip one newline. It's simple to implement.
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number | false} index
|
||||
* @param {SkipOptions=} opts
|
||||
* @returns {number | false}
|
||||
*/
|
||||
function skipNewline(text, index, opts) {
|
||||
const backwards = opts && opts.backwards;
|
||||
if (index === false) {
|
||||
|
@ -144,6 +180,12 @@ function skipNewline(text, index, opts) {
|
|||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number} index
|
||||
* @param {SkipOptions=} opts
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function hasNewline(text, index, opts) {
|
||||
opts = opts || {};
|
||||
const idx = skipSpaces(text, opts.backwards ? index - 1 : index, opts);
|
||||
|
@ -151,6 +193,12 @@ function hasNewline(text, index, opts) {
|
|||
return idx !== idx2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number} start
|
||||
* @param {number} end
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function hasNewlineInRange(text, start, end) {
|
||||
for (let i = start; i < end; ++i) {
|
||||
if (text.charAt(i) === "\n") {
|
||||
|
@ -161,7 +209,14 @@ function hasNewlineInRange(text, start, end) {
|
|||
}
|
||||
|
||||
// Note: this function doesn't ignore leading comments unlike isNextLineEmpty
|
||||
/**
|
||||
* @template N
|
||||
* @param {string} text
|
||||
* @param {N} node
|
||||
* @param {(node: N) => number} locStart
|
||||
*/
|
||||
function isPreviousLineEmpty(text, node, locStart) {
|
||||
/** @type {number | false} */
|
||||
let idx = locStart(node) - 1;
|
||||
idx = skipSpaces(text, idx, { backwards: true });
|
||||
idx = skipNewline(text, idx, { backwards: true });
|
||||
|
@ -170,8 +225,15 @@ function isPreviousLineEmpty(text, node, locStart) {
|
|||
return idx !== idx2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number} index
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isNextLineEmptyAfterIndex(text, index) {
|
||||
/** @type {number | false} */
|
||||
let oldIdx = null;
|
||||
/** @type {number | false} */
|
||||
let idx = index;
|
||||
while (idx !== oldIdx) {
|
||||
// We need to skip all the potential trailing inline comments
|
||||
|
@ -182,25 +244,47 @@ function isNextLineEmptyAfterIndex(text, index) {
|
|||
}
|
||||
idx = skipTrailingComment(text, idx);
|
||||
idx = skipNewline(text, idx);
|
||||
return hasNewline(text, idx);
|
||||
return idx !== false && hasNewline(text, idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @template N
|
||||
* @param {string} text
|
||||
* @param {N} node
|
||||
* @param {(node: N) => number} locEnd
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isNextLineEmpty(text, node, locEnd) {
|
||||
return isNextLineEmptyAfterIndex(text, locEnd(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number} idx
|
||||
* @returns {number | false}
|
||||
*/
|
||||
function getNextNonSpaceNonCommentCharacterIndexWithStartIndex(text, idx) {
|
||||
/** @type {number | false} */
|
||||
let oldIdx = null;
|
||||
while (idx !== oldIdx) {
|
||||
oldIdx = idx;
|
||||
idx = skipSpaces(text, idx);
|
||||
idx = skipInlineComment(text, idx);
|
||||
idx = skipTrailingComment(text, idx);
|
||||
idx = skipNewline(text, idx);
|
||||
/** @type {number | false} */
|
||||
let nextIdx = idx;
|
||||
while (nextIdx !== oldIdx) {
|
||||
oldIdx = nextIdx;
|
||||
nextIdx = skipSpaces(text, nextIdx);
|
||||
nextIdx = skipInlineComment(text, nextIdx);
|
||||
nextIdx = skipTrailingComment(text, nextIdx);
|
||||
nextIdx = skipNewline(text, nextIdx);
|
||||
}
|
||||
return idx;
|
||||
return nextIdx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template N
|
||||
* @param {string} text
|
||||
* @param {N} node
|
||||
* @param {(node: N) => number} locEnd
|
||||
* @returns {number | false}
|
||||
*/
|
||||
function getNextNonSpaceNonCommentCharacterIndex(text, node, locEnd) {
|
||||
return getNextNonSpaceNonCommentCharacterIndexWithStartIndex(
|
||||
text,
|
||||
|
@ -208,18 +292,36 @@ function getNextNonSpaceNonCommentCharacterIndex(text, node, locEnd) {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @template N
|
||||
* @param {string} text
|
||||
* @param {N} node
|
||||
* @param {(node: N) => number} locEnd
|
||||
* @returns {string}
|
||||
*/
|
||||
function getNextNonSpaceNonCommentCharacter(text, node, locEnd) {
|
||||
return text.charAt(
|
||||
// @ts-ignore => TBD: can return false, should we define a fallback?
|
||||
getNextNonSpaceNonCommentCharacterIndex(text, node, locEnd)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number} index
|
||||
* @param {SkipOptions=} opts
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function hasSpaces(text, index, opts) {
|
||||
opts = opts || {};
|
||||
const idx = skipSpaces(text, opts.backwards ? index - 1 : index, opts);
|
||||
return idx !== index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{range?: [number, number], start?: number}} node
|
||||
* @param {number} index
|
||||
*/
|
||||
function setLocStart(node, index) {
|
||||
if (node.range) {
|
||||
node.range[0] = index;
|
||||
|
@ -228,6 +330,10 @@ function setLocStart(node, index) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{range?: [number, number], end?: number}} node
|
||||
* @param {number} index
|
||||
*/
|
||||
function setLocEnd(node, index) {
|
||||
if (node.range) {
|
||||
node.range[1] = index;
|
||||
|
@ -400,6 +506,12 @@ function getLeftMost(node) {
|
|||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @param {number} tabWidth
|
||||
* @param {number=} startIndex
|
||||
* @returns {number}
|
||||
*/
|
||||
function getAlignmentSize(value, tabWidth, startIndex) {
|
||||
startIndex = startIndex || 0;
|
||||
|
||||
|
@ -419,6 +531,11 @@ function getAlignmentSize(value, tabWidth, startIndex) {
|
|||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @param {number} tabWidth
|
||||
* @returns {number}
|
||||
*/
|
||||
function getIndentSize(value, tabWidth) {
|
||||
const lastNewlineIndex = value.lastIndexOf("\n");
|
||||
if (lastNewlineIndex === -1) {
|
||||
|
@ -432,12 +549,24 @@ function getIndentSize(value, tabWidth) {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {'"' | "'"} Quote
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} raw
|
||||
* @param {Quote} preferredQuote
|
||||
* @returns {Quote}
|
||||
*/
|
||||
function getPreferredQuote(raw, preferredQuote) {
|
||||
// `rawContent` is the string exactly like it appeared in the input source
|
||||
// code, without its enclosing quotes.
|
||||
const rawContent = raw.slice(1, -1);
|
||||
|
||||
/** @type {{ quote: '"', regex: RegExp }} */
|
||||
const double = { quote: '"', regex: /"/g };
|
||||
/** @type {{ quote: "'", regex: RegExp }} */
|
||||
const single = { quote: "'", regex: /'/g };
|
||||
|
||||
const preferred = preferredQuote === "'" ? single : double;
|
||||
|
@ -474,6 +603,7 @@ function printString(raw, options, isDirectiveLiteral) {
|
|||
const canChangeDirectiveQuotes =
|
||||
!rawContent.includes('"') && !rawContent.includes("'");
|
||||
|
||||
/** @type {Quote} */
|
||||
const enclosingQuote =
|
||||
options.parser === "json"
|
||||
? '"'
|
||||
|
@ -508,6 +638,12 @@ function printString(raw, options, isDirectiveLiteral) {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} rawContent
|
||||
* @param {Quote} enclosingQuote
|
||||
* @param {boolean=} unescapeUnnecessaryEscapes
|
||||
* @returns {string}
|
||||
*/
|
||||
function makeString(rawContent, enclosingQuote, unescapeUnnecessaryEscapes) {
|
||||
const otherQuote = enclosingQuote === '"' ? "'" : '"';
|
||||
|
||||
|
@ -563,6 +699,11 @@ function printNumber(rawNumber) {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @param {string} target
|
||||
* @returns {number}
|
||||
*/
|
||||
function getMaxContinuousCount(str, target) {
|
||||
const results = str.match(
|
||||
new RegExp(`(${escapeStringRegexp(target)})+`, "g")
|
||||
|
@ -607,6 +748,10 @@ function getMinNotPresentContinuousCount(str, target) {
|
|||
return max + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @returns {number}
|
||||
*/
|
||||
function getStringWidth(text) {
|
||||
if (!text) {
|
||||
return 0;
|
||||
|
|
|
@ -510,7 +510,8 @@ function printComments(path, print, options, needsSemi) {
|
|||
leadingParts.push(contents);
|
||||
|
||||
const text = options.originalText;
|
||||
if (hasNewline(text, skipNewline(text, options.locEnd(comment)))) {
|
||||
const index = skipNewline(text, options.locEnd(comment));
|
||||
if (index !== false && hasNewline(text, index)) {
|
||||
leadingParts.push(hardline);
|
||||
}
|
||||
} else if (trailing) {
|
||||
|
|
|
@ -228,28 +228,31 @@ defaultOptions: {
|
|||
|
||||
A `util` module from Prettier core is considered a private API and is not meant to be consumed by plugins. Instead, the `util-shared` module provides the following limited set of utility functions for plugins:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
```ts
|
||||
getMaxContinuousCount(str: string, target: string): number;
|
||||
getStringWidth(text: string): number;
|
||||
getAlignmentSize(value: string, tabWidth: number, startIndex: number): number;
|
||||
getIndentSize(value: string, tabWidth: number): number;
|
||||
skip(chars: string|RegExp): number;
|
||||
skipWhitespace(text: string, index: number, options: object): number;
|
||||
skipSpaces(text: string, index: number, options: object): number;
|
||||
skipToLineEnd(text: string, index: number, options: object): number;
|
||||
skipEverythingButNewLine(text: string, index: number, options: object): number;
|
||||
skipInlineComment(text: string, index: number): number;
|
||||
skipTrailingComment(text: string, index: number): number;
|
||||
skipNewline(text: string, index: number, options: object): number;
|
||||
hasNewline(text: string, index: number, options: object): boolean;
|
||||
hasNewlineInRange(text: string, start: number, start: number): boolean;
|
||||
hasSpaces(text: string, index: number, options: object): number;
|
||||
makeString(rawContent: string, enclosingQuote: string, unescapeUnnecessarEscapes: boolean): string;
|
||||
getNextNonSpaceNonCommentCharacterIndex(text: string, node: object, options: object): number;
|
||||
isNextLineEmptyAfterIndex(text: string, index: number): boolean;
|
||||
isNextLineEmpty(text: string, node: object, options: object): boolean;
|
||||
isPreviousLineEmpty(text: string, node: object, options: object): boolean;
|
||||
mapDoc(doc: object, callback: function): void;
|
||||
type Quote = '"' | "'";
|
||||
type SkipOptions = { backwards?: boolean };
|
||||
function getMaxContinuousCount(str: string, target: string): number;
|
||||
function getStringWidth(text: string): number;
|
||||
function getAlignmentSize(value: string, tabWidth: number, startIndex?: number): number;
|
||||
function getIndentSize(value: string, tabWidth: number): number;
|
||||
function skip(chars: string | RegExp): (text: string, index: number | false, opts?: SkipOptions) => number | false;
|
||||
function skipWhitespace(text: string, index: number | false, opts?: SkipOptions): number | false;
|
||||
function skipSpaces(text: string, index: number | false, opts?: SkipOptions): number | false;
|
||||
function skipToLineEnd(text: string, index: number | false, opts?: SkipOptions): number | false;
|
||||
function skipEverythingButNewLine(text: string, index: number | false, opts?: SkipOptions): number | false;
|
||||
function skipInlineComment(text: string, index: number | false): number | false;
|
||||
function skipTrailingComment(text: string, index: number | false): number | false;
|
||||
function skipNewline(text: string, index: number | false, opts?: SkipOptions): number | false;
|
||||
function hasNewline(text: string, index: number, opts?: SkipOptions): boolean;
|
||||
function hasNewlineInRange(text: string, start: number, end: number): boolean;
|
||||
function hasSpaces(text: string, index: number, opts?: SkipOptions): boolean;
|
||||
function makeString(rawContent: string, enclosingQuote: Quote, unescapeUnnecessaryEscapes?: boolean): string;
|
||||
function getNextNonSpaceNonCommentCharacterIndex<N>(text: string, node: N, locEnd: (node: N) => number): number | false;
|
||||
function isNextLineEmptyAfterIndex(text: string, index: number): boolean;
|
||||
function isNextLineEmpty<N>(text: string, node: N, locEnd: (node: N) => number): boolean;
|
||||
function isPreviousLineEmpty<N>(text: string, node: N, locStart: (node: N) => number): boolean;
|
||||
function mapDoc(doc: object, callback: function): void;
|
||||
```
|
||||
|
||||
### Tutorials
|
||||
|
|
Loading…
Reference in New Issue