From 1ea72933582d90ee5e190f140c0c4bbd13088c5e Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Fri, 5 Jan 2024 10:21:18 +0100 Subject: [PATCH 1/2] feat(config-migration): respect editorconfig max line length --- .../__fixtures__/.global_editorconfig | 1 + .../__fixtures__/.json_editorconfig | 3 ++ lib/util/json-writer/code-format.ts | 1 + lib/util/json-writer/editor-config.spec.ts | 8 ++--- lib/util/json-writer/editor-config.ts | 1 + .../branch/migrated-data.spec.ts | 35 +++++++++++++++++-- .../config-migration/branch/migrated-data.ts | 25 +++++++++++-- 7 files changed, 64 insertions(+), 10 deletions(-) diff --git a/lib/util/json-writer/__fixtures__/.global_editorconfig b/lib/util/json-writer/__fixtures__/.global_editorconfig index 712d48e6c0cedd..54a4aa49ab63bc 100644 --- a/lib/util/json-writer/__fixtures__/.global_editorconfig +++ b/lib/util/json-writer/__fixtures__/.global_editorconfig @@ -1,3 +1,4 @@ [*] indent_style = space indent_size = 6 +max_line_length = 160 diff --git a/lib/util/json-writer/__fixtures__/.json_editorconfig b/lib/util/json-writer/__fixtures__/.json_editorconfig index c7a221961de91a..487051e1763595 100644 --- a/lib/util/json-writer/__fixtures__/.json_editorconfig +++ b/lib/util/json-writer/__fixtures__/.json_editorconfig @@ -1,2 +1,5 @@ +[*] +max_line_length = off + [*.json] indent_style = tab diff --git a/lib/util/json-writer/code-format.ts b/lib/util/json-writer/code-format.ts index 2e86f0f592268f..e435f905f0662d 100644 --- a/lib/util/json-writer/code-format.ts +++ b/lib/util/json-writer/code-format.ts @@ -3,4 +3,5 @@ import type { IndentationType } from './indentation-type'; export interface CodeFormat { indentationSize?: number; indentationType?: IndentationType; + maxLineLength?: number | 'off'; } diff --git a/lib/util/json-writer/editor-config.spec.ts b/lib/util/json-writer/editor-config.spec.ts index 0139c907666dc5..f015329f36588a 100644 --- a/lib/util/json-writer/editor-config.spec.ts +++ b/lib/util/json-writer/editor-config.spec.ts @@ -33,7 +33,6 @@ describe('util/json-writer/editor-config', () => { }); it('should handle empty .editorconfig file', async () => { - expect.assertions(2); Fixtures.mock({ '.editorconfig': '', }); @@ -41,20 +40,20 @@ describe('util/json-writer/editor-config', () => { expect(format.indentationSize).toBeUndefined(); expect(format.indentationType).toBeUndefined(); + expect(format.maxLineLength).toBeUndefined(); }); it('should handle global config from .editorconfig', async () => { - expect.assertions(2); Fixtures.mock({ '.editorconfig': Fixtures.get('.global_editorconfig'), }); const format = await EditorConfig.getCodeFormat(defaultConfigFile); expect(format.indentationSize).toBe(6); expect(format.indentationType).toBe('space'); + expect(format.maxLineLength).toBe(160); }); it('should return undefined in case of exception', async () => { - expect.assertions(2); Fixtures.mock({ '.editorconfig': Fixtures.get('.global_editorconfig'), }); @@ -70,7 +69,6 @@ describe('util/json-writer/editor-config', () => { }); it('should not handle non json config from .editorconfig', async () => { - expect.assertions(2); Fixtures.mock({ '.editorconfig': Fixtures.get('.non_json_editorconfig'), }); @@ -81,12 +79,12 @@ describe('util/json-writer/editor-config', () => { }); it('should handle json config from .editorconfig', async () => { - expect.assertions(1); Fixtures.mock({ '.editorconfig': Fixtures.get('.json_editorconfig'), }); const format = await EditorConfig.getCodeFormat(defaultConfigFile); expect(format.indentationType).toBe('tab'); + expect(format.maxLineLength).toBe('off'); }); }); diff --git a/lib/util/json-writer/editor-config.ts b/lib/util/json-writer/editor-config.ts index 5216039a1f550a..5474e655dee114 100644 --- a/lib/util/json-writer/editor-config.ts +++ b/lib/util/json-writer/editor-config.ts @@ -13,6 +13,7 @@ export class EditorConfig { return { indentationSize: EditorConfig.getIndentationSize(knownProps), indentationType: EditorConfig.getIndentationType(knownProps), + maxLineLength: knownProps.max_line_length as number | 'off' | undefined, }; } catch (err) { logger.warn({ err }, 'Failed to parse editor config'); diff --git a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts index acafa26226c39a..c63ca22f81730c 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts @@ -5,12 +5,14 @@ import { mockedFunction, scm } from '../../../../../test/util'; import { migrateConfig } from '../../../../config/migration'; import { logger } from '../../../../logger'; import { readLocalFile } from '../../../../util/fs'; +import { EditorConfig } from '../../../../util/json-writer'; import { detectRepoFileConfig } from '../../init/merge'; import { MigratedDataFactory, applyPrettierFormatting } from './migrated-data'; jest.mock('../../../../config/migration'); jest.mock('../../../../util/git'); jest.mock('../../../../util/fs'); +jest.mock('../../../../util/json-writer'); jest.mock('../../init/merge'); jest.mock('detect-indent'); @@ -191,13 +193,42 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { }); it('formats with default 2 spaces', async () => { - mockedFunction(scm.getFileList).mockResolvedValue(['.prettierrc']); + mockedFunction(scm.getFileList).mockResolvedValue([ + '.prettierrc', + '.editorconfig', + ]); + mockedFunction(EditorConfig.getCodeFormat).mockResolvedValueOnce({ + maxLineLength: 80, + }); await expect( - applyPrettierFormatting(migratedData.content, 'json', { + applyPrettierFormatting('.prettierrc', migratedData.content, 'json', { amount: 0, indent: ' ', }), ).resolves.toEqual(formattedMigratedData.content); }); + + it('formats with printWith=Infinity', async () => { + mockedFunction(scm.getFileList).mockResolvedValue([ + '.prettierrc', + '.editorconfig', + ]); + mockedFunction(EditorConfig.getCodeFormat).mockResolvedValueOnce({ + maxLineLength: 'off', + }); + await expect( + applyPrettierFormatting( + '.prettierrc', + `{\n"extends":[":separateMajorReleases",":prImmediately",":renovatePrefix",":semanticPrefixFixDepsChoreOthers"]}`, + 'json', + { + amount: 0, + indent: ' ', + }, + ), + ).resolves.toBe( + `{\n "extends": [":separateMajorReleases", ":prImmediately", ":renovatePrefix", ":semanticPrefixFixDepsChoreOthers"]\n}\n`, + ); + }); }); }); diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index 84d91607357de9..cbdf6fd28e2ddd 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -1,12 +1,14 @@ +import is from '@sindresorhus/is'; import detectIndent from 'detect-indent'; import JSON5 from 'json5'; -import type { BuiltInParserName } from 'prettier'; +import type { BuiltInParserName, Options } from 'prettier'; import upath from 'upath'; import { migrateConfig } from '../../../../config/migration'; import { prettier } from '../../../../expose.cjs'; import { logger } from '../../../../logger'; import { scm } from '../../../../modules/platform/scm'; import { readLocalFile } from '../../../../util/fs'; +import { EditorConfig } from '../../../../util/json-writer'; import { detectRepoFileConfig } from '../../init/merge'; export interface MigratedData { @@ -37,6 +39,7 @@ const prettierConfigFilenames = new Set([ export type PrettierParser = BuiltInParserName; export async function applyPrettierFormatting( + filename: string, content: string, parser: PrettierParser, indent?: Indent, @@ -48,6 +51,8 @@ export async function applyPrettierFormatting( prettierConfigFilenames.has(file), ); + const editroconfExists = fileList.some((file) => file === '.editorconfig'); + if (!prettierExists) { try { const packageJsonContent = await readLocalFile('package.json', 'utf8'); @@ -63,12 +68,26 @@ export async function applyPrettierFormatting( if (!prettierExists) { return content; } - const options = { + + const options: Options = { parser, tabWidth: indent?.amount === 0 ? 2 : indent?.amount, useTabs: indent?.type === 'tab', }; + if (editroconfExists) { + const editorconf = await EditorConfig.getCodeFormat(filename); + + // https://github.com/prettier/prettier/blob/bab892242a1f9d8fcae50514b9304bf03f2e25ab/src/config/editorconfig/editorconfig-to-prettier.js#L47 + if (editorconf.maxLineLength) { + options.printWidth = is.number(editorconf.maxLineLength) + ? editorconf.maxLineLength + : Number.POSITIVE_INFINITY; + } + + // TODO: support editor config `indent_style` and `indent_size` + } + return prettier().format(content, options); } finally { logger.trace('applyPrettierFormatting - END'); @@ -103,7 +122,7 @@ export class MigratedDataFactory { indent, }: MigratedData): Promise { const parser = upath.extname(filename).replace('.', '') as PrettierParser; - return applyPrettierFormatting(content, parser, indent); + return applyPrettierFormatting(filename, content, parser, indent); } private static async build(): Promise { From c77b133258894a60e88ce934c806d02b797041c3 Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Fri, 5 Jan 2024 10:30:36 +0100 Subject: [PATCH 2/2] fix: typo --- .../repository/config-migration/branch/migrated-data.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index cbdf6fd28e2ddd..e96a24d9ecdb75 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -51,7 +51,9 @@ export async function applyPrettierFormatting( prettierConfigFilenames.has(file), ); - const editroconfExists = fileList.some((file) => file === '.editorconfig'); + const editorconfigExists = fileList.some( + (file) => file === '.editorconfig', + ); if (!prettierExists) { try { @@ -75,7 +77,7 @@ export async function applyPrettierFormatting( useTabs: indent?.type === 'tab', }; - if (editroconfExists) { + if (editorconfigExists) { const editorconf = await EditorConfig.getCodeFormat(filename); // https://github.com/prettier/prettier/blob/bab892242a1f9d8fcae50514b9304bf03f2e25ab/src/config/editorconfig/editorconfig-to-prettier.js#L47