From 69d5a49d06c45e39f2bceb85db0a246bc9aade02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4=20=28Donny=29?= Date: Wed, 15 Nov 2023 12:28:20 +0900 Subject: [PATCH] [TMP] Merge styled --- .../crates/napi/src/next_api/utils.rs | 39 +++++++++- .../next-core/src/app_segment_config.rs | 7 +- .../crates/next-core/src/app_structure.rs | 16 ++-- .../next-swc/crates/next-core/src/babel.rs | 11 +-- .../crates/next-core/src/next_config.rs | 6 +- .../src/next_font/google/font_fallback.rs | 7 +- .../crates/next-core/src/next_font/issue.rs | 6 +- .../next-swc/crates/next-core/src/util.rs | 7 +- packages/next/src/build/swc/index.ts | 24 +++++- .../lib/router-utils/setup-dev-bundler.ts | 76 ++++++++++++++----- 10 files changed, 149 insertions(+), 50 deletions(-) diff --git a/packages/next-swc/crates/napi/src/next_api/utils.rs b/packages/next-swc/crates/napi/src/next_api/utils.rs index 2efc044c23e70..3c09a28a4b97f 100644 --- a/packages/next-swc/crates/napi/src/next_api/utils.rs +++ b/packages/next-swc/crates/napi/src/next_api/utils.rs @@ -13,7 +13,7 @@ use turbopack_binding::{ turbopack::core::{ diagnostics::{Diagnostic, DiagnosticContextExt, PlainDiagnostic}, error::PrettyPrintError, - issue::{IssueDescriptionExt, PlainIssue, PlainIssueSource, PlainSource}, + issue::{IssueDescriptionExt, PlainIssue, PlainIssueSource, PlainSource, StyledString}, source_pos::SourcePos, }, }; @@ -101,7 +101,7 @@ pub struct NapiIssue { pub category: String, pub file_path: String, pub title: String, - pub description: String, + pub description: serde_json::Value, pub detail: String, pub source: Option, pub documentation_link: String, @@ -111,7 +111,8 @@ pub struct NapiIssue { impl From<&PlainIssue> for NapiIssue { fn from(issue: &PlainIssue) -> Self { Self { - description: issue.description.clone(), + description: serde_json::to_value(Into::::into(&issue.description)) + .unwrap(), category: issue.category.clone(), file_path: issue.file_path.clone(), detail: issue.detail.clone(), @@ -128,6 +129,38 @@ impl From<&PlainIssue> for NapiIssue { } } +#[derive(Serialize)] +#[serde(tag = "type", rename_all = "camelCase")] +pub enum NapiStyledString { + Line { value: Vec }, + Stack { value: Vec }, + Text { value: String }, + Code { value: String }, + Strong { value: String }, +} + +impl From<&StyledString> for NapiStyledString { + fn from(value: &StyledString) -> Self { + match value { + StyledString::Line(parts) => NapiStyledString::Line { + value: parts.iter().map(|p| p.into()).collect(), + }, + StyledString::Stack(parts) => NapiStyledString::Stack { + value: parts.iter().map(|p| p.into()).collect(), + }, + StyledString::Text(string) => NapiStyledString::Text { + value: string.clone(), + }, + StyledString::Code(string) => NapiStyledString::Code { + value: string.clone(), + }, + StyledString::Strong(string) => NapiStyledString::Strong { + value: string.clone(), + }, + } + } +} + #[napi(object)] pub struct NapiIssueSource { pub source: NapiSource, diff --git a/packages/next-swc/crates/next-core/src/app_segment_config.rs b/packages/next-swc/crates/next-core/src/app_segment_config.rs index b9e776b966bef..6804322075400 100644 --- a/packages/next-swc/crates/next-core/src/app_segment_config.rs +++ b/packages/next-swc/crates/next-core/src/app_segment_config.rs @@ -13,7 +13,7 @@ use turbopack_binding::turbopack::{ core::{ file_source::FileSource, ident::AssetIdent, - issue::{Issue, IssueExt, IssueSeverity, IssueSource, OptionIssueSource}, + issue::{Issue, IssueExt, IssueSeverity, IssueSource, OptionIssueSource, StyledString}, source::Source, }, ecmascript::{ @@ -178,12 +178,13 @@ impl Issue for NextSegmentConfigParsingIssue { } #[turbo_tasks::function] - fn description(&self) -> Vc { - Vc::cell( + fn description(&self) -> Vc { + StyledString::Text( "The exported configuration object in a source file need to have a very specific \ format from which some properties can be statically parsed at compiled-time." .to_string(), ) + .cell() } #[turbo_tasks::function] diff --git a/packages/next-swc/crates/next-core/src/app_structure.rs b/packages/next-swc/crates/next-core/src/app_structure.rs index 3e028e64d39bc..14dca4fe8dc59 100644 --- a/packages/next-swc/crates/next-core/src/app_structure.rs +++ b/packages/next-swc/crates/next-core/src/app_structure.rs @@ -13,7 +13,7 @@ use turbo_tasks::{ }; use turbopack_binding::{ turbo::tasks_fs::{DirectoryContent, DirectoryEntry, FileSystemEntryType, FileSystemPath}, - turbopack::core::issue::{Issue, IssueExt, IssueSeverity}, + turbopack::core::issue::{Issue, IssueExt, IssueSeverity, StyledString}, }; use crate::{ @@ -468,11 +468,12 @@ fn conflict_issue( DirectoryTreeIssue { app_dir, - message: Vc::cell(format!( + message: StyledString::Text(format!( "Conflicting {} at {}: {a} at {value_a} and {b} at {value_b}", item_names, e.key(), - )), + )) + .cell(), severity: IssueSeverity::Error.cell(), } .cell() @@ -781,11 +782,12 @@ async fn directory_tree_to_loader_tree( // TODO: improve error message to have the full paths DirectoryTreeIssue { app_dir, - message: Vc::cell(format!( + message: StyledString::Text(format!( "You cannot have two parallel pages that resolve to the same path. Route \ {} has multiple matches in {}", for_app_path, app_page - )), + )) + .cell(), severity: IssueSeverity::Error.cell(), } .cell() @@ -1127,7 +1129,7 @@ pub async fn get_global_metadata( struct DirectoryTreeIssue { pub severity: Vc, pub app_dir: Vc, - pub message: Vc, + pub message: Vc, } #[turbo_tasks::value_impl] @@ -1155,7 +1157,7 @@ impl Issue for DirectoryTreeIssue { } #[turbo_tasks::function] - fn description(&self) -> Vc { + fn description(&self) -> Vc { self.message } } diff --git a/packages/next-swc/crates/next-core/src/babel.rs b/packages/next-swc/crates/next-core/src/babel.rs index 702d60da1ecd3..a3bc8dbb0279c 100644 --- a/packages/next-swc/crates/next-core/src/babel.rs +++ b/packages/next-swc/crates/next-core/src/babel.rs @@ -4,7 +4,7 @@ use turbopack_binding::{ turbo::tasks_fs::{FileSystemEntryType, FileSystemPath}, turbopack::{ core::{ - issue::{Issue, IssueExt, IssueSeverity}, + issue::{Issue, IssueExt, IssueSeverity, StyledString}, resolve::{parse::Request, pattern::Pattern, resolve}, }, node::transforms::webpack::WebpackLoaderItem, @@ -77,10 +77,11 @@ pub async fn maybe_add_babel_loader( "Unable to resolve babel-loader, but a babel config is present" .to_owned(), ), - description: Vc::cell( + description: StyledString::Text( "Make sure babel-loader is installed via your package manager." .to_owned(), - ), + ) + .cell(), severity: IssueSeverity::Fatal.cell(), } .cell() @@ -143,7 +144,7 @@ pub async fn is_babel_loader_available(project_path: Vc) -> Resu struct BabelIssue { path: Vc, title: Vc, - description: Vc, + description: Vc, severity: Vc, } @@ -170,7 +171,7 @@ impl Issue for BabelIssue { } #[turbo_tasks::function] - fn description(&self) -> Vc { + fn description(&self) -> Vc { self.description } } diff --git a/packages/next-swc/crates/next-core/src/next_config.rs b/packages/next-swc/crates/next-core/src/next_config.rs index eecbba2a34b9b..684490f7c72dd 100644 --- a/packages/next-swc/crates/next-core/src/next_config.rs +++ b/packages/next-swc/crates/next-core/src/next_config.rs @@ -12,7 +12,7 @@ use turbopack_binding::{ context::AssetContext, file_source::FileSource, ident::AssetIdent, - issue::{Issue, IssueDescriptionExt, IssueExt, IssueSeverity}, + issue::{Issue, IssueDescriptionExt, IssueExt, IssueSeverity, StyledString}, reference_type::{EntryReferenceSubType, InnerAssets, ReferenceType}, resolve::{ find_context_file, @@ -967,7 +967,7 @@ impl Issue for OutdatedConfigIssue { } #[turbo_tasks::function] - fn description(&self) -> Vc { - Vc::cell(self.description.to_string()) + fn description(&self) -> Vc { + StyledString::Text(self.description.to_string()).cell() } } diff --git a/packages/next-swc/crates/next-core/src/next_font/google/font_fallback.rs b/packages/next-swc/crates/next-core/src/next_font/google/font_fallback.rs index 749c2b88ce1d2..171c353b724fa 100644 --- a/packages/next-swc/crates/next-core/src/next_font/google/font_fallback.rs +++ b/packages/next-swc/crates/next-core/src/next_font/google/font_fallback.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use turbo_tasks::{trace::TraceRawVcs, Vc}; use turbopack_binding::{ turbo::tasks_fs::FileSystemPath, - turbopack::core::issue::{IssueExt, IssueSeverity}, + turbopack::core::issue::{IssueExt, IssueSeverity, StyledString}, }; use super::options::NextFontGoogleOptions; @@ -86,7 +86,10 @@ pub(super) async fn get_font_fallback( "Failed to find font override values for font `{}`", &options.font_family, )), - description: Vc::cell("Skipping generating a fallback font.".to_owned()), + description: StyledString::Text( + "Skipping generating a fallback font.".to_owned(), + ) + .cell(), severity: IssueSeverity::Warning.cell(), } .cell() diff --git a/packages/next-swc/crates/next-core/src/next_font/issue.rs b/packages/next-swc/crates/next-core/src/next_font/issue.rs index 1a53dfdd376c2..44c021b4c2632 100644 --- a/packages/next-swc/crates/next-core/src/next_font/issue.rs +++ b/packages/next-swc/crates/next-core/src/next_font/issue.rs @@ -1,14 +1,14 @@ use turbo_tasks::Vc; use turbopack_binding::{ turbo::tasks_fs::FileSystemPath, - turbopack::core::issue::{Issue, IssueSeverity}, + turbopack::core::issue::{Issue, IssueSeverity, StyledString}, }; #[turbo_tasks::value(shared)] pub(crate) struct NextFontIssue { pub(crate) path: Vc, pub(crate) title: Vc, - pub(crate) description: Vc, + pub(crate) description: Vc, pub(crate) severity: Vc, } @@ -35,7 +35,7 @@ impl Issue for NextFontIssue { } #[turbo_tasks::function] - fn description(&self) -> Vc { + fn description(&self) -> Vc { self.description } } diff --git a/packages/next-swc/crates/next-core/src/util.rs b/packages/next-swc/crates/next-core/src/util.rs index 3266c23a68497..baa18cd58cec0 100644 --- a/packages/next-swc/crates/next-core/src/util.rs +++ b/packages/next-swc/crates/next-core/src/util.rs @@ -12,7 +12,7 @@ use turbopack_binding::{ asset::AssetContent, environment::{ServerAddr, ServerInfo}, ident::AssetIdent, - issue::{Issue, IssueExt, IssueSeverity}, + issue::{Issue, IssueExt, IssueSeverity, StyledString}, module::Module, source::Source, virtual_source::VirtualSource, @@ -191,12 +191,13 @@ impl Issue for NextSourceConfigParsingIssue { } #[turbo_tasks::function] - fn description(&self) -> Vc { - Vc::cell( + fn description(&self) -> Vc { + StyledString::Text( "The exported configuration object in a source file need to have a very specific \ format from which some properties can be statically parsed at compiled-time." .to_string(), ) + .cell() } #[turbo_tasks::function] diff --git a/packages/next/src/build/swc/index.ts b/packages/next/src/build/swc/index.ts index 8874b1598ea43..ec11391b36490 100644 --- a/packages/next/src/build/swc/index.ts +++ b/packages/next/src/build/swc/index.ts @@ -473,12 +473,34 @@ export interface TurboEngineOptions { memoryLimit?: number } +export type StyledString = + | { + type: 'text' + value: string + } + | { + type: 'code' + value: string + } + | { + type: 'strong' + value: string + } + | { + type: 'stack' + value: StyledString[] + } + | { + type: 'line' + value: StyledString[] + } + export interface Issue { severity: string category: string filePath: string title: string - description: string + description: StyledString detail: string source?: { source: { diff --git a/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts b/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts index ec20eba12322f..31e66e8f89338 100644 --- a/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts +++ b/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts @@ -6,6 +6,7 @@ import type { WrittenEndpoint, Issue, Project, + StyledString, } from '../../../build/swc' import type { Socket } from 'net' import type { FilesystemDynamicRoute } from './filesystem' @@ -126,6 +127,7 @@ import type { ActionManifest } from '../../../build/webpack/plugins/flight-clien import { denormalizePagePath } from '../../../shared/lib/page-path/denormalize-page-path' import type { LoadableManifest } from '../../load-components' import { generateRandomActionKeyRaw } from '../../app-render/action-encryption-utils' +import { bold, green, red } from '../../../lib/picocolors' const wsServer = new ws.Server({ noServer: true }) @@ -285,44 +287,52 @@ async function startWatcher(opts: SetupOpts) { function formatIssue(issue: Issue) { const { filePath, title, description, source, detail } = issue let formattedTitle = title.replace(/\n/g, '\n ') - let message = '' let formattedFilePath = filePath .replace('[project]/', '') .replaceAll('/./', '/') .replace('\\\\?\\', '') + let message + if (source) { if (source.range) { - const { start, end } = source.range + const { start } = source.range message = `${issue.severity} - ${formattedFilePath}:${ start.line + 1 - }:${start.column} ${formattedTitle}` - - if (source.source.content) { - const { - codeFrameColumns, - } = require('next/dist/compiled/babel/code-frame') - message += - '\n\n' + - codeFrameColumns( - source.source.content, - { - start: { line: start.line + 1, column: start.column + 1 }, - end: { line: end.line + 1, column: end.column + 1 }, - }, - { forceColor: true } - ) - } + }:${start.column}` } else { message = `${issue.severity} - ${formattedFilePath} ${formattedTitle}` } } else { message = `${formattedTitle}` } + + if (source?.range && source.source.content) { + const { start, end } = source.range + const { + codeFrameColumns, + } = require('next/dist/compiled/babel/code-frame') + + message += + '\n\n' + + codeFrameColumns( + source.source.content, + { + start: { line: start.line + 1, column: start.column + 1 }, + end: { line: end.line + 1, column: end.column + 1 }, + }, + { forceColor: true } + ) + } + if (description) { - message += `\n${description.replace(/\n/g, '\n ')}` + message += `\n${renderStyledStringToErrorAnsi(description).replace( + /\n/g, + '\n ' + )}` } + if (detail) { message += `\n${detail.replace(/\n/g, '\n ')}` } @@ -2489,3 +2499,29 @@ export async function setupDevBundler(opts: SetupOpts) { } export type DevBundler = Awaited> + +function renderStyledStringToErrorAnsi(string: StyledString): string { + switch (string.type) { + case 'text': + return string.value + case 'strong': + return bold(red(string.value)) + case 'code': + return green(string.value) + case 'line': { + let line = '' + for (const styled of string.value) { + line += renderStyledStringToErrorAnsi(styled) + } + return line + '\n' + } + case 'stack': + let stack = '' + for (const styled of string.value) { + stack += renderStyledStringToErrorAnsi(styled) + '\n' + } + return stack + '\n' + default: + throw new Error('Unknown StyledString type', string) + } +}