diff --git a/src/DiagnosticsManager.ts b/src/DiagnosticsManager.ts index c9b8a81a6..9d01f1e0b 100644 --- a/src/DiagnosticsManager.ts +++ b/src/DiagnosticsManager.ts @@ -19,7 +19,7 @@ import stripAnsi = require("strip-ansi"); import configuration from "./configuration"; import { SwiftExecution } from "./tasks/SwiftExecution"; import { WorkspaceContext } from "./WorkspaceContext"; -import { checkIfBuildComplete } from "./utilities/tasks"; +import { checkIfBuildComplete, lineBreakRegex } from "./utilities/tasks"; interface ParsedDiagnostic { uri: string; @@ -278,7 +278,7 @@ export class DiagnosticsManager implements vscode.Disposable { disposables.push( swiftExecution.onDidWrite(data => { const sanitizedData = (remainingData || "") + stripAnsi(data); - const lines = sanitizedData.split(/\r\n|\n|\r/gm); + const lines = sanitizedData.split(lineBreakRegex); // If ends with \n then will be "" and there's no affect. // Otherwise want to keep remaining data to pre-pend next write remainingData = lines.pop(); diff --git a/src/SwiftPackage.ts b/src/SwiftPackage.ts index 9a25f6136..3a46d61ea 100644 --- a/src/SwiftPackage.ts +++ b/src/SwiftPackage.ts @@ -20,6 +20,7 @@ import { isPathInsidePath } from "./utilities/filesystem"; import { SwiftToolchain } from "./toolchain/toolchain"; import { BuildFlags } from "./toolchain/BuildFlags"; import { SwiftOutputChannel } from "./ui/SwiftOutputChannel"; +import { lineBreakRegex } from "./utilities/tasks"; /** Swift Package Manager contents */ interface PackageContents { @@ -313,7 +314,7 @@ export class SwiftPackage { cwd: folder.fsPath, }); const plugins: PackagePlugin[] = []; - const lines = stdout.split("\n").map(item => item.trim()); + const lines = stdout.split(lineBreakRegex).map(item => item.trim()); for (const line of lines) { // ‘generate-documentation’ (plugin ‘Swift-DocC’ in package ‘SwiftDocCPlugin’) const pluginMatch = /^‘(.*)’ \(plugin ‘(.*)’ in package ‘(.*)’\)/.exec(line); diff --git a/src/TestExplorer/TestParsers/SwiftTestingOutputParser.ts b/src/TestExplorer/TestParsers/SwiftTestingOutputParser.ts index a226dd276..ff3281e07 100644 --- a/src/TestExplorer/TestParsers/SwiftTestingOutputParser.ts +++ b/src/TestExplorer/TestParsers/SwiftTestingOutputParser.ts @@ -24,6 +24,7 @@ import { ITestRunState } from "./TestRunState"; import { TestClass } from "../TestDiscovery"; import { sourceLocationToVSCodeLocation } from "../../utilities/utilities"; import { exec } from "child_process"; +import { lineBreakRegex } from "../../utilities/tasks"; // All events produced by a swift-testing run will be one of these three types. // Detailed information about swift-testing's JSON schema is available here: @@ -235,7 +236,7 @@ export class SwiftTestingOutputParser { * @param chunk A chunk of stdout emitted during a test run. */ public parseStdout(chunk: string, runState: ITestRunState) { - for (const line of chunk.split("\n")) { + for (const line of chunk.split(lineBreakRegex)) { if (line.trim().length > 0) { runState.recordOutput(undefined, `${line}\r\n`); } diff --git a/src/TestExplorer/TestParsers/XCTestOutputParser.ts b/src/TestExplorer/TestParsers/XCTestOutputParser.ts index e74bff2d5..ee4be7ac4 100644 --- a/src/TestExplorer/TestParsers/XCTestOutputParser.ts +++ b/src/TestExplorer/TestParsers/XCTestOutputParser.ts @@ -17,6 +17,7 @@ import { sourceLocationToVSCodeLocation } from "../../utilities/utilities"; import { MarkdownString, Location } from "vscode"; // eslint-disable-next-line @typescript-eslint/no-require-imports import stripAnsi = require("strip-ansi"); +import { lineBreakRegex } from "../../utilities/tasks"; /** Regex for parsing XCTest output */ interface TestRegex { @@ -190,7 +191,7 @@ export class XCTestOutputParser implements IXCTestOutputParser { // which we don't care about. const output = process.platform === "win32" ? stripAnsi(rawOutput) : rawOutput; const output2 = output.replace(/\r\n/g, "\n"); - const lines = output2.split("\n"); + const lines = output2.split(lineBreakRegex); if (runState.excess) { lines[0] = runState.excess + lines[0]; } diff --git a/src/process-list/BaseProcessList.ts b/src/process-list/BaseProcessList.ts index 0e5f621bd..ec48d1fa0 100644 --- a/src/process-list/BaseProcessList.ts +++ b/src/process-list/BaseProcessList.ts @@ -15,6 +15,7 @@ import * as util from "util"; import * as child_process from "child_process"; import { Process, ProcessList } from "."; +import { lineBreakRegex } from "../utilities/tasks"; const exec = util.promisify(child_process.execFile); @@ -46,7 +47,7 @@ export abstract class BaseProcessList implements ProcessList { maxBuffer: 10 * 1024 * 1024, // Increase the max buffer size to 10Mb }); const parser = this.createParser(); - return (await execCommand).stdout.split("\n").flatMap(line => { + return (await execCommand).stdout.split(lineBreakRegex).flatMap(line => { const process = parser(line.toString()); if (!process || process.id === execCommand.child.pid) { return []; diff --git a/src/toolchain/toolchain.ts b/src/toolchain/toolchain.ts index 2e0358baa..a2a412c4a 100644 --- a/src/toolchain/toolchain.ts +++ b/src/toolchain/toolchain.ts @@ -25,6 +25,7 @@ import { Version } from "../utilities/version"; import { BuildFlags } from "./BuildFlags"; import { Sanitizer } from "./Sanitizer"; import { SwiftlyConfig } from "./ToolchainVersion"; +import { lineBreakRegex } from "../utilities/tasks"; /** * Contents of **Info.plist** on Windows. @@ -235,7 +236,8 @@ export class SwiftToolchain { execFile("mdfind", [`kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode'`]), this.getXcodeDeveloperDir(), ]); - const spotlightXcodes = mdfindOutput.length > 0 ? mdfindOutput.trimEnd().split("\n") : []; + const spotlightXcodes = + mdfindOutput.length > 0 ? mdfindOutput.trimEnd().split(lineBreakRegex) : []; const selectedXcode = this.getXcodeDirectory(xcodeDeveloperDir); // Combine the results from both commands @@ -933,7 +935,7 @@ export class SwiftToolchain { } const { stdout } = await execSwift(["--version"], { swiftExecutable }); return { - compilerVersion: stdout.split("\n", 1)[0], + compilerVersion: stdout.split(lineBreakRegex, 1)[0], paths: { runtimeLibraryPaths: [""] }, }; } catch { diff --git a/src/ui/SwiftBuildStatus.ts b/src/ui/SwiftBuildStatus.ts index 33748e87a..d597fc5aa 100644 --- a/src/ui/SwiftBuildStatus.ts +++ b/src/ui/SwiftBuildStatus.ts @@ -18,7 +18,7 @@ import * as vscode from "vscode"; import configuration, { ShowBuildStatusOptions } from "../configuration"; import { RunningTask, StatusItem } from "./StatusItem"; import { SwiftExecution } from "../tasks/SwiftExecution"; -import { checkIfBuildComplete } from "../utilities/tasks"; +import { checkIfBuildComplete, lineBreakRegex } from "../utilities/tasks"; /** * Progress of `swift` build, parsed from the @@ -121,7 +121,7 @@ export class SwiftBuildStatus implements vscode.Disposable { // We'll process data one line at a time, in reverse order // since the latest interesting message is all we need to // be concerned with - const lines = sanitizedData.split(/\r\n|\n|\r/gm).reverse(); + const lines = sanitizedData.split(lineBreakRegex).reverse(); for (const line of lines) { if (checkIfBuildComplete(line)) { update(name); diff --git a/src/utilities/tasks.ts b/src/utilities/tasks.ts index b035dc45e..089c78be4 100644 --- a/src/utilities/tasks.ts +++ b/src/utilities/tasks.ts @@ -14,6 +14,8 @@ import * as path from "path"; import * as vscode from "vscode"; +export const lineBreakRegex = /\r\n|\n|\r/gm; + export function resolveTaskCwd(task: vscode.Task, cwd?: string): string | undefined { const scopeWorkspaceFolder = getScopeWorkspaceFolder(task); if (!cwd) { diff --git a/test/integration-tests/testexplorer/XCTestOutputParser.test.ts b/test/integration-tests/testexplorer/XCTestOutputParser.test.ts index ed5744d34..80f45b09d 100644 --- a/test/integration-tests/testexplorer/XCTestOutputParser.test.ts +++ b/test/integration-tests/testexplorer/XCTestOutputParser.test.ts @@ -24,6 +24,7 @@ import { sourceLocationToVSCodeLocation } from "../../../src/utilities/utilities import { TestXUnitParser } from "../../../src/TestExplorer/TestXUnitParser"; import { activateExtensionForSuite } from "../utilities/testutilities"; import { SwiftOutputChannel } from "../../../src/ui/SwiftOutputChannel"; +import { lineBreakRegex } from "../../../src/utilities/tasks"; enum ParserTestKind { Regular = "Regular Test Run", @@ -33,7 +34,7 @@ enum ParserTestKind { suite("XCTestOutputParser Suite", () => { function inputToTestOutput(input: string) { return input - .split("\n") + .split(lineBreakRegex) .slice(0, -1) .map(line => `${line}\r\n`); }