UNPKG

alm

Version:

The best IDE for TypeScript

191 lines (190 loc) 7.7 kB
/** * From https://raw.githubusercontent.com/Microsoft/vscode-json-languageservice/master/src/services/jsonFormatter.ts * - Redirected dependencies * - Made `getEol` use editorconfig ;) */ /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var Json = require("../core/jsonc-parser"); var Position = monaco.Position; var Range = monaco.Range; /** * BAS: Was simple so I wrote it :) */ var TextEditReplace; (function (TextEditReplace) { function replace(range, text) { var result = { range: range, text: text }; return result; } TextEditReplace.replace = replace; })(TextEditReplace || (TextEditReplace = {})); function format(document, range, options) { var documentText = document.getValue(); var initialIndentLevel; var value; var rangeOffset; if (range) { var startPosition = new Position(range.startLineNumber, 0); rangeOffset = document.getOffsetAt(startPosition); var endOffset = document.getOffsetAt(new Position(range.endLineNumber + 1, 0)); var endLineStart = document.getOffsetAt(new Position(range.endLineNumber, 0)); while (endOffset > endLineStart && isEOL(documentText, endOffset - 1)) { endOffset--; } var endPosition = document.getPositionAt(endOffset); range = new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column); value = documentText.substring(rangeOffset, endOffset); initialIndentLevel = computeIndentLevel(value, 0, options); } else { value = documentText; var endPosition = document.getPositionAt(value.length); range = new Range(0, 0, endPosition.lineNumber, endPosition.column); initialIndentLevel = 0; rangeOffset = 0; } var eol = getEOL(document); var lineBreak = false; var indentLevel = 0; var indentValue; if (options.insertSpaces) { indentValue = repeat(' ', options.tabSize); } else { indentValue = '\t'; } var scanner = Json.createScanner(value, false); function newLineAndIndent() { return eol + repeat(indentValue, initialIndentLevel + indentLevel); } function scanNext() { var token = scanner.scan(); lineBreak = false; while (token === Json.SyntaxKind.Trivia || token === Json.SyntaxKind.LineBreakTrivia) { lineBreak = lineBreak || (token === Json.SyntaxKind.LineBreakTrivia); token = scanner.scan(); } return token; } var editOperations = []; function addEdit(text, startOffset, endOffset) { if (documentText.substring(startOffset, endOffset) !== text) { var startPos = document.getPositionAt(startOffset); var endPos = document.getPositionAt(endOffset); var replaceRange = new Range(startPos.lineNumber, startPos.column, endPos.lineNumber, endPos.column); editOperations.push(TextEditReplace.replace(replaceRange, text)); } } var firstToken = scanNext(); if (firstToken !== Json.SyntaxKind.EOF) { var firstTokenStart = scanner.getTokenOffset() + rangeOffset; var initialIndent = repeat(indentValue, initialIndentLevel); addEdit(initialIndent, rangeOffset, firstTokenStart); } while (firstToken !== Json.SyntaxKind.EOF) { var firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + rangeOffset; var secondToken = scanNext(); var replaceContent = ''; while (!lineBreak && (secondToken === Json.SyntaxKind.LineCommentTrivia || secondToken === Json.SyntaxKind.BlockCommentTrivia)) { // comments on the same line: keep them on the same line, but ignore them otherwise var commentTokenStart = scanner.getTokenOffset() + rangeOffset; addEdit(' ', firstTokenEnd, commentTokenStart); firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + rangeOffset; replaceContent = secondToken === Json.SyntaxKind.LineCommentTrivia ? newLineAndIndent() : ''; secondToken = scanNext(); } if (secondToken === Json.SyntaxKind.CloseBraceToken) { if (firstToken !== Json.SyntaxKind.OpenBraceToken) { indentLevel--; replaceContent = newLineAndIndent(); } } else if (secondToken === Json.SyntaxKind.CloseBracketToken) { if (firstToken !== Json.SyntaxKind.OpenBracketToken) { indentLevel--; replaceContent = newLineAndIndent(); } } else { switch (firstToken) { case Json.SyntaxKind.OpenBracketToken: case Json.SyntaxKind.OpenBraceToken: indentLevel++; replaceContent = newLineAndIndent(); break; case Json.SyntaxKind.CommaToken: case Json.SyntaxKind.LineCommentTrivia: replaceContent = newLineAndIndent(); break; case Json.SyntaxKind.BlockCommentTrivia: if (lineBreak) { replaceContent = newLineAndIndent(); } else { // symbol following comment on the same line: keep on same line, separate with ' ' replaceContent = ' '; } break; case Json.SyntaxKind.ColonToken: replaceContent = ' '; break; case Json.SyntaxKind.NullKeyword: case Json.SyntaxKind.TrueKeyword: case Json.SyntaxKind.FalseKeyword: case Json.SyntaxKind.NumericLiteral: if (secondToken === Json.SyntaxKind.NullKeyword || secondToken === Json.SyntaxKind.FalseKeyword || secondToken === Json.SyntaxKind.NumericLiteral) { replaceContent = ' '; } break; } if (lineBreak && (secondToken === Json.SyntaxKind.LineCommentTrivia || secondToken === Json.SyntaxKind.BlockCommentTrivia)) { replaceContent = newLineAndIndent(); } } var secondTokenStart = scanner.getTokenOffset() + rangeOffset; addEdit(replaceContent, firstTokenEnd, secondTokenStart); firstToken = secondToken; } return editOperations; } exports.format = format; function repeat(s, count) { var result = ''; for (var i = 0; i < count; i++) { result += s; } return result; } function computeIndentLevel(content, offset, options) { var i = 0; var nChars = 0; var tabSize = options.tabSize || 4; while (i < content.length) { var ch = content.charAt(i); if (ch === ' ') { nChars++; } else if (ch === '\t') { nChars += tabSize; } else { break; } i++; } return Math.floor(nChars / tabSize); } function getEOL(document) { return document._editorOptions.newLineCharacter; } function isEOL(text, offset) { return '\r\n'.indexOf(text.charAt(offset)) !== -1; }