@typespec/http-server-js
Version:
TypeSpec HTTP server code generator for JavaScript
111 lines • 4.51 kB
JavaScript
import { NoTarget } from "@typespec/compiler";
import { reportDiagnostic } from "../lib.js";
import { UnreachableError } from "./error.js";
const DEFAULT_DECLARATION_OPTIONS = {
source: NoTarget,
resolutionStrategy: "shadow",
};
const NO_PARENT = {
declare() {
throw new UnreachableError("Cannot declare in the no-parent scope");
},
isDeclared() {
return false;
},
};
/**
* Create a new scope.
*
* @param ctx - the JS emitter context.
* @param parent - an optional parent scope for this scope. It will consider declarations in the parent scope for some conflicts.
*/
export function createScope(ctx, parent = NO_PARENT) {
const ownDeclarations = new Set();
const self = {
declare(primaryName, options = {}) {
const { source: target, resolutionStrategy } = { ...DEFAULT_DECLARATION_OPTIONS, ...options };
if (!self.isDeclared(primaryName)) {
ownDeclarations.add(primaryName);
return primaryName;
}
// Apply resolution strategy
const resolutionStrategyName = typeof resolutionStrategy === "string" ? resolutionStrategy : resolutionStrategy.kind;
switch (resolutionStrategyName) {
case "none":
// Report diagnostic and return the name as is.
reportDiagnostic(ctx.program, {
code: "name-conflict",
format: {
name: primaryName,
},
target,
});
return primaryName;
case "shadow":
// Check to make sure this name isn't an own-declaration, and if not allow it, otherwise raise a diagnostic.
if (!ownDeclarations.has(primaryName)) {
ownDeclarations.add(primaryName);
return primaryName;
}
else {
reportDiagnostic(ctx.program, {
code: "name-conflict",
format: {
name: primaryName,
},
target,
});
return primaryName;
}
case "prefix": {
const { prefix = "_", repeated = false, shadow = true, } = resolutionStrategy;
let name = primaryName;
const isDeclared = shadow ? (name) => ownDeclarations.has(name) : self.isDeclared;
while (isDeclared(name)) {
name = prefix + name;
if (!repeated)
break;
}
if (isDeclared(name)) {
// We were not able to resolve the conflict with this strategy, so raise a diagnostic.
reportDiagnostic(ctx.program, {
code: "name-conflict",
format: {
name: name,
},
target,
});
return name;
}
ownDeclarations.add(name);
return name;
}
case "alt-name": {
const { altName } = resolutionStrategy;
if (!self.isDeclared(altName)) {
ownDeclarations.add(altName);
return altName;
}
// We were not able to resolve the conflict with this strategy, so raise a diagnostic.
reportDiagnostic(ctx.program, {
code: "name-conflict",
format: {
name: altName,
},
target,
});
return altName;
}
default:
throw new UnreachableError(`Unknown resolution strategy: ${resolutionStrategy}`, {
resolutionStrategyName,
});
}
},
isDeclared(name) {
return ownDeclarations.has(name) || parent.isDeclared(name);
},
};
return self;
}
//# sourceMappingURL=scope.js.map