diff --git a/developer/src/common/include/kmn_compiler_errors.h b/developer/src/common/include/kmn_compiler_errors.h index f2410f03b0..5ca5c6acfd 100644 --- a/developer/src/common/include/kmn_compiler_errors.h +++ b/developer/src/common/include/kmn_compiler_errors.h @@ -28,11 +28,13 @@ namespace CompilerErrorSeverity { // We use a namespace to stop the enum names leaking out into global namespace scope enum { - Info = 0x000000, // Informational, not necessarily a problem - Hint = 0x100000, // Something the user might want to be aware of - Warn = 0x200000, // Warning: Not great, but we can keep going. - Error = 0x300000, // Severe error where we can't continue - Fatal = 0x400000, // OOM or should-not-happen internal problem + Debug = 0x000000, // log everything including internal debug + Verbose = 0x100000, // log everything, except debug + Info = 0x200000, // Informational, not necessarily a problem + Hint = 0x300000, // Something the user might want to be aware of + Warn = 0x400000, // Warning: Not great, but we can keep going. + Error = 0x500000, // Severe error where we can't continue + Fatal = 0x600000, // OOM or should-not-happen internal problem }; }; diff --git a/developer/src/common/web/test-helpers/TestCompilerCallbacks.ts b/developer/src/common/web/test-helpers/TestCompilerCallbacks.ts index a0b0464e21..fad1dd646f 100644 --- a/developer/src/common/web/test-helpers/TestCompilerCallbacks.ts +++ b/developer/src/common/web/test-helpers/TestCompilerCallbacks.ts @@ -2,7 +2,8 @@ import * as fs from 'fs'; import * as path from 'path'; import { CompilerEvent, CompilerCallbacks, CompilerPathCallbacks, CompilerFileSystemCallbacks, CompilerError, CompilerNetAsyncCallbacks, DefaultCompilerFileSystemAsyncCallbacks, - CompilerFileSystemAsyncCallbacks } from '@keymanapp/developer-utils'; + CompilerFileSystemAsyncCallbacks, + CompilerErrorSeverity} from '@keymanapp/developer-utils'; import { fileURLToPath } from 'url'; const { TEST_SAVE_FIXTURES } = process.env; @@ -27,6 +28,10 @@ export class TestCompilerCallbacks implements CompilerCallbacks { this.messages = []; } + filteredMessages(severity: CompilerErrorSeverity = CompilerErrorSeverity.Info) { + return this.messages.filter(m => CompilerError.severity(m.code) >= severity); + } + printMessages() { if(this.messages.length) { process.stdout.write(CompilerError.formatEvent(this.messages)); diff --git a/developer/src/common/web/test-helpers/verifyCompilerMessagesObject.ts b/developer/src/common/web/test-helpers/verifyCompilerMessagesObject.ts index 7f0d9aee76..8a16de6bf1 100644 --- a/developer/src/common/web/test-helpers/verifyCompilerMessagesObject.ts +++ b/developer/src/common/web/test-helpers/verifyCompilerMessagesObject.ts @@ -31,7 +31,7 @@ export function verifyCompilerMessagesObject(source: Record, namespa // Verify each object member matches the pattern we expect if(typeof m[key] == 'function') { - const o = /^(Info|Hint|Warn|Error|Fatal)_([A-Za-z0-9_]+)$/.exec(key); + const o = /^(Debug|Verbose|Info|Hint|Warn|Error|Fatal)_([A-Za-z0-9_]+)$/.exec(key); expect(o).to.be.instanceOf(Array, `Expected member ${key} to be a valid message function name`); const c = o[1].toUpperCase() + '_' + o[2]; @@ -41,7 +41,7 @@ export function verifyCompilerMessagesObject(source: Record, namespa expect(v.code).to.equal(m[c], `Function ${key} returns the wrong code`); } else if(typeof m[key] == 'number') { - const o = /^(INFO|HINT|WARN|ERROR|FATAL)_([A-Za-z0-9_]+)$/.exec(key); + const o = /^(DEBUG|VERBOSE|INFO|HINT|WARN|ERROR|FATAL)_([A-Za-z0-9_]+)$/.exec(key); expect(o).to.be.instanceOf(Array); const f = toTitleCase(o[1]) + '_' + o[2]; @@ -53,7 +53,7 @@ export function verifyCompilerMessagesObject(source: Record, namespa // Verify severify masks if(typeof m[key] == 'number') { - const o = /^(INFO|HINT|WARN|ERROR|FATAL)_([A-Za-z0-9_]+)$/.exec(key); + const o = /^(DEBUG|VERBOSE|INFO|HINT|WARN|ERROR|FATAL)_([A-Za-z0-9_]+)$/.exec(key); expect(o).to.be.instanceOf(Array); const mask = CompilerError.formatSeverity(m[key]).toUpperCase(); diff --git a/developer/src/common/web/utils/src/compiler-interfaces.ts b/developer/src/common/web/utils/src/compiler-interfaces.ts index 0ffc828f1d..4cb9ae3c22 100644 --- a/developer/src/common/web/utils/src/compiler-interfaces.ts +++ b/developer/src/common/web/utils/src/compiler-interfaces.ts @@ -21,14 +21,18 @@ export interface CompilerEvent { }; export enum CompilerErrorSeverity { - Info = 0x000000, // Informational, not necessarily a problem - Hint = 0x100000, // Something the user might want to be aware of - Warn = 0x200000, // Warning: Not great, but we can keep going. - Error = 0x300000, // Severe error where we can't continue - Fatal = 0x400000, // OOM or should-not-happen internal problem + Debug = 0x000000, // log everything including internal debug + Verbose = 0x100000, // log everything, except debug + Info = 0x200000, // Informational, not necessarily a problem + Hint = 0x300000, // Something the user might want to be aware of + Warn = 0x400000, // Warning: Not great, but we can keep going. + Error = 0x500000, // Severe error where we can't continue + Fatal = 0x600000, // OOM or should-not-happen internal problem }; export const CompilerErrorSeverityValues = [ + CompilerErrorSeverity.Debug, + CompilerErrorSeverity.Verbose, CompilerErrorSeverity.Info, CompilerErrorSeverity.Hint, CompilerErrorSeverity.Warn, @@ -48,6 +52,8 @@ export enum CompilerErrorMask { }; const errorSeverityName = { + [CompilerErrorSeverity.Debug]: 'debug', + [CompilerErrorSeverity.Verbose]: 'verbose', [CompilerErrorSeverity.Info]: 'info', [CompilerErrorSeverity.Hint]: 'hint', [CompilerErrorSeverity.Warn]: 'warn', @@ -415,8 +421,9 @@ export const ALL_COMPILER_LOG_LEVELS = [ 'error', /// Only errors emitted 'warn', /// Errors + warnings 'hint', /// Errors + warnings + hints - 'info', /// All messages: errors + warnings + hints + info - 'debug' /// All messages: errors + warnings + hints + info, plus debug logs + 'info', /// All normal messages: errors + warnings + hints + info + 'verbose', /// All messages + verbose logging + 'debug', /// All messages + verbose + internal debug ] as const; type CompilerLogLevelTuple = typeof ALL_COMPILER_LOG_LEVELS; @@ -428,7 +435,8 @@ export const compilerLogLevelToSeverity: {[index in CompilerLogLevel]: number} = 'warn': CompilerErrorSeverity.Warn, 'hint': CompilerErrorSeverity.Hint, 'info': CompilerErrorSeverity.Info, - 'debug': CompilerErrorSeverity.Info + 'verbose': CompilerErrorSeverity.Verbose, + 'debug': CompilerErrorSeverity.Debug, }; export const ALL_COMPILER_LOG_FORMATS = [ diff --git a/developer/src/kmc-copy/src/cloud.ts b/developer/src/kmc-copy/src/cloud.ts index 7b3ef1ff11..a65284933e 100644 --- a/developer/src/kmc-copy/src/cloud.ts +++ b/developer/src/kmc-copy/src/cloud.ts @@ -63,9 +63,10 @@ export class KeymanCloudSource { } public async downloadFolderFromGitHub(ref: GitHubRef): Promise<{filename:string,type:'dir'|'file'}[]> { - // this.callbacks.reportMessage(CopierMessages.Info_DownloadingFile({ref})); // TODO-COPY: verbose mode support const url = `https://api.github.com/repos/${ref.owner}/${ref.repo}/contents/${ref.path}?ref=${ref.branch}`; + this.callbacks.reportMessage(CopierMessages.Verbose_DownloadingFolder({path:ref.path, url})); + let folder: any; try { folder = await this.callbacks.net.fetchJSON(url); @@ -94,6 +95,7 @@ export class KeymanCloudSource { } const url = `https://raw.githubusercontent.com/${ref.owner}/${ref.repo}/refs/heads/${ref.branch}${ref.path}`; + this.callbacks.reportMessage(CopierMessages.Verbose_DownloadingFile({filename:this.callbacks.path.basename(ref.path), url})); try { return await this.callbacks.net.fetchBlob(url); diff --git a/developer/src/kmc-copy/src/copier-messages.ts b/developer/src/kmc-copy/src/copier-messages.ts index 78a948ec79..8b25f93b19 100644 --- a/developer/src/kmc-copy/src/copier-messages.ts +++ b/developer/src/kmc-copy/src/copier-messages.ts @@ -7,6 +7,7 @@ import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m, CompilerMessageDef as def, CompilerMessageSpecWithException } from "@keymanapp/developer-utils"; const Namespace = CompilerErrorNamespace.Copier; +const SevVerbose = CompilerErrorSeverity.Verbose | Namespace; const SevInfo = CompilerErrorSeverity.Info | Namespace; // const SevHint = CompilerErrorSeverity.Hint | Namespace; const SevWarn = CompilerErrorSeverity.Warn | Namespace; @@ -198,4 +199,16 @@ export class CopierMessages { the provided error details for more details.` ); + static VERBOSE_DownloadingFile = SevVerbose | 0x001C; + static Verbose_DownloadingFile = (o:{filename: string, url: string}) => m( + this.VERBOSE_DownloadingFile, + `Downloading '${def(o.filename)}' from '${def(o.url)}'`, + ); + + static VERBOSE_DownloadingFolder = SevVerbose | 0x001D; + static Verbose_DownloadingFolder = (o:{path: string, url: string}) => m( + this.VERBOSE_DownloadingFolder, + `Downloading folder '${def(o.path)}' from '${def(o.url)}'`, + ); + }; diff --git a/developer/src/kmc-copy/test/copier.tests.ts b/developer/src/kmc-copy/test/copier.tests.ts index e468bbd79c..7f4dccf535 100644 --- a/developer/src/kmc-copy/test/copier.tests.ts +++ b/developer/src/kmc-copy/test/copier.tests.ts @@ -315,7 +315,7 @@ describe('KeymanProjectCopier', function() { // assert.isOk(result); - assert.isEmpty(callbacks.messages); + assert.isEmpty(callbacks.filteredMessages()); if(TEST_SAVE_ARTIFACTS) { assert.isTrue(await copier.write(result.artifacts)); @@ -377,7 +377,7 @@ describe('KeymanProjectCopier', function() { // We should have no messages and a successful result assert.isOk(result); - assert.isEmpty(callbacks.messages); + assert.isEmpty(callbacks.filteredMessages()); // TODO-COPY: verify outcome using pattern above @@ -404,7 +404,7 @@ describe('KeymanProjectCopier', function() { // We should have no messages and a successful result assert.isOk(result); - assert.isEmpty(callbacks.messages); + assert.isEmpty(callbacks.filteredMessages()); // TODO-COPY: verify outcome using pattern above diff --git a/developer/src/kmc/src/commands/messageCommand.ts b/developer/src/kmc/src/commands/messageCommand.ts index ee568dad9c..257eacc913 100644 --- a/developer/src/kmc/src/commands/messageCommand.ts +++ b/developer/src/kmc/src/commands/messageCommand.ts @@ -178,7 +178,7 @@ function allMessageDetails(): CompilerMessageDetail[] { const toTitleCase = (s: string) => s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase(); function getMessageDetail(cls: any, id: string, escapeMarkdown: boolean): CompilerEvent { - const o = /^(INFO|HINT|WARN|ERROR|FATAL)_([A-Za-z0-9_]+)$/.exec(id); + const o = /^(DEBUG|VERBOSE|INFO|HINT|WARN|ERROR|FATAL)_([A-Za-z0-9_]+)$/.exec(id); if(!o) { throw new Error(`Unexpected compiler message ${id}, does not match message error format`); } diff --git a/developer/src/kmc/src/util/NodeCompilerCallbacks.ts b/developer/src/kmc/src/util/NodeCompilerCallbacks.ts index fd5f29d212..f3cdf1e7b2 100644 --- a/developer/src/kmc/src/util/NodeCompilerCallbacks.ts +++ b/developer/src/kmc/src/util/NodeCompilerCallbacks.ts @@ -23,6 +23,8 @@ const severityColors: {[value in CompilerErrorSeverity]: chalk.Chalk} = { [CompilerErrorSeverity.Warn]: color.hex('FFA500'), // orange [CompilerErrorSeverity.Error]: color.redBright, [CompilerErrorSeverity.Fatal]: color.redBright, + [CompilerErrorSeverity.Verbose]: color.gray, + [CompilerErrorSeverity.Debug]: color.blueBright, }; /** diff --git a/developer/src/tike/compile/Keyman.Developer.System.KmcWrapper.pas b/developer/src/tike/compile/Keyman.Developer.System.KmcWrapper.pas index 9778119e9f..24c070a5e8 100644 --- a/developer/src/tike/compile/Keyman.Developer.System.KmcWrapper.pas +++ b/developer/src/tike/compile/Keyman.Developer.System.KmcWrapper.pas @@ -114,7 +114,7 @@ begin state := plsFatal; Result := False; end - else // assume msgType = 'info' + else // assume msgType = 'info' (fine also for 'verbose', 'debug') state := plsInfo; FGlobalProject.Log(state, msgFilename, msgText, msgCode, msgLine); end