Move compiler utils to `/utils` exports (#2919)

Provide a new exports `/utils` where we can export utils that are
commonly used in libraries and emitters but not tied to typespec
directly(deepClone, deepEquals, etc.)
This commit is contained in:
Timothee Guerin 2024-02-23 09:48:19 -08:00 коммит произвёл GitHub
Родитель 753ca1ad9b
Коммит 15702e82f4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
48 изменённых файлов: 238 добавлений и 194 удалений

Просмотреть файл

@ -0,0 +1,8 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: deprecation
packages:
- "@typespec/compiler"
---
[API] Create a new export `@typespec/compiler/utils` exports. Deprecate export from `@typespec/compiler` of utils like `DuplicateTracker`, `Queue`, `createTwoKeyMap`, etc.

Просмотреть файл

@ -0,0 +1,6 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: internal
packages:
- "@typespec/openapi3"
---

Просмотреть файл

@ -0,0 +1,8 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: fix
packages:
- "@typespec/eslint-config-typespec"
---
Exclude `temp` folder

Просмотреть файл

@ -25,6 +25,10 @@
"types": "./dist/src/index.d.ts",
"default": "./dist/src/index.js"
},
"./utils": {
"types": "./dist/src/utils/index.d.ts",
"default": "./dist/src/utils/index.js"
},
"./testing": {
"types": "./dist/src/testing/index.d.ts",
"default": "./dist/src/testing/index.js"

Просмотреть файл

@ -1,9 +1,9 @@
import { createSourceFile } from "../core/diagnostics.js";
import { createDiagnostic } from "../core/messages.js";
import { getDirectoryPath, isPathAbsolute, joinPaths, resolvePath } from "../core/path-utils.js";
import { createJSONSchemaValidator } from "../core/schema-validator.js";
import { createSourceFile } from "../core/source-file.js";
import { CompilerHost, Diagnostic, NoTarget, SourceFile } from "../core/types.js";
import { deepClone, deepFreeze, doIO, omitUndefined } from "../core/util.js";
import { deepClone, deepFreeze, doIO, omitUndefined } from "../utils/misc.js";
import { getLocationInYamlScript } from "../yaml/index.js";
import { parseYaml } from "../yaml/parser.js";
import { YamlScript } from "../yaml/types.js";

Просмотреть файл

@ -1,7 +1,7 @@
import { createDiagnosticCollector, getDirectoryPath, normalizePath } from "../core/index.js";
import { CompilerOptions } from "../core/options.js";
import { CompilerHost, Diagnostic } from "../core/types.js";
import { deepClone, doIO, omitUndefined } from "../core/util.js";
import { deepClone, doIO, omitUndefined } from "../utils/misc.js";
import { expandConfigVariables } from "./config-interpolation.js";
import { loadTypeSpecConfigForPath, validateConfigPathsAbsolute } from "./config-loader.js";
import { EmitterOptions, TypeSpecConfig } from "./types.js";

Просмотреть файл

@ -1,3 +1,4 @@
import { mutate } from "../utils/misc.js";
import { compilerAssert } from "./diagnostics.js";
import { getLocationContext } from "./helpers/index.js";
import { visitChildren } from "./parser.js";
@ -35,7 +36,6 @@ import {
UnionStatementNode,
UsingStatementNode,
} from "./types.js";
import { mutate } from "./util.js";
// Use a regular expression to define the prefix for TypeSpec-exposed functions
// defined in JavaScript modules

Просмотреть файл

@ -1,4 +1,5 @@
import { $docFromComment, getIndexer } from "../lib/decorators.js";
import { MultiKeyMap, Mutable, createRekeyableMap, isArray, mutate } from "../utils/misc.js";
import { createSymbol, createSymbolTable } from "./binder.js";
import { getDeprecationDetails, markDeprecated } from "./deprecation.js";
import { ProjectionError, compilerAssert, reportDeprecated } from "./diagnostics.js";
@ -150,7 +151,6 @@ import {
ValueType,
VoidType,
} from "./types.js";
import { MultiKeyMap, Mutable, createRekeyableMap, isArray, mutate } from "./util.js";
export type CreateTypeProps = Omit<Type, "isFinished" | keyof TypePrototype>;

Просмотреть файл

@ -1,9 +1,9 @@
import { resolveCompilerOptions } from "../../../../config/config-to-options.js";
import { omitUndefined } from "../../../../utils/misc.js";
import { createDiagnosticCollector } from "../../../diagnostics.js";
import { CompilerOptions } from "../../../options.js";
import { resolvePath } from "../../../path-utils.js";
import { CompilerHost, Diagnostic } from "../../../types.js";
import { omitUndefined } from "../../../util.js";
export interface CompileCliArgs {
"output-dir"?: string;

Просмотреть файл

@ -7,8 +7,8 @@ try {
}
import yargs from "yargs";
import { typespecVersion } from "../../utils/misc.js";
import { installTypeSpecDependencies } from "../install.js";
import { typespecVersion } from "../util.js";
import { compileAction } from "./actions/compile/compile.js";
import { formatAction } from "./actions/format.js";
import { printInfoAction } from "./actions/info.js";

Просмотреть файл

@ -1,6 +1,6 @@
import { CharCode } from "./charcode.js";
import { formatLog } from "./logger/index.js";
import type { Program } from "./program.js";
import { createSourceFile } from "./source-file.js";
import {
Diagnostic,
DiagnosticResult,
@ -9,7 +9,6 @@ import {
Node,
NodeFlags,
NoTarget,
SourceFile,
SourceLocation,
SymbolFlags,
SyntaxKind,
@ -52,42 +51,6 @@ export function formatDiagnostic(diagnostic: Diagnostic) {
);
}
export function createSourceFile(text: string, path: string): SourceFile {
let lineStarts: number[] | undefined = undefined;
return {
text,
path,
getLineStarts,
getLineAndCharacterOfPosition,
};
function getLineStarts() {
return (lineStarts = lineStarts ?? scanLineStarts(text));
}
function getLineAndCharacterOfPosition(position: number) {
const starts = getLineStarts();
let line = binarySearch(starts, position);
// When binarySearch returns < 0 indicating that the value was not found, it
// returns the bitwise complement of the index where the value would need to
// be inserted to keep the array sorted. So flipping the bits back to this
// positive index tells us what the line number would be if we were to
// create a new line starting at the given position, and subtracting 1 from
// that therefore gives us the line number we're after.
if (line < 0) {
line = ~line - 1;
}
return {
line,
character: position - starts[line],
};
}
}
export interface SourceLocationOptions {
/**
* If trying to resolve the location of a type with an ID, show the location of the ID node instead of the entire type.
@ -241,55 +204,6 @@ export function compilerAssert(
throw new Error(message);
}
function scanLineStarts(text: string): number[] {
const starts = [];
let start = 0;
let pos = 0;
while (pos < text.length) {
const ch = text.charCodeAt(pos);
pos++;
switch (ch) {
case CharCode.CarriageReturn:
if (text.charCodeAt(pos) === CharCode.LineFeed) {
pos++;
}
// fallthrough
case CharCode.LineFeed:
starts.push(start);
start = pos;
break;
}
}
starts.push(start);
return starts;
}
/**
* Search sorted array of numbers for the given value. If found, return index
* in array where value was found. If not found, return a negative number that
* is the bitwise complement of the index where value would need to be inserted
* to keep the array sorted.
*/
function binarySearch(array: readonly number[], value: number) {
let low = 0;
let high = array.length - 1;
while (low <= high) {
const middle = low + ((high - low) >> 1);
const v = array[middle];
if (v < value) {
low = middle + 1;
} else if (v > value) {
high = middle - 1;
} else {
return middle;
}
}
return ~low;
}
/**
* Assert that the input type has one of the kinds provided
*/

Просмотреть файл

@ -1,7 +1,7 @@
import { doIO, loadFile, resolveTspMain } from "../utils/misc.js";
import { DiagnosticHandler } from "./diagnostics.js";
import { resolvePath } from "./path-utils.js";
import { CompilerHost } from "./types.js";
import { doIO, loadFile, resolveTspMain } from "./util.js";
/**
* Resolve the path to the main file

Просмотреть файл

@ -1,9 +1,10 @@
import { Discriminator, getDiscriminatedTypes } from "../../lib/decorators.js";
import { DuplicateTracker } from "../../utils/duplicate-tracker.js";
import { isDefined } from "../../utils/misc.js";
import { createDiagnostic } from "../messages.js";
import { Program } from "../program.js";
import { isTemplateDeclarationOrInstance } from "../type-utils.js";
import { Diagnostic, Model, Type, Union } from "../types.js";
import { DuplicateTracker, isDefined } from "../util.js";
export interface DiscriminatedUnion {
propertyName: string;

Просмотреть файл

@ -1,5 +1,5 @@
import { isArray } from "../../utils/misc.js";
import { Enum, Interface, Model, Namespace, Operation, Tuple, Type, Union } from "../types.js";
import { isArray } from "../util.js";
// prettier-ignore
export enum UsageFlags {

Просмотреть файл

@ -25,12 +25,6 @@ export * from "./path-utils.js";
export * from "./program.js";
export * from "./scanner.js";
export * from "./semantic-walker.js";
export { createSourceFile, getSourceFileKindFromExt } from "./source-file.js";
export * from "./type-utils.js";
export * from "./types.js";
export {
DuplicateTracker,
Queue,
TwoLevelMap,
createRekeyableMap,
getSourceFileKindFromExt,
} from "./util.js";

Просмотреть файл

@ -1,12 +1,12 @@
import { realpath } from "fs";
import { mkdir, readdir, readFile, rm, stat, writeFile } from "fs/promises";
import { fileURLToPath, pathToFileURL } from "url";
import { createSourceFile } from "./diagnostics.js";
import { findProjectRoot } from "../utils/misc.js";
import { fetch } from "./fetch.js";
import { createConsoleSink } from "./logger/index.js";
import { joinPaths } from "./path-utils.js";
import { createSourceFile, getSourceFileKindFromExt } from "./source-file.js";
import { CompilerHost, RmOptions } from "./types.js";
import { findProjectRoot, getSourceFileKindFromExt } from "./util.js";
export const CompilerPackageRoot = (await findProjectRoot(stat, fileURLToPath(import.meta.url)))!;

Просмотреть файл

@ -1,3 +1,4 @@
import { isArray, mutate } from "../utils/misc.js";
import { trim } from "./charcode.js";
import { compilerAssert } from "./diagnostics.js";
import { CompilerDiagnostics, createDiagnostic } from "./messages.js";
@ -109,7 +110,6 @@ import {
ValueOfExpressionNode,
VoidKeywordNode,
} from "./types.js";
import { isArray, mutate } from "./util.js";
/**
* Callback to parse each element in a delimited list

Просмотреть файл

@ -2,9 +2,18 @@ import { EmitterOptions } from "../config/types.js";
import { createAssetEmitter } from "../emitter-framework/asset-emitter.js";
import { validateEncodedNamesConflicts } from "../lib/encoded-names.js";
import { MANIFEST } from "../manifest.js";
import {
deepEquals,
doIO,
findProjectRoot,
isDefined,
mapEquals,
mutate,
resolveTspMain,
} from "../utils/misc.js";
import { createBinder } from "./binder.js";
import { Checker, createChecker } from "./checker.js";
import { compilerAssert, createSourceFile } from "./diagnostics.js";
import { compilerAssert } from "./diagnostics.js";
import {
resolveTypeSpecEntrypoint,
resolveTypeSpecEntrypointForDir,
@ -26,6 +35,7 @@ import { CompilerOptions } from "./options.js";
import { isImportStatement, parse, parseStandaloneTypeReference } from "./parser.js";
import { getDirectoryPath, joinPaths } from "./path-utils.js";
import { createProjector } from "./projector.js";
import { createSourceFile } from "./source-file.js";
import {
CompilerHost,
Diagnostic,
@ -56,15 +66,6 @@ import {
TypeSpecLibrary,
TypeSpecScriptNode,
} from "./types.js";
import {
deepEquals,
doIO,
findProjectRoot,
isDefined,
mapEquals,
mutate,
resolveTspMain,
} from "./util.js";
export interface ProjectedProgram extends Program {
projector: Projector;

Просмотреть файл

@ -1,6 +1,7 @@
import { createRekeyableMap, mutate } from "../utils/misc.js";
import { finishTypeForProgram } from "./checker.js";
import { compilerAssert } from "./diagnostics.js";
import { createStateAccessors, isProjectedProgram, Program, ProjectedProgram } from "./program.js";
import { Program, ProjectedProgram, createStateAccessors, isProjectedProgram } from "./program.js";
import { getParentTemplateNode, isNeverType, isTemplateInstance } from "./type-utils.js";
import {
DecoratorApplication,
@ -21,7 +22,6 @@ import {
Union,
UnionVariant,
} from "./types.js";
import { createRekeyableMap, mutate } from "./util.js";
/**
* Creates a projector which returns a projected view of either the global namespace or the

Просмотреть файл

@ -15,8 +15,9 @@ import {
isWhiteSpaceSingleLine,
utf16CodeUnits,
} from "./charcode.js";
import { DiagnosticHandler, compilerAssert, createSourceFile } from "./diagnostics.js";
import { DiagnosticHandler, compilerAssert } from "./diagnostics.js";
import { CompilerDiagnostics, createDiagnostic } from "./messages.js";
import { createSourceFile } from "./source-file.js";
import { DiagnosticReport, SourceFile, TextRange } from "./types.js";
// All conflict markers consist of the same character repeated seven times. If it is

Просмотреть файл

@ -0,0 +1,99 @@
import { CharCode } from "./charcode.js";
import { getAnyExtensionFromPath } from "./path-utils.js";
import type { SourceFile, SourceFileKind } from "./types.js";
export function createSourceFile(text: string, path: string): SourceFile {
let lineStarts: number[] | undefined = undefined;
return {
text,
path,
getLineStarts,
getLineAndCharacterOfPosition,
};
function getLineStarts() {
return (lineStarts = lineStarts ?? scanLineStarts(text));
}
function getLineAndCharacterOfPosition(position: number) {
const starts = getLineStarts();
let line = binarySearch(starts, position);
// When binarySearch returns < 0 indicating that the value was not found, it
// returns the bitwise complement of the index where the value would need to
// be inserted to keep the array sorted. So flipping the bits back to this
// positive index tells us what the line number would be if we were to
// create a new line starting at the given position, and subtracting 1 from
// that therefore gives us the line number we're after.
if (line < 0) {
line = ~line - 1;
}
return {
line,
character: position - starts[line],
};
}
}
export function getSourceFileKindFromExt(path: string): SourceFileKind | undefined {
const ext = getAnyExtensionFromPath(path);
if (ext === ".js" || ext === ".mjs") {
return "js";
} else if (ext === ".tsp" || ext === ".cadl") {
return "typespec";
} else {
return undefined;
}
}
function scanLineStarts(text: string): number[] {
const starts = [];
let start = 0;
let pos = 0;
while (pos < text.length) {
const ch = text.charCodeAt(pos);
pos++;
switch (ch) {
case CharCode.CarriageReturn:
if (text.charCodeAt(pos) === CharCode.LineFeed) {
pos++;
}
// fallthrough
case CharCode.LineFeed:
starts.push(start);
start = pos;
break;
}
}
starts.push(start);
return starts;
}
/**
* Search sorted array of numbers for the given value. If found, return index
* in array where value was found. If not found, return a negative number that
* is the bitwise complement of the index where value would need to be inserted
* to keep the array sorted.
*/
function binarySearch(array: readonly number[], value: number) {
let low = 0;
let high = array.length - 1;
while (low <= high) {
const middle = low + ((high - low) >> 1);
const v = array[middle];
if (v < value) {
low = middle + 1;
} else if (v > value) {
high = middle - 1;
} else {
return middle;
}
}
return ~low;
}

Просмотреть файл

@ -2,7 +2,7 @@ import type { ParserOptions } from "prettier";
import { getSourceLocation } from "../core/diagnostics.js";
import { parse as typespecParse, visitChildren } from "../core/parser.js";
import { Diagnostic, Node, SyntaxKind, TypeSpecScriptNode } from "../core/types.js";
import { mutate } from "../core/util.js";
import { mutate } from "../utils/misc.js";
export function parse(text: string, options: ParserOptions<any>): TypeSpecScriptNode {
const result = typespecParse(text, { comments: true, docs: true });

Просмотреть файл

@ -5,5 +5,17 @@ export * from "./server/index.js";
import * as formatter from "./formatter/index.js";
export const TypeSpecPrettierPlugin = formatter;
// DO NOT ADD ANYMORE EXPORTS HERE, this is for backcompat. Utils should be exported from the utils folder.
export {
/** @deprecated use import from @typespec/compiler/utils */
DuplicateTracker,
/** @deprecated use import from @typespec/compiler/utils */
Queue,
/** @deprecated use import from @typespec/compiler/utils */
TwoLevelMap,
/** @deprecated use import from @typespec/compiler/utils */
createRekeyableMap,
} from "./utils/index.js";
/** @deprecated Use TypeSpecPrettierPlugin */
export const CadlPrettierPlugin = TypeSpecPrettierPlugin;

Просмотреть файл

@ -6,8 +6,8 @@ import { createDiagnostic } from "../core/messages.js";
import { getBaseFileName, getDirectoryPath } from "../core/path-utils.js";
import { createJSONSchemaValidator } from "../core/schema-validator.js";
import { CompilerHost, Diagnostic, NoTarget, SourceFile } from "../core/types.js";
import { readUrlOrPath } from "../core/util.js";
import { MANIFEST } from "../manifest.js";
import { readUrlOrPath } from "../utils/misc.js";
import { TypeSpecCoreTemplates } from "./core-templates.js";
import { InitTemplate, InitTemplateLibrarySpec, InitTemplateSchema } from "./init-template.js";
import { makeScaffoldingConfig, normalizeLibrary, scaffoldNewProject } from "./scaffold.js";

Просмотреть файл

@ -4,7 +4,7 @@ import { formatTypeSpec } from "../core/formatter.js";
import { NodePackage } from "../core/module-resolver.js";
import { getDirectoryPath, joinPaths } from "../core/path-utils.js";
import { CompilerHost } from "../core/types.js";
import { readUrlOrPath, resolveRelativeUrlOrPath } from "../core/util.js";
import { readUrlOrPath, resolveRelativeUrlOrPath } from "../utils/misc.js";
import { FileTemplatingContext, createFileTemplatingContext, render } from "./file-templating.js";
import {
InitTemplate,

Просмотреть файл

@ -2,7 +2,7 @@ import { reportDiagnostic } from "../core/messages.js";
import { parseMimeType } from "../core/mime-type.js";
import { Program } from "../core/program.js";
import { DecoratorContext, Enum, Model, Type, Union } from "../core/types.js";
import { DuplicateTracker } from "../core/util.js";
import { DuplicateTracker } from "../utils/index.js";
function createStateSymbol(name: string) {
return Symbol.for(`TypeSpec.${name}`);

Просмотреть файл

@ -20,7 +20,7 @@ import {
parse,
} from "../core/index.js";
import { compile as compileProgram } from "../core/program.js";
import { doIO, loadFile, resolveTspMain } from "../core/util.js";
import { doIO, loadFile, resolveTspMain } from "../utils/misc.js";
import { serverOptions } from "./constants.js";
import { FileService } from "./file-service.js";
import { FileSystemCache } from "./file-system-cache.js";

Просмотреть файл

@ -27,8 +27,8 @@ import {
hasTrailingDirectorySeparator,
resolvePath,
} from "../core/path-utils.js";
import { findProjectRoot, loadFile, resolveTspMain } from "../core/util.js";
import { printId } from "../formatter/print/printer.js";
import { findProjectRoot, loadFile, resolveTspMain } from "../utils/misc.js";
import { getSymbolDetails } from "./type-details.js";
export type CompletionContext = {

Просмотреть файл

@ -1,6 +1,6 @@
import { TextDocumentIdentifier } from "vscode-languageserver";
import { TextDocument } from "vscode-languageserver-textdocument";
import { getNormalizedRealPath } from "../core/util.js";
import { getNormalizedRealPath } from "../utils/misc.js";
import { ServerHost } from "./types.js";
/**

Просмотреть файл

@ -11,7 +11,7 @@ import {
createConnection,
} from "vscode-languageserver/node.js";
import { NodeHost } from "../core/node-host.js";
import { typespecVersion } from "../core/util.js";
import { typespecVersion } from "../utils/misc.js";
import { createServer } from "./serverlib.js";
import { Server, ServerHost } from "./types.js";

Просмотреть файл

@ -42,13 +42,14 @@ import {
WorkspaceFoldersChangeEvent,
} from "vscode-languageserver/node.js";
import { CharCode, codePointBefore, isIdentifierContinue } from "../core/charcode.js";
import { compilerAssert, createSourceFile, getSourceLocation } from "../core/diagnostics.js";
import { compilerAssert, getSourceLocation } from "../core/diagnostics.js";
import { formatTypeSpec } from "../core/formatter.js";
import { getTypeName } from "../core/helpers/type-name-utils.js";
import { getNodeAtPosition, visitChildren } from "../core/parser.js";
import { ensureTrailingDirectorySeparator } from "../core/path-utils.js";
import { Program } from "../core/program.js";
import { skipTrivia, skipWhiteSpace } from "../core/scanner.js";
import { createSourceFile, getSourceFileKindFromExt } from "../core/source-file.js";
import {
AugmentDecoratorStatementNode,
CompilerHost,
@ -63,7 +64,7 @@ import {
TypeReferenceNode,
TypeSpecScriptNode,
} from "../core/types.js";
import { getNormalizedRealPath, getSourceFileKindFromExt } from "../core/util.js";
import { getNormalizedRealPath } from "../utils/misc.js";
import { getSemanticTokens } from "./classify.js";
import { createCompileService } from "./compile-service.js";
import { resolveCompletion } from "./completion.js";

Просмотреть файл

@ -12,7 +12,7 @@ import {
UnionStatementNode,
} from "../core/index.js";
import { NamespaceStatementNode, Node, SyntaxKind } from "../core/types.js";
import { isArray, isDefined } from "../core/util.js";
import { isArray, isDefined } from "../utils/misc.js";
export function getSymbolStructure(ast: TypeSpecScriptNode): DocumentSymbol[] {
const file = ast.file;

Просмотреть файл

@ -1,6 +1,6 @@
import { fail, match, strictEqual } from "assert";
import { Diagnostic, NoTarget, Type, formatDiagnostic, getSourceLocation } from "../core/index.js";
import { isArray } from "../core/util.js";
import { isArray } from "../utils/misc.js";
import { resolveVirtualPath } from "./test-host.js";
/**

Просмотреть файл

@ -3,14 +3,15 @@ import { RmOptions } from "fs";
import { readFile } from "fs/promises";
import { globby } from "globby";
import { fileURLToPath, pathToFileURL } from "url";
import { createSourceFile, logDiagnostics, logVerboseTestOutput } from "../core/diagnostics.js";
import { logDiagnostics, logVerboseTestOutput } from "../core/diagnostics.js";
import { createLogger } from "../core/logger/logger.js";
import { NodeHost } from "../core/node-host.js";
import { CompilerOptions } from "../core/options.js";
import { getAnyExtensionFromPath, resolvePath } from "../core/path-utils.js";
import { Program, compile as compileProgram } from "../core/program.js";
import { CompilerHost, Diagnostic, StringLiteral, Type } from "../core/types.js";
import { createStringMap, getSourceFileKindFromExt } from "../core/util.js";
import { createSourceFile, getSourceFileKindFromExt } from "../index.js";
import { createStringMap } from "../utils/misc.js";
import { expectDiagnosticEmpty } from "./expect.js";
import { createTestWrapper, findTestPackageRoot } from "./test-utils.js";
import {

Просмотреть файл

@ -4,8 +4,8 @@ import { TextDocument } from "vscode-languageserver-textdocument";
import { Diagnostic } from "vscode-languageserver/node.js";
import { parse, visitChildren } from "../core/parser.js";
import { IdentifierNode, SyntaxKind } from "../core/types.js";
import { createStringMap } from "../core/util.js";
import { Server, ServerHost, createServer } from "../server/index.js";
import { createStringMap } from "../utils/misc.js";
import {
StandardTestLibrary,
TestHostOptions,

Просмотреть файл

@ -1,7 +1,7 @@
import { fileURLToPath } from "url";
import { NodeHost, resolvePath } from "../core/index.js";
import { CompilerOptions } from "../core/options.js";
import { findProjectRoot } from "../core/util.js";
import { findProjectRoot } from "../utils/misc.js";
import {
BasicTestRunner,
TestHost,

Просмотреть файл

@ -0,0 +1,31 @@
/**
* Helper class to track duplicate instance
*/
export class DuplicateTracker<K, V> {
#entries = new Map<K, V[]>();
/**
* Track usage of K.
* @param k key that is being checked for duplicate.
* @param v value that map to the key
*/
track(k: K, v: V) {
const existing = this.#entries.get(k);
if (existing === undefined) {
this.#entries.set(k, [v]);
} else {
existing.push(v);
}
}
/**
* Return iterator of all the duplicate entries.
*/
*entries(): Iterable<[K, V[]]> {
for (const [k, v] of this.#entries.entries()) {
if (v.length > 1) {
yield [k, v];
}
}
}
}

Просмотреть файл

@ -0,0 +1,6 @@
// ---------------------------------------
// Exports for `@typespec/compiler/utils`.
// Be explicit about what get exported so we don't export utils that are not meant to be public.
// ---------------------------------------
export { DuplicateTracker } from "./duplicate-tracker.js";
export { Queue, TwoLevelMap, createRekeyableMap, deepClone, deepEquals } from "./misc.js";

Просмотреть файл

@ -1,14 +1,14 @@
import { createSourceFile, DiagnosticHandler } from "./diagnostics.js";
import { createDiagnostic } from "./messages.js";
import { DiagnosticHandler } from "../core/diagnostics.js";
import { createDiagnostic } from "../core/messages.js";
import {
getAnyExtensionFromPath,
getDirectoryPath,
isPathAbsolute,
isUrl,
joinPaths,
normalizePath,
resolvePath,
} from "./path-utils.js";
} from "../core/path-utils.js";
import { createSourceFile } from "../core/source-file.js";
import {
CompilerHost,
Diagnostic,
@ -16,10 +16,9 @@ import {
NoTarget,
RekeyableMap,
SourceFile,
SourceFileKind,
Sym,
SymbolTable,
} from "./types.js";
} from "../core/types.js";
export { typespecVersion } from "../manifest.js";
@ -438,17 +437,6 @@ export function mutate<T>(value: T): Mutable<T> {
return value as Mutable<T>;
}
export function getSourceFileKindFromExt(path: string): SourceFileKind | undefined {
const ext = getAnyExtensionFromPath(path);
if (ext === ".js" || ext === ".mjs") {
return "js";
} else if (ext === ".tsp" || ext === ".cadl") {
return "typespec";
} else {
return undefined;
}
}
export function createStringMap<T>(caseInsensitive: boolean): Map<string, T> {
return caseInsensitive ? new CaseInsensitiveMap<T>() : new Map<string, T>();
}
@ -468,38 +456,6 @@ class CaseInsensitiveMap<T> extends Map<string, T> {
}
}
/**
* Helper class to track duplicate instance
*/
export class DuplicateTracker<K, V> {
#entries = new Map<K, V[]>();
/**
* Track usage of K.
* @param k key that is being checked for duplicate.
* @param v value that map to the key
*/
track(k: K, v: V) {
const existing = this.#entries.get(k);
if (existing === undefined) {
this.#entries.set(k, [v]);
} else {
existing.push(v);
}
}
/**
* Return iterator of all the duplicate entries.
*/
*entries(): Iterable<[K, V[]]> {
for (const [k, v] of this.#entries.entries()) {
if (v.length > 1) {
yield [k, v];
}
}
}
}
export function createRekeyableMap<K, V>(entries?: [K, V][]): RekeyableMap<K, V> {
return new RekeyableMapImpl<K, V>(entries);
}

Просмотреть файл

@ -1,5 +1,6 @@
import { YAMLError, parseDocument } from "yaml";
import { createDiagnosticCollector, createSourceFile } from "../core/diagnostics.js";
import { createDiagnosticCollector } from "../core/diagnostics.js";
import { createSourceFile } from "../core/source-file.js";
import { Diagnostic, DiagnosticSeverity, SourceFile } from "../core/types.js";
import { YamlScript } from "./types.js";

Просмотреть файл

@ -1,11 +1,11 @@
import { ok, strictEqual } from "assert";
import { beforeEach, describe, it } from "vitest";
import { Binder, createBinder } from "../src/core/binder.js";
import { createSourceFile } from "../src/core/diagnostics.js";
import { createLogger } from "../src/core/logger/logger.js";
import { createTracer } from "../src/core/logger/tracer.js";
import { parse } from "../src/core/parser.js";
import { Program } from "../src/core/program.js";
import { createSourceFile } from "../src/core/source-file.js";
import {
AliasStatementNode,
InterfaceStatementNode,

Просмотреть файл

@ -2,8 +2,8 @@ import { deepStrictEqual, ok, strictEqual } from "assert";
import { beforeEach, describe, it } from "vitest";
import { Program } from "../../src/core/program.js";
import { DecoratorContext, Type } from "../../src/core/types.js";
import { createRekeyableMap } from "../../src/core/util.js";
import { TestHost, createTestHost } from "../../src/testing/index.js";
import { createRekeyableMap } from "../../src/utils/misc.js";
describe("compiler: type cloning", () => {
let testHost: TestHost;

Просмотреть файл

@ -3,9 +3,9 @@ import { join } from "path";
import { describe, it } from "vitest";
import { TypeSpecConfigJsonSchema } from "../../src/config/config-schema.js";
import { TypeSpecRawConfig, loadTypeSpecConfigForPath } from "../../src/config/index.js";
import { createSourceFile } from "../../src/core/diagnostics.js";
import { NodeHost } from "../../src/core/node-host.js";
import { createJSONSchemaValidator } from "../../src/core/schema-validator.js";
import { createSourceFile } from "../../src/core/source-file.js";
import { resolvePath } from "../../src/index.js";
import { findTestPackageRoot } from "../../src/testing/test-utils.js";

Просмотреть файл

@ -5,7 +5,7 @@ import { dirname, resolve } from "path";
import { describe, it } from "vitest";
import vscode_oniguruma from "vscode-oniguruma";
import vscode_textmate, { IOnigLib, StateStack } from "vscode-textmate";
import { createSourceFile } from "../../src/core/diagnostics.js";
import { createSourceFile } from "../../src/core/source-file.js";
import { TypeSpecScope } from "../../src/server/tmlanguage.js";
import { SemanticToken, SemanticTokenKind } from "../../src/server/types.js";
import { createTestServerHost } from "../../src/testing/test-server-host.js";

Просмотреть файл

@ -1,12 +1,12 @@
import { ok } from "assert";
import { describe, it } from "vitest";
import { Program, SymbolTable, visitChildren } from "../../src/core/index.js";
import { mutate } from "../../src/core/util.js";
import {
createTestServerHost,
expectDiagnosticEmpty,
resolveVirtualPath,
} from "../../src/testing/index.js";
import { mutate } from "../../src/utils/misc.js";
describe("compiler: server: reuse", () => {
it("reuses unchanged programs", async () => {

Просмотреть файл

@ -1,7 +1,7 @@
import { deepStrictEqual } from "assert";
import { beforeEach, describe, it } from "vitest";
import { RekeyableMap } from "../src/core/index.js";
import { createRekeyableMap } from "../src/core/util.js";
import { createRekeyableMap } from "../src/utils/misc.js";
describe("compiler: util", () => {
describe("RekeyableMap", () => {

Просмотреть файл

@ -57,7 +57,7 @@ module.exports = {
// Symbols should have a description so it can be serialized.
"symbol-description": "warn",
},
ignorePatterns: ["dist/**/*", "dist-dev/**/*"],
ignorePatterns: ["dist/**/*", "dist-dev/**/*", "temp/**/*"],
overrides: [
{
/**

Просмотреть файл

@ -3,11 +3,11 @@ import {
Namespace,
Operation,
Program,
TwoLevelMap,
Type,
ignoreDiagnostics,
navigateTypesInNamespace,
} from "@typespec/compiler";
import { TwoLevelMap } from "@typespec/compiler/utils";
import {
MetadataInfo,
Visibility,