Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "Add opt-in declaration source map generation so editors can resolve go-to-definition from generated typings to the original source file.",
"type": "minor",
"packageName": "@rushstack/heft-localization-typings-plugin"
}
],
"packageName": "@rushstack/heft-localization-typings-plugin",
"email": "mdelgaudio_microsoft@users.noreply.github.com"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "Add opt-in declaration source map generation so editors can resolve go-to-definition from generated typings to the original source file.",
"type": "minor",
"packageName": "@rushstack/localization-utilities"
}
],
"packageName": "@rushstack/localization-utilities",
"email": "mdelgaudio_microsoft@users.noreply.github.com"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "Add opt-in declaration source map generation so editors can resolve go-to-definition from generated typings to the original source file.",
"type": "minor",
"packageName": "@rushstack/typings-generator"
}
],
"packageName": "@rushstack/typings-generator",
"email": "mdelgaudio_microsoft@users.noreply.github.com"
}
2 changes: 2 additions & 0 deletions common/reviews/api/localization-utilities.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
```ts

import { IExportAsDefaultOptions } from '@rushstack/typings-generator';
import type { ISourcePosition } from '@rushstack/typings-generator';
import type { ITerminal } from '@rushstack/terminal';
import { ITypingsGeneratorBaseOptions } from '@rushstack/typings-generator';
import { NewlineKind } from '@rushstack/node-core-library';
Expand All @@ -31,6 +32,7 @@ export interface ILocalizationFile {
export interface ILocalizedString {
// (undocumented)
comment?: string;
sourcePosition?: ISourcePosition;
// (undocumented)
value: string;
}
Expand Down
32 changes: 29 additions & 3 deletions common/reviews/api/typings-generator.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@

import { ITerminal } from '@rushstack/terminal';

// @public
export interface IDeclarationMapping {
generatedColumn: number;
generatedLine: number;
sourcePosition: ISourcePosition;
}

// @public (undocumented)
export interface IExportAsDefaultOptions {
// @deprecated (undocumented)
Expand All @@ -15,6 +22,20 @@ export interface IExportAsDefaultOptions {
valueDocumentationComment?: string;
}

// @public
export interface IGeneratedTypings {
declarationMappings?: readonly IDeclarationMapping[];
typingsData: string;
}

// @public
export interface ISourcePosition {
// (undocumented)
column: number;
// (undocumented)
line: number;
}

// @public (undocumented)
export interface IStringValuesTypingsGeneratorBaseOptions {
exportAsDefault?: boolean | IExportAsDefaultOptions;
Expand All @@ -36,6 +57,7 @@ export interface IStringValueTyping {
comment?: string;
// (undocumented)
exportName: string;
sourcePosition?: ISourcePosition;
}

// @public (undocumented)
Expand All @@ -47,6 +69,7 @@ export interface IStringValueTypings {

// @public (undocumented)
export interface ITypingsGeneratorBaseOptions {
generateDeclarationMaps?: boolean;
// (undocumented)
generatedTsFolder: string;
// (undocumented)
Expand Down Expand Up @@ -84,6 +107,9 @@ export interface ITypingsGeneratorOptionsWithoutReadFile<TTypingsResult = string
// @public (undocumented)
export type ReadFile<TFileContents = string> = (filePath: string, relativePath: string) => Promise<TFileContents> | TFileContents;

// @public
export function serializeDeclarationMap(mappings: readonly IDeclarationMapping[], generatedFileName: string, sourcePath: string, generatedLineOffset: number): string;

// @public
export class StringValuesTypingsGenerator<TFileContents = string> extends TypingsGenerator<TFileContents> {
constructor(options: TFileContents extends string ? IStringValuesTypingsGeneratorOptions<TFileContents> : never);
Expand All @@ -92,15 +118,15 @@ export class StringValuesTypingsGenerator<TFileContents = string> extends Typing

// @public
export class TypingsGenerator<TFileContents = string> {
constructor(options: TFileContents extends string ? ITypingsGeneratorOptions<string | undefined, TFileContents> : never);
constructor(options: ITypingsGeneratorOptionsWithCustomReadFile<string | undefined, TFileContents>);
constructor(options: TFileContents extends string ? ITypingsGeneratorOptions<string | IGeneratedTypings | undefined, TFileContents> : never);
constructor(options: ITypingsGeneratorOptionsWithCustomReadFile<string | IGeneratedTypings | undefined, TFileContents>);
generateTypingsAsync(relativeFilePaths?: string[]): Promise<void>;
// (undocumented)
getOutputFilePaths(relativePath: string): string[];
readonly ignoredFileGlobs: readonly string[];
readonly inputFileGlob: string;
// (undocumented)
protected readonly _options: ITypingsGeneratorOptionsWithCustomReadFile<string | undefined, TFileContents>;
protected readonly _options: ITypingsGeneratorOptionsWithCustomReadFile<string | IGeneratedTypings | undefined, TFileContents>;
registerDependency(consumer: string, rawDependency: string): void;
// (undocumented)
runWatcherAsync(): Promise<void>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ export interface ILocalizationTypingsPluginOptions {
* An array of string names to ignore when generating typings.
*/
stringNamesToIgnore?: string[];

/**
* If true, a `.d.ts.map` file is emitted next to each generated `.d.ts` file. This allows editors
* to resolve "go to definition" on a localized string to its declaration in the source
* localization file, instead of to the generated typings.
*
* @defaultValue false
*/
generateDeclarationMaps?: boolean;
}

const PLUGIN_NAME: 'localization-typings-plugin' = 'localization-typings-plugin';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@
"items": {
"type": "string"
}
},

"generateDeclarationMaps": {
"type": "boolean",
"description": "If true, a \".d.ts.map\" file is emitted next to each generated \".d.ts\" file, allowing editors to resolve \"go to definition\" to the source localization file instead of the generated typings."
}
}
}
3 changes: 2 additions & 1 deletion libraries/localization-utilities/src/TypingsGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ export class TypingsGenerator extends StringValuesTypingsGenerator {

typings.push({
exportName: stringName,
comment
comment,
sourcePosition: value.sourcePosition
});
}

Expand Down
9 changes: 9 additions & 0 deletions libraries/localization-utilities/src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.

import type { ISourcePosition } from '@rushstack/typings-generator';

/**
* Options for the pseudolocale library.
*
Expand Down Expand Up @@ -32,6 +34,13 @@ export interface ILocalizationFile {
export interface ILocalizedString {
value: string;
comment?: string;

/**
* The zero-based position of this string's declaration in the source file, when the parser is
* able to determine it. This is used to emit declaration source maps so that editors can
* navigate from generated typings back to the string declaration.
*/
sourcePosition?: ISourcePosition;
}

/**
Expand Down
5 changes: 4 additions & 1 deletion libraries/localization-utilities/src/parsers/parseResx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,10 @@ function _readDataElement(

return {
value: value || '',
comment
comment,
// xmldoc's `column` refers to the end of the element's open tag rather than its start, so the
// beginning of the line is used instead. That reliably lands an editor on the <data> element.
sourcePosition: { line: dataElement.line, column: 0 }
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ exports[`parseResx correctly ignores a string: Loc file 1`] = `
Object {
"foo": Object {
"comment": "Foo",
"sourcePosition": Object {
"column": 0,
"line": 57,
},
"value": "foo",
},
}
Expand All @@ -28,6 +32,10 @@ exports[`parseResx fails to parse a RESX file with a duplicate string: Loc file
Object {
"stringA": Object {
"comment": undefined,
"sourcePosition": Object {
"column": 0,
"line": 5,
},
"value": "Another string",
},
}
Expand All @@ -43,6 +51,10 @@ exports[`parseResx ignoreMissingResxComments when set to false, warns on a missi
Object {
"stringWithoutAComment": Object {
"comment": undefined,
"sourcePosition": Object {
"column": 0,
"line": 2,
},
"value": "String without a comment",
},
}
Expand All @@ -58,6 +70,10 @@ exports[`parseResx ignoreMissingResxComments when set to true, ignores a missing
Object {
"stringWithoutAComment": Object {
"comment": undefined,
"sourcePosition": Object {
"column": 0,
"line": 2,
},
"value": "String without a comment",
},
}
Expand All @@ -69,6 +85,10 @@ exports[`parseResx ignoreMissingResxComments when set to undefined, warns on a m
Object {
"stringWithoutAComment": Object {
"comment": undefined,
"sourcePosition": Object {
"column": 0,
"line": 2,
},
"value": "String without a comment",
},
}
Expand All @@ -80,10 +100,18 @@ exports[`parseResx parses a valid file with a schema: Loc file 1`] = `
Object {
"bar": Object {
"comment": "Bar",
"sourcePosition": Object {
"column": 0,
"line": 61,
},
"value": "bar",
},
"foo": Object {
"comment": "Foo",
"sourcePosition": Object {
"column": 0,
"line": 57,
},
"value": "foo",
},
}
Expand All @@ -95,6 +123,10 @@ exports[`parseResx parses a valid file with quotemarks: Loc file 1`] = `
Object {
"stringWithQuotes": Object {
"comment": "RESX string with quotemarks",
"sourcePosition": Object {
"column": 0,
"line": 2,
},
"value": "\\"RESX string with quotemarks\\"",
},
}
Expand All @@ -106,6 +138,10 @@ exports[`parseResx prints an error on invalid XML: Loc file 1`] = `
Object {
"foo": Object {
"comment": "Foo",
"sourcePosition": Object {
"column": 0,
"line": 2,
},
"value": "foo",
},
}
Expand All @@ -121,6 +157,10 @@ exports[`parseResx resxNewlineNormalization when set to CrLf, normalizes to CrLf
Object {
"stringWithTabsAndNewlines": Object {
"comment": "RESX string with newlines and tabs",
"sourcePosition": Object {
"column": 0,
"line": 2,
},
"value": "
RESX string with newlines and tabs
",
Expand All @@ -134,6 +174,10 @@ exports[`parseResx resxNewlineNormalization when set to Lf, normalizes to Lf: Lo
Object {
"stringWithTabsAndNewlines": Object {
"comment": "RESX string with newlines and tabs",
"sourcePosition": Object {
"column": 0,
"line": 2,
},
"value": "
RESX string with newlines and tabs
",
Expand Down
Loading