Fixed the declaration generation
parent
6b5adf30c7
commit
da0956fe24
|
@ -3,6 +3,5 @@ interface Window {
|
||||||
__native_client_init_shared: (webpackRequire: any) => void;
|
__native_client_init_shared: (webpackRequire: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare const __webpack_require__;
|
|
||||||
declare const __teaclient_preview_notice: any;
|
declare const __teaclient_preview_notice: any;
|
||||||
declare const __teaclient_preview_error: any;
|
declare const __teaclient_preview_error: any;
|
|
@ -2,13 +2,6 @@ import * as loader from "../loader/loader";
|
||||||
import {Stage} from "../loader/loader";
|
import {Stage} from "../loader/loader";
|
||||||
import {BrowserInfo, detect as detectBrowser,} from "detect-browser";
|
import {BrowserInfo, detect as detectBrowser,} from "detect-browser";
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
detectedBrowser: BrowserInfo,
|
|
||||||
removeLoaderContextMenuHook: () => void
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loader.register_task(Stage.SETUP, {
|
loader.register_task(Stage.SETUP, {
|
||||||
name: "app init",
|
name: "app init",
|
||||||
function: async () => {
|
function: async () => {
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
"description": "Welcome here! This repository is created with two reasons:\n 1. People can bring their own ideas and follow their implementation\n 2. People can see TeaSpeak Web client progress and avoid creating repetitive issues all the time.",
|
"description": "Welcome here! This repository is created with two reasons:\n 1. People can bring their own ideas and follow their implementation\n 2. People can see TeaSpeak Web client progress and avoid creating repetitive issues all the time.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"compile-project-base": "tsc -p tsbaseconfig.json",
|
"compile-project-base": "tsc -p tsbaseconfig.json",
|
||||||
"dtsgen": "node tools/dtsgen/index.js",
|
|
||||||
"trgen": "node tools/trgen/index.js",
|
"trgen": "node tools/trgen/index.js",
|
||||||
"tsc": "tsc",
|
"tsc": "tsc",
|
||||||
"compile-scss": "sass loader/css/index.scss:loader/css/index.css",
|
"compile-scss": "sass loader/css/index.scss:loader/css/index.css",
|
||||||
|
|
|
@ -5,28 +5,6 @@ BASEDIR=$(dirname "$0")
|
||||||
source "${BASEDIR}/resolve_commands.sh"
|
source "${BASEDIR}/resolve_commands.sh"
|
||||||
cd "$BASEDIR/../" || { echo "Failed to enter parent directory!"; exit 1; }
|
cd "$BASEDIR/../" || { echo "Failed to enter parent directory!"; exit 1; }
|
||||||
|
|
||||||
function generate_link() {
|
|
||||||
if [[ ! -L $2 ]] || [[ "${BASH_ARGV[0]}" == "force" ]]; then
|
|
||||||
if [[ -e $2 ]] || [[ -L $2 ]]; then
|
|
||||||
rm $2
|
|
||||||
fi
|
|
||||||
ln -rs $1 $2
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function replace_tribble() {
|
|
||||||
#${1} => file name
|
|
||||||
echo "$(cat ${1} | sed -E 's/\/\/\/[ ]+<reference [a-zA-Z.-=_ ]+\/>.*/\n/')" > ${1}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#Building the generator
|
|
||||||
./tools/build_dtsgen.sh; _exit_code=$?
|
|
||||||
if [[ $_exit_code -ne 0 ]]; then
|
|
||||||
echo "Failed to build typescript declaration generator ($_exit_code)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
#Shared
|
#Shared
|
||||||
./shared/generate_declarations.sh; _exit_code=$?
|
./shared/generate_declarations.sh; _exit_code=$?
|
||||||
[[ $_exit_code -ne 0 ]] && {
|
[[ $_exit_code -ne 0 ]] && {
|
||||||
|
|
|
@ -15,7 +15,7 @@ function generate_declaration() {
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
npm run dtsgen -- --config "$(pwd)/tsconfig/$1" -v
|
npm run tsc -- --project "$(pwd)/tsconfig/$1"
|
||||||
if [[ ! -e $2 ]]; then
|
if [[ ! -e $2 ]]; then
|
||||||
echo "Failed to generate definitions"
|
echo "Failed to generate definitions"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
@ -60,8 +60,9 @@ export class DummyVoiceConnection extends AbstractVoiceConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
async acquireVoiceRecorder(recorder: RecorderProfile | undefined): Promise<void> {
|
async acquireVoiceRecorder(recorder: RecorderProfile | undefined): Promise<void> {
|
||||||
if(this.recorder === recorder)
|
if(this.recorder === recorder) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(this.recorder) {
|
if(this.recorder) {
|
||||||
this.recorder.callback_unmount = undefined;
|
this.recorder.callback_unmount = undefined;
|
||||||
|
@ -69,6 +70,7 @@ export class DummyVoiceConnection extends AbstractVoiceConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
await recorder?.unmount();
|
await recorder?.unmount();
|
||||||
|
const oldRecorder = this.recorder;
|
||||||
this.recorder = recorder;
|
this.recorder = recorder;
|
||||||
|
|
||||||
if(this.recorder) {
|
if(this.recorder) {
|
||||||
|
@ -78,7 +80,10 @@ export class DummyVoiceConnection extends AbstractVoiceConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.events.fire("notify_recorder_changed", {});
|
this.events.fire("notify_recorder_changed", {
|
||||||
|
oldRecorder,
|
||||||
|
newRecorder: recorder
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
availableVoiceClients(): VoiceClient[] {
|
availableVoiceClients(): VoiceClient[] {
|
||||||
|
|
|
@ -20,7 +20,6 @@ import * as aplayer from "tc-backend/audio/player";
|
||||||
import * as ppt from "tc-backend/ppt";
|
import * as ppt from "tc-backend/ppt";
|
||||||
import * as keycontrol from "./KeyControl";
|
import * as keycontrol from "./KeyControl";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as ReactDOM from "react-dom";
|
|
||||||
import * as global_ev_handler from "./events/ClientGlobalControlHandler";
|
import * as global_ev_handler from "./events/ClientGlobalControlHandler";
|
||||||
import {global_client_actions} from "tc-shared/events/GlobalEvents";
|
import {global_client_actions} from "tc-shared/events/GlobalEvents";
|
||||||
import {FileTransferState, TransferProvider,} from "tc-shared/file/Transfer";
|
import {FileTransferState, TransferProvider,} from "tc-shared/file/Transfer";
|
||||||
|
|
|
@ -16,7 +16,7 @@ import "../../../file/RemoteAvatars";
|
||||||
import "../../../file/RemoteIcons";
|
import "../../../file/RemoteIcons";
|
||||||
|
|
||||||
if("__native_client_init_shared" in window) {
|
if("__native_client_init_shared" in window) {
|
||||||
window.__native_client_init_shared(__webpack_require__);
|
(window as any).__native_client_init_shared(__webpack_require__);
|
||||||
}
|
}
|
||||||
|
|
||||||
let modalRenderer: ModalRenderer;
|
let modalRenderer: ModalRenderer;
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
"baseUrl": "../../",
|
"baseUrl": "../../",
|
||||||
"paths": {
|
"paths": {
|
||||||
"tc-shared/*": ["shared/js/*"],
|
"tc-shared/*": ["shared/js/*"],
|
||||||
// "tc-backend/web/*": ["web/app/*"], /* specific web part */
|
|
||||||
"tc-backend/*": ["shared/backend.d/*"],
|
"tc-backend/*": ["shared/backend.d/*"],
|
||||||
"tc-loader": ["loader/exports/loader.d.ts"],
|
"tc-loader": ["loader/exports/loader.d.ts"],
|
||||||
"svg-sprites/*": ["shared/svg-sprites/*"],
|
"svg-sprites/*": ["shared/svg-sprites/*"],
|
||||||
|
@ -23,6 +22,7 @@
|
||||||
"include": [
|
"include": [
|
||||||
"../js/proto.ts",
|
"../js/proto.ts",
|
||||||
"../backend.d",
|
"../backend.d",
|
||||||
"../js/**/*.ts"
|
"../js/**/*.ts",
|
||||||
|
"../../webpack/build-definitions.d.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
BASEDIR=$(dirname "$0")
|
|
||||||
source "${BASEDIR}/../scripts/resolve_commands.sh"
|
|
||||||
cd "$BASEDIR/dtsgen"
|
|
||||||
|
|
||||||
execute_tsc -p tsconfig.json
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "Failed to build typescript declaration generator"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
|
@ -1,475 +0,0 @@
|
||||||
import * as ts from "typescript";
|
|
||||||
import {SyntaxKind} from "typescript";
|
|
||||||
import * as webpack from "webpack";
|
|
||||||
|
|
||||||
interface Array<T> {
|
|
||||||
last?(): T;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(<any>Array).prototype.last){
|
|
||||||
(<any>Array).prototype.last = function(){
|
|
||||||
if(this.length == 0) return undefined;
|
|
||||||
return this[this.length - 1];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function has_modifier<T extends ts.Modifier["kind"]>(modifiers: ts.ModifiersArray | undefined, target: T) : boolean {
|
|
||||||
if(modifiers) {
|
|
||||||
for(const modifier of modifiers)
|
|
||||||
if(modifier.kind == target)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function append_modifier<T extends ts.Modifier["kind"]>(modifiers: ts.ModifiersArray | undefined, target: T) : ts.ModifiersArray {
|
|
||||||
if(has_modifier(modifiers, target)) return modifiers;
|
|
||||||
|
|
||||||
const sort_oder: {[key: number]:number} = {};
|
|
||||||
sort_oder[SyntaxKind.AbstractKeyword] = 20;
|
|
||||||
sort_oder[SyntaxKind.AsyncKeyword] = 20;
|
|
||||||
sort_oder[SyntaxKind.ConstKeyword] = 20;
|
|
||||||
sort_oder[SyntaxKind.DeclareKeyword] = 20;
|
|
||||||
sort_oder[SyntaxKind.DefaultKeyword] = 20;
|
|
||||||
sort_oder[SyntaxKind.ExportKeyword] = 10;
|
|
||||||
sort_oder[SyntaxKind.PublicKeyword] = 30;
|
|
||||||
sort_oder[SyntaxKind.PrivateKeyword] = 30;
|
|
||||||
sort_oder[SyntaxKind.ProtectedKeyword] = 30;
|
|
||||||
sort_oder[SyntaxKind.ReadonlyKeyword] = 30;
|
|
||||||
sort_oder[SyntaxKind.StaticKeyword] = 30;
|
|
||||||
|
|
||||||
const comparator = (a: ts.Modifier, b: ts.Modifier) => sort_oder[a.kind] - sort_oder[b.kind];
|
|
||||||
return ts.createNodeArray(
|
|
||||||
[ts.createModifier(target as number), ...(modifiers || [])].sort(comparator).map((e, index, array) => {
|
|
||||||
const range = ts.getCommentRange(e);
|
|
||||||
if(range.end === -1 && range.pos === -1)
|
|
||||||
return e;
|
|
||||||
ts.setCommentRange(e, {pos: -1, end: -1});
|
|
||||||
|
|
||||||
const first_range = ts.getCommentRange(array[0]);
|
|
||||||
if(first_range.end === -1 && first_range.pos === -1)
|
|
||||||
ts.setCommentRange(array[0], range);
|
|
||||||
else
|
|
||||||
console.warn("Dropping comment on node because first node already has a comment");
|
|
||||||
return e;
|
|
||||||
}),
|
|
||||||
(modifiers || {hasTrailingComma: false}).hasTrailingComma
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Transfer comments?
|
|
||||||
function remove_modifier<T extends ts.Modifier["kind"]>(modifiers: ts.ModifiersArray | undefined, target: T) : ts.ModifiersArray {
|
|
||||||
if(!has_modifier(modifiers, target)) return modifiers;
|
|
||||||
|
|
||||||
const new_modifiers: ts.Modifier[] = [];
|
|
||||||
for(const modifier of (modifiers || []))
|
|
||||||
if(modifier.kind != target)
|
|
||||||
new_modifiers.push(modifier);
|
|
||||||
|
|
||||||
return new_modifiers.length == 0 ? undefined : ts.createNodeArray(new_modifiers, (modifiers || {hasTrailingComma: false}).hasTrailingComma);
|
|
||||||
}
|
|
||||||
|
|
||||||
const has_declare = (modifiers?: ts.ModifiersArray) => has_modifier(modifiers, SyntaxKind.DeclareKeyword);
|
|
||||||
const has_private = (modifiers?: ts.ModifiersArray) => has_modifier(modifiers, SyntaxKind.PrivateKeyword);
|
|
||||||
const append_declare = (modifiers?: ts.ModifiersArray, flag: boolean = true) => flag ? append_modifier(modifiers, SyntaxKind.DeclareKeyword) : remove_modifier(modifiers, SyntaxKind.DeclareKeyword);
|
|
||||||
const append_export = (modifiers?: ts.ModifiersArray, flag: boolean = true) => flag ? append_modifier(modifiers, SyntaxKind.ExportKeyword) : remove_modifier(modifiers, SyntaxKind.ExportKeyword);
|
|
||||||
|
|
||||||
interface StackParameter {
|
|
||||||
flag_declare: boolean,
|
|
||||||
flag_namespace: boolean
|
|
||||||
flag_class: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
class StackParameters implements StackParameter {
|
|
||||||
flag_declare: boolean = false;
|
|
||||||
flag_namespace: boolean = false;
|
|
||||||
flag_class: boolean = false;
|
|
||||||
|
|
||||||
stack: StackParameter[] = [];
|
|
||||||
|
|
||||||
recalculate() {
|
|
||||||
{
|
|
||||||
this.flag_declare = false;
|
|
||||||
for(const layer of this.stack) {
|
|
||||||
if(layer.flag_declare) {
|
|
||||||
this.flag_declare = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
this.flag_namespace = false;
|
|
||||||
for(const layer of this.stack) {
|
|
||||||
if(layer.flag_namespace) {
|
|
||||||
this.flag_namespace = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
this.flag_class = false;
|
|
||||||
for(const layer of this.stack) {
|
|
||||||
if(layer.flag_class) {
|
|
||||||
this.flag_class = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
push(layer: StackParameter) {
|
|
||||||
this.stack.push(layer);
|
|
||||||
this.recalculate();
|
|
||||||
}
|
|
||||||
|
|
||||||
pop?() : StackParameter {
|
|
||||||
const result = this.stack.pop();
|
|
||||||
if(result)
|
|
||||||
this.recalculate();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const generators: {[key: number]:((settings: _Settings, stack: StackParameters, node: ts.Node) => ts.Node | undefined) | undefined} = {};
|
|
||||||
|
|
||||||
function _generate(settings: _Settings, stack: StackParameters, layer: ts.Node[], node: ts.Node) {
|
|
||||||
//console.log(SyntaxKind[node.kind]);
|
|
||||||
if(generators[node.kind]) {
|
|
||||||
const result = generators[node.kind](settings, stack, node);
|
|
||||||
if(result)
|
|
||||||
layer.push(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(node.kind) {
|
|
||||||
case SyntaxKind.Identifier:
|
|
||||||
console.log("Unknown identifier %s", (<ts.Identifier>node).text);
|
|
||||||
break;
|
|
||||||
case SyntaxKind.SourceFile: /* yeah we have something */
|
|
||||||
node.forEachChild(n => _generate(settings, stack, layer, n));
|
|
||||||
break;
|
|
||||||
case SyntaxKind.EndOfFileToken: /* oh no, we're at the end */
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
//node.forEachChild(n => _generate(settings, stack, layer, n));
|
|
||||||
const sf = node.getSourceFile();
|
|
||||||
let { line, character } = sf ? sf.getLineAndCharacterOfPosition(node.getStart()) : {line: -1, character: -1};
|
|
||||||
console.log(`${(sf || {fileName: "unknown"}).fileName} (${line + 1},${character + 1}): Unhandled type %s`, SyntaxKind[node.kind]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Settings {
|
|
||||||
remove_private?: {
|
|
||||||
field?: boolean;
|
|
||||||
method?: boolean;
|
|
||||||
} | boolean;
|
|
||||||
|
|
||||||
log?: {
|
|
||||||
unhandled_types: boolean;
|
|
||||||
} | boolean;
|
|
||||||
|
|
||||||
module_mode?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _Settings implements Settings {
|
|
||||||
remove_private: {
|
|
||||||
field: boolean;
|
|
||||||
method: boolean;
|
|
||||||
} = {
|
|
||||||
field: false,
|
|
||||||
method: false
|
|
||||||
};
|
|
||||||
|
|
||||||
log?: {
|
|
||||||
unhandled_types: boolean;
|
|
||||||
} = {
|
|
||||||
unhandled_types: false
|
|
||||||
};
|
|
||||||
|
|
||||||
module_mode?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
function specify_settings(settings?: Settings) : _Settings {
|
|
||||||
const result: _Settings = new _Settings();
|
|
||||||
Object.assign(result, settings);
|
|
||||||
if(!settings)
|
|
||||||
settings = {};
|
|
||||||
|
|
||||||
if(typeof(settings.remove_private) === "boolean")
|
|
||||||
result.remove_private = {
|
|
||||||
field: settings.remove_private,
|
|
||||||
method: settings.remove_private
|
|
||||||
};
|
|
||||||
|
|
||||||
if(typeof(settings.log) === "boolean")
|
|
||||||
result.log = {
|
|
||||||
unhandled_types: settings.log,
|
|
||||||
};
|
|
||||||
if(typeof(settings.module_mode) !== "boolean")
|
|
||||||
result.module_mode = false;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generate(file: ts.SourceFile, settings?: Settings) : ts.Node[]{
|
|
||||||
const layer: ts.Node[] = [];
|
|
||||||
const stack = new StackParameters();
|
|
||||||
const _settings = specify_settings(settings);
|
|
||||||
|
|
||||||
stack.push({
|
|
||||||
flag_class: false,
|
|
||||||
flag_declare: false,
|
|
||||||
flag_namespace: _settings.module_mode
|
|
||||||
});
|
|
||||||
_generate(_settings, stack, layer, file);
|
|
||||||
stack.pop();
|
|
||||||
|
|
||||||
return layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function print(source: ts.SourceFile, nodes: ts.Node[]) : string {
|
|
||||||
const printer = ts.createPrinter({
|
|
||||||
newLine: ts.NewLineKind.LineFeed
|
|
||||||
});
|
|
||||||
|
|
||||||
return printer.printList(
|
|
||||||
ts.ListFormat.SpaceBetweenBraces | ts.ListFormat.MultiLine | ts.ListFormat.PreferNewLine,
|
|
||||||
nodes as any,
|
|
||||||
source
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* generator impl */
|
|
||||||
generators[SyntaxKind.ModuleBlock] = (settings, stack, node: ts.ModuleBlock) => {
|
|
||||||
const layer = [] as ts.Node[];
|
|
||||||
node.forEachChild(n => _generate(settings, stack, layer, n));
|
|
||||||
return ts.createModuleBlock(layer as any);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.ModuleDeclaration] = (settings, stack, node: ts.ModuleDeclaration) => {
|
|
||||||
//if (node.flags & ~(ts.NodeFlags.Namespace | ts.NodeFlags.NestedNamespace | ts.NodeFlags.ExportContext)) {
|
|
||||||
// throw "Some module declaration flags are not jet supported (flags: " + Object.keys(ts.NodeFlags).filter(e => node.flags & ts.NodeFlags[e]).join(", ") + ")";
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
stack.push({
|
|
||||||
flag_declare: true,
|
|
||||||
flag_namespace: true,
|
|
||||||
flag_class: false
|
|
||||||
});
|
|
||||||
const body = generators[node.body.kind](settings, stack, node.body) as ts.ModuleBlock;
|
|
||||||
stack.pop();
|
|
||||||
|
|
||||||
return ts.createModuleDeclaration(node.decorators, append_declare(node.modifiers, !stack.flag_declare), node.name, body, node.flags);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const _generate_param_declare = (settings, stack, params: ts.NodeArray<ts.ParameterDeclaration>) => {
|
|
||||||
const parms: any[] = [];
|
|
||||||
for(const parm of params)
|
|
||||||
parms.push(generators[parm.kind](settings, stack, parm));
|
|
||||||
return parms;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* functions */
|
|
||||||
generators[SyntaxKind.Parameter] = (settings, stack, node: ts.ParameterDeclaration) => {
|
|
||||||
return ts.createParameter(node.decorators, node.modifiers, node.dotDotDotToken, node.name, node.questionToken || (node.initializer ? ts.createToken(SyntaxKind.QuestionToken) : undefined), node.type, undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.Constructor] = (settings, stack, node: ts.ConstructorDeclaration) => {
|
|
||||||
if(settings.remove_private.method && has_private(node.modifiers)) return;
|
|
||||||
|
|
||||||
return ts.createConstructor(node.decorators, node.modifiers, _generate_param_declare(settings, stack, node.parameters), undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.FunctionDeclaration] = (settings, stack, node: ts.FunctionDeclaration) => {
|
|
||||||
if(stack.flag_namespace && !has_modifier(node.modifiers, SyntaxKind.ExportKeyword)) return;
|
|
||||||
|
|
||||||
let return_type = node.type;
|
|
||||||
if(has_modifier(node.modifiers, SyntaxKind.AsyncKeyword)) {
|
|
||||||
if(!return_type)
|
|
||||||
return_type = ts.createTypeReferenceNode("Promise", [ts.createIdentifier("any") as any]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ts.createFunctionDeclaration(node.decorators, remove_modifier(append_declare(node.modifiers, !stack.flag_declare), SyntaxKind.AsyncKeyword), node.asteriskToken, node.name, node.typeParameters, _generate_param_declare(settings, stack, node.parameters), return_type, undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
generators[SyntaxKind.MethodDeclaration] = (settings, stack, node: ts.MethodDeclaration) => {
|
|
||||||
if(settings.remove_private.method && has_private(node.modifiers)) return;
|
|
||||||
|
|
||||||
return ts.createMethod(node.decorators, remove_modifier(node.modifiers, SyntaxKind.AsyncKeyword), node.asteriskToken, node.name, node.questionToken, node.typeParameters, _generate_param_declare(settings, stack, node.parameters), node.type, undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.GetAccessor] = (settings, stack, node: ts.GetAccessorDeclaration) => {
|
|
||||||
if(settings.remove_private.method && has_private(node.modifiers)) return;
|
|
||||||
|
|
||||||
node = ts.createGetAccessor(node.decorators, node.modifiers, node.name, _generate_param_declare(settings, stack, node.parameters), node.type, undefined);
|
|
||||||
return ts.addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, " @ts-ignore", true);
|
|
||||||
};
|
|
||||||
generators[SyntaxKind.SetAccessor] = (settings, stack, node: ts.SetAccessorDeclaration) => {
|
|
||||||
if(settings.remove_private.method && has_private(node.modifiers)) return;
|
|
||||||
node = ts.createSetAccessor(node.decorators, node.modifiers, node.name, _generate_param_declare(settings, stack, node.parameters), undefined);
|
|
||||||
return ts.addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, " @ts-ignore", true);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* variables or properties */
|
|
||||||
generators[SyntaxKind.PropertyDeclaration] = (settings, stack, node: ts.PropertyDeclaration) => {
|
|
||||||
if(settings.remove_private.field && has_private(node.modifiers)) return;
|
|
||||||
|
|
||||||
return ts.createProperty(node.decorators, append_declare(node.modifiers, !stack.flag_declare), node.name, node.questionToken, node.type, undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* class types */
|
|
||||||
generators[SyntaxKind.ClassDeclaration] = (settings, stack, node: ts.ClassDeclaration) => {
|
|
||||||
if((stack.flag_namespace || settings.module_mode) && !has_modifier(node.modifiers, SyntaxKind.ExportKeyword))
|
|
||||||
return;
|
|
||||||
|
|
||||||
const members = [] as ts.Node[];
|
|
||||||
{
|
|
||||||
stack.push({
|
|
||||||
flag_declare: true,
|
|
||||||
flag_namespace: false,
|
|
||||||
flag_class: true
|
|
||||||
});
|
|
||||||
|
|
||||||
node.forEachChild(n => {
|
|
||||||
if(n.kind == SyntaxKind.Identifier) return; /* class identifier */
|
|
||||||
if(ts.isModifier(n)) return; /* we have already class modifiers */
|
|
||||||
|
|
||||||
_generate(settings, stack, members, n)
|
|
||||||
});
|
|
||||||
stack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
members.sort((a, b) => {
|
|
||||||
if(a.kind > b.kind) return 1;
|
|
||||||
if(a.kind < b.kind) return -1;
|
|
||||||
|
|
||||||
if(a.kind == SyntaxKind.FunctionDeclaration)
|
|
||||||
return (<ts.FunctionDeclaration>b).name.escapedText.toString().localeCompare((<ts.FunctionDeclaration>a).name.escapedText.toString());
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
const decorators = node.decorators?.map(e => {
|
|
||||||
let text: string;
|
|
||||||
if(e.getSourceFile())
|
|
||||||
text = e.getText();
|
|
||||||
else
|
|
||||||
text = "*synthetic added annotation*";
|
|
||||||
return ts.createIdentifier("/* " + text.replace("*/", "* /") + " */");
|
|
||||||
});
|
|
||||||
return ts.createClassDeclaration(decorators as any, append_export(append_declare(node.modifiers, !stack.flag_declare), stack.flag_namespace), node.name, node.typeParameters, node.heritageClauses, members as any);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.PropertySignature] = (settings, stack, node: ts.PropertySignature) => {
|
|
||||||
if(!node.type)
|
|
||||||
return node;
|
|
||||||
|
|
||||||
let type: ts.TypeNode = node.type;
|
|
||||||
switch (node.type.kind) {
|
|
||||||
case SyntaxKind.LiteralType:
|
|
||||||
type = ts.createIdentifier("any") as any;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ts.createPropertySignature(node.modifiers, node.name, node.questionToken, type, undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.InterfaceDeclaration] = (settings, stack, node: ts.InterfaceDeclaration) => {
|
|
||||||
if(settings.remove_private.field && has_private(node.modifiers)) return;
|
|
||||||
if(stack.flag_namespace && !has_modifier(node.modifiers, SyntaxKind.ExportKeyword)) return;
|
|
||||||
|
|
||||||
const members: any[] = [];
|
|
||||||
for(const member of node.members) {
|
|
||||||
if(generators[member.kind])
|
|
||||||
members.push(generators[member.kind](settings, stack, member));
|
|
||||||
else
|
|
||||||
members.push(member);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ts.createInterfaceDeclaration(undefined, append_export(append_declare(node.modifiers, !stack.flag_declare), stack.flag_namespace), node.name, node.typeParameters, node.heritageClauses, members);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.VariableDeclaration] = (settings, stack, node: ts.VariableDeclaration) => {
|
|
||||||
return ts.createVariableDeclaration(node.name, node.type, undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.VariableDeclarationList] = (settings, stack, node: ts.VariableDeclarationList) => {
|
|
||||||
const decls: any[] = [];
|
|
||||||
for(const decl of node.declarations)
|
|
||||||
decls.push(generators[SyntaxKind.VariableDeclaration](settings, stack, decl) as any);
|
|
||||||
return ts.createVariableDeclarationList(decls, node.flags);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.VariableStatement] = (settings, stack, node: ts.VariableStatement) => {
|
|
||||||
if(settings.remove_private.field && has_private(node.modifiers)) return;
|
|
||||||
|
|
||||||
if(stack.flag_class) {
|
|
||||||
|
|
||||||
} else if(stack.flag_namespace) {
|
|
||||||
if(!has_modifier(node.modifiers, SyntaxKind.ExportKeyword)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ts.createVariableStatement(append_declare(node.modifiers, !stack.flag_declare), generators[node.declarationList.kind](settings, stack, node.declarationList) as any);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.TypeAliasDeclaration] = (settings, stack, node: ts.TypeAliasDeclaration) => {
|
|
||||||
if(stack.flag_namespace && !has_modifier(node.modifiers, SyntaxKind.ExportKeyword)) return;
|
|
||||||
|
|
||||||
let type = node.type;
|
|
||||||
if(type.kind == SyntaxKind.UnionType) {
|
|
||||||
const union_members = [];
|
|
||||||
const union = <ts.UnionTypeNode>node.type;
|
|
||||||
|
|
||||||
for(const element of union.types as any as any[]) {
|
|
||||||
union_members.push(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
type = ts.createUnionTypeNode(union_members);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ts.createTypeAliasDeclaration(node.decorators, append_declare(node.modifiers, !stack.flag_declare), node.name, node.typeParameters, type);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.EnumMember] = (settings, stack, node: ts.EnumMember) => {
|
|
||||||
return ts.createEnumMember(node.name, node.initializer);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.EnumDeclaration] = (settings, stack, node: ts.EnumDeclaration) => {
|
|
||||||
const members: any[] = [];
|
|
||||||
|
|
||||||
let uninitialized_index = 0;
|
|
||||||
for(const member of node.members) {
|
|
||||||
let initializer = member.initializer;
|
|
||||||
if(!initializer)
|
|
||||||
initializer = ts.createIdentifier((uninitialized_index++).toString());
|
|
||||||
members.push(ts.createEnumMember(member.name, initializer));
|
|
||||||
}
|
|
||||||
return ts.createEnumDeclaration(undefined, append_export(append_declare(node.modifiers, !stack.flag_declare), stack.flag_namespace), node.name, members);
|
|
||||||
};
|
|
||||||
|
|
||||||
generators[SyntaxKind.HeritageClause] = () => undefined;
|
|
||||||
|
|
||||||
/* every variable in a block has no global scope! */
|
|
||||||
generators[SyntaxKind.Block] = () => undefined;
|
|
||||||
generators[SyntaxKind.IfStatement] = () => undefined;
|
|
||||||
|
|
||||||
/* Example for an ExpressionStatement would be: Module["text"] = "XXX"; */
|
|
||||||
generators[SyntaxKind.ExpressionStatement] = () => undefined;
|
|
||||||
generators[SyntaxKind.SemicolonClassElement] = () => undefined;
|
|
||||||
|
|
||||||
generators[SyntaxKind.ImportDeclaration] = (settings, stack, node: ts.ImportDeclaration) => {
|
|
||||||
const specifier = node.moduleSpecifier as ts.StringLiteral;
|
|
||||||
if(specifier.kind !== SyntaxKind.StringLiteral)
|
|
||||||
throw "cant handle import declaration with specifier of type " + specifier.kind;
|
|
||||||
|
|
||||||
return ts.createImportDeclaration(
|
|
||||||
node.decorators,
|
|
||||||
node.modifiers,
|
|
||||||
node.importClause,
|
|
||||||
ts.createStringLiteral(specifier.text)
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -1,15 +0,0 @@
|
||||||
import * as ts from "typescript";
|
|
||||||
import {SyntaxKind} from "typescript";
|
|
||||||
|
|
||||||
let has_export;
|
|
||||||
const visit = (node: ts.Node) => has_export = has_export || (node.modifiers || [] as any).filter(e => e.kind === SyntaxKind.ExportKeyword).length !== 0 || ts.forEachChild(node, visit);
|
|
||||||
|
|
||||||
export function fix_declare_global(nodes: ts.Node[]) : ts.Node[] {
|
|
||||||
has_export = false;
|
|
||||||
|
|
||||||
// nodes.forEach(visit); /* for a "deep" check */
|
|
||||||
nodes.forEach(e => has_export = has_export || (e.modifiers || [] as any).filter(e => e.kind === SyntaxKind.ExportKeyword).length !== 0);
|
|
||||||
if(has_export) return nodes;
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
|
@ -1,272 +0,0 @@
|
||||||
import * as ts from "typescript";
|
|
||||||
import {SyntaxKind} from "typescript";
|
|
||||||
|
|
||||||
interface RequiredType {
|
|
||||||
identifier: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ImportsParserData {
|
|
||||||
readonly source_file: ts.SourceFile;
|
|
||||||
required_type: RequiredType[];
|
|
||||||
depth: number;
|
|
||||||
|
|
||||||
constructor(sf: ts.SourceFile) {
|
|
||||||
this.source_file = sf;
|
|
||||||
this.required_type = [];
|
|
||||||
this.depth = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
has_type(name: string) {
|
|
||||||
return this.required_type.findIndex(e => e.identifier === name) !== -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function remove_unused(source_file: ts.SourceFile, nodes: ts.Node[]) : ts.Node[] {
|
|
||||||
const data = new ImportsParserData(source_file);
|
|
||||||
|
|
||||||
for(const node of nodes)
|
|
||||||
gather_required_types(node, data);
|
|
||||||
|
|
||||||
//console.log(data.required_type);
|
|
||||||
const result2d = nodes.map(e => ts.transform(e, [ctx => node => eliminate_imports(node, ctx, data)])).map(e => e.transformed);
|
|
||||||
const result = [];
|
|
||||||
for(const entry of result2d)
|
|
||||||
result.push(...entry);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function eliminate_imports(node: ts.Node, ctx: ts.TransformationContext, data: ImportsParserData) : ts.Node | undefined {
|
|
||||||
switch (node.kind) {
|
|
||||||
case SyntaxKind.ImportDeclaration:
|
|
||||||
const import_decl = node as ts.ImportDeclaration;
|
|
||||||
const clause = import_decl.importClause;
|
|
||||||
if(!clause?.namedBindings) return node;
|
|
||||||
|
|
||||||
let new_binding;
|
|
||||||
if(clause.namedBindings.kind === SyntaxKind.NamedImports) {
|
|
||||||
const bindings = clause.namedBindings as ts.NamedImports;
|
|
||||||
const elements = bindings.elements.filter(e => data.has_type(e.name.text));
|
|
||||||
if(!elements.length) return ts.createIdentifier("");
|
|
||||||
|
|
||||||
new_binding = ts.createNamedImports(elements);
|
|
||||||
} else if(clause.namedBindings.kind === SyntaxKind.NamespaceImport) {
|
|
||||||
const binding = clause.namedBindings as ts.NamespaceImport;
|
|
||||||
if(!data.has_type(binding.name.text))
|
|
||||||
return ts.createIdentifier("");
|
|
||||||
new_binding = binding;
|
|
||||||
} else
|
|
||||||
throw "unknown named binding";
|
|
||||||
|
|
||||||
return ts.createImportDeclaration(import_decl.decorators, import_decl.modifiers, new_binding, import_decl.moduleSpecifier);
|
|
||||||
default:
|
|
||||||
return ts.visitEachChild(node, e => eliminate_imports(e, ctx, data), ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const import_parsers: {[key: number]:(node: ts.Node, data: ImportsParserData) => void} = {};
|
|
||||||
function gather_required_types(node: ts.Node, data: ImportsParserData) {
|
|
||||||
if(!node) return;
|
|
||||||
//console.log("%d %s", data.depth, SyntaxKind[node.kind]);
|
|
||||||
|
|
||||||
if(import_parsers[node.kind]) {
|
|
||||||
import_parsers[node.kind](node, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.depth++;
|
|
||||||
node.forEachChild(e => gather_required_types(e, data));
|
|
||||||
data.depth--;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
import_parsers[SyntaxKind.Parameter] = (node: ts.ParameterDeclaration, data) => {
|
|
||||||
if(!node.type) return;
|
|
||||||
|
|
||||||
analyze_type_node(node.type, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
import_parsers[SyntaxKind.TypeAliasDeclaration] = (node: ts.TypeAliasDeclaration, data) => {
|
|
||||||
(node.typeParameters || []).forEach(e => gather_required_types(e, data));
|
|
||||||
if(node.type) analyze_type_node(node.type, data);
|
|
||||||
if(node.decorators) node.decorators.forEach(e => analyze_type_node(e.expression, data));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
import_parsers[SyntaxKind.HeritageClause] = (node: ts.HeritageClause, data) => {
|
|
||||||
const heritage = node as ts.HeritageClause;
|
|
||||||
for(const type of heritage.types)
|
|
||||||
analyze_type_node(type, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
import_parsers[SyntaxKind.TypeParameter] = (node: ts.TypeParameterDeclaration, data) => {
|
|
||||||
if(node.constraint) analyze_type_node(node.constraint, data);
|
|
||||||
if(node.default) analyze_type_node(node.default, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
import_parsers[SyntaxKind.FunctionDeclaration] = (node: ts.FunctionDeclaration, data) => {
|
|
||||||
if(node.type)
|
|
||||||
analyze_type_node(node.type, data);
|
|
||||||
(node.typeParameters || []).forEach(e => gather_required_types(e, data));
|
|
||||||
for(const param of node.parameters)
|
|
||||||
gather_required_types(param, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
import_parsers[SyntaxKind.MethodSignature] = (node: ts.MethodSignature, data) => {
|
|
||||||
if(node.type)
|
|
||||||
analyze_type_node(node.type, data);
|
|
||||||
(node.typeParameters || []).forEach(e => gather_required_types(e, data));
|
|
||||||
for(const param of node.parameters)
|
|
||||||
gather_required_types(param, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
import_parsers[SyntaxKind.ClassDeclaration] = (node: ts.ClassDeclaration, data) => {
|
|
||||||
for(const e of node.heritageClauses || [])
|
|
||||||
gather_required_types(e, data);
|
|
||||||
|
|
||||||
for(const e of node.typeParameters || [])
|
|
||||||
gather_required_types(e, data);
|
|
||||||
|
|
||||||
for(const e of node.members || [])
|
|
||||||
gather_required_types(e, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
import_parsers[SyntaxKind.PropertySignature] = (node: ts.PropertySignature, data) => {
|
|
||||||
analyze_type_node(node.type, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
import_parsers[SyntaxKind.PropertyDeclaration] = (node: ts.PropertyDeclaration, data) => {
|
|
||||||
analyze_type_node(node.type, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
import_parsers[SyntaxKind.MethodDeclaration] = (node: ts.MethodDeclaration, data) => {
|
|
||||||
for(const e of node.parameters || [])
|
|
||||||
gather_required_types(e, data);
|
|
||||||
for(const e of node.typeParameters || [])
|
|
||||||
gather_required_types(e, data);
|
|
||||||
analyze_type_node(node.type, data);
|
|
||||||
};
|
|
||||||
|
|
||||||
function analyze_type_node(node: ts.TypeNode | ts.LeftHandSideExpression, data: ImportsParserData) {
|
|
||||||
if(!node) return;
|
|
||||||
|
|
||||||
//console.log("T: %s", SyntaxKind[node.kind]);
|
|
||||||
switch (node.kind) {
|
|
||||||
case SyntaxKind.AnyKeyword:
|
|
||||||
case SyntaxKind.VoidKeyword:
|
|
||||||
case SyntaxKind.ThisType:
|
|
||||||
case SyntaxKind.ThisKeyword:
|
|
||||||
case SyntaxKind.BooleanKeyword:
|
|
||||||
case SyntaxKind.StringKeyword:
|
|
||||||
case SyntaxKind.StringLiteral:
|
|
||||||
case SyntaxKind.LiteralType:
|
|
||||||
case SyntaxKind.NumberKeyword:
|
|
||||||
case SyntaxKind.ObjectKeyword:
|
|
||||||
case SyntaxKind.NullKeyword:
|
|
||||||
case SyntaxKind.NeverKeyword:
|
|
||||||
case SyntaxKind.UndefinedKeyword:
|
|
||||||
/* no special export type */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.UnionType:
|
|
||||||
const union = node as ts.UnionTypeNode;
|
|
||||||
union.types.forEach(e => analyze_type_node(e, data));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.IntersectionType:
|
|
||||||
const intersection = node as ts.IntersectionTypeNode;
|
|
||||||
intersection.types.forEach(e => analyze_type_node(e, data));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.TypeReference:
|
|
||||||
const ref = node as ts.TypeReferenceNode;
|
|
||||||
if(ref.typeName.kind === SyntaxKind.Identifier) {
|
|
||||||
data.required_type.push({
|
|
||||||
identifier: ref.typeName.text
|
|
||||||
});
|
|
||||||
} else if(ref.typeName.kind === SyntaxKind.QualifiedName) {
|
|
||||||
let left: ts.Identifier | ts.QualifiedName = ref.typeName.left;
|
|
||||||
while(left.kind !== SyntaxKind.Identifier)
|
|
||||||
left = left.left;
|
|
||||||
data.required_type.push({
|
|
||||||
identifier: left.text
|
|
||||||
});
|
|
||||||
} else
|
|
||||||
throw "invalid type name";
|
|
||||||
for(const e of ref.typeArguments || [])
|
|
||||||
analyze_type_node(e, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.Identifier:
|
|
||||||
data.required_type.push({
|
|
||||||
identifier: (node as ts.Identifier).text
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.TypeLiteral:
|
|
||||||
const lit = node as ts.TypeLiteralNode;
|
|
||||||
for(const member of lit.members)
|
|
||||||
gather_required_types(member, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.ArrayType:
|
|
||||||
const array = node as ts.ArrayTypeNode;
|
|
||||||
analyze_type_node(array.elementType, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.FunctionType:
|
|
||||||
const fn = node as ts.FunctionTypeNode;
|
|
||||||
for(const param of fn.parameters || [])
|
|
||||||
gather_required_types(param, data);
|
|
||||||
|
|
||||||
for(const type of fn.typeParameters || [])
|
|
||||||
gather_required_types(type, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.TypeOperator:
|
|
||||||
const to = node as ts.TypeOperatorNode;
|
|
||||||
analyze_type_node(to.type, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.ExpressionWithTypeArguments:
|
|
||||||
analyze_type_node((node as ts.ExpressionWithTypeArguments).expression, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.IndexedAccessType:
|
|
||||||
const ia = node as ts.IndexedAccessTypeNode;
|
|
||||||
analyze_type_node(ia.indexType, data);
|
|
||||||
analyze_type_node(ia.objectType, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.ParenthesizedType:
|
|
||||||
const parenthesized = node as ts.ParenthesizedTypeNode;
|
|
||||||
analyze_type_node(parenthesized.type, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.MappedType:
|
|
||||||
const mt = node as ts.MappedTypeNode;
|
|
||||||
analyze_type_node(mt.type, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.PropertyAccessExpression:
|
|
||||||
let pae = node as ts.PropertyAccessExpression;
|
|
||||||
while(pae.expression.kind == SyntaxKind.PropertyAccessExpression)
|
|
||||||
pae = pae.expression as ts.PropertyAccessExpression;
|
|
||||||
|
|
||||||
analyze_type_node(pae.expression, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.ConstructorType:
|
|
||||||
let ct = node as ts.ConstructorTypeNode;
|
|
||||||
analyze_type_node(ct.type, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.TupleType:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SyntaxKind.ConditionalType:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw "Unknown type " + SyntaxKind[node.kind] + ". Extend me :)";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,129 +0,0 @@
|
||||||
import {readFileSync, writeFileSync, mkdir, existsSync} from "fs";
|
|
||||||
import * as ts from "typescript";
|
|
||||||
import * as decl from "./declarator";
|
|
||||||
import * as glob from "glob";
|
|
||||||
import * as path from "path";
|
|
||||||
import * as mkdirp from "mkdirp";
|
|
||||||
import {removeSync} from "fs-extra";
|
|
||||||
import * as import_organizer from "./import_organizer";
|
|
||||||
import * as declare_fixup from "./declare_fixup";
|
|
||||||
|
|
||||||
let source_files: string[] = [];
|
|
||||||
let exclude_files: string[] = [];
|
|
||||||
let target_directory: string = "out.d/";
|
|
||||||
let verbose: boolean = false;
|
|
||||||
let config_file: string = undefined;
|
|
||||||
let base_path = process.cwd();
|
|
||||||
let module_mode: boolean = false;
|
|
||||||
|
|
||||||
let args = process.argv.slice(2);
|
|
||||||
while(args.length > 0) {
|
|
||||||
if(args[0] === "--file") {
|
|
||||||
source_files.push(args[1]);
|
|
||||||
args = args.slice(2);
|
|
||||||
} else if(args[0] === "--exclude") {
|
|
||||||
exclude_files.push(args[1]);
|
|
||||||
args = args.slice(2);
|
|
||||||
} else if(args[0] === "--destination") {
|
|
||||||
target_directory = args[1];
|
|
||||||
args = args.slice(2);
|
|
||||||
} else if(args[0] === "-v" || args[0] === "--verbose") {
|
|
||||||
verbose = true;
|
|
||||||
args = args.slice(1);
|
|
||||||
} else if(args[0] === "-c" || args[0] === "--config") {
|
|
||||||
config_file = args[1];
|
|
||||||
base_path = path.normalize(path.dirname(config_file));
|
|
||||||
args = args.slice(2);
|
|
||||||
} else if(args[0] === "-b" || args[0] === "--base-directory") {
|
|
||||||
base_path = args[1];
|
|
||||||
base_path = path.normalize(base_path);
|
|
||||||
args = args.slice(2);
|
|
||||||
} else if(args[0] === "-m" || args[0] === "--module") {
|
|
||||||
module_mode = true;
|
|
||||||
args = args.slice(1);
|
|
||||||
} else {
|
|
||||||
console.error("Invalid command line option %s", args[0]);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(config_file) {
|
|
||||||
console.log("Loading config file");
|
|
||||||
const json = JSON.parse(readFileSync(config_file).toString());
|
|
||||||
if(!json) {
|
|
||||||
console.error("Failed to parse config!");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Array.isArray(json["source_files"]))
|
|
||||||
source_files.push(...json["source_files"]);
|
|
||||||
if(Array.isArray(json["exclude"]))
|
|
||||||
exclude_files.push(...json["exclude"]);
|
|
||||||
if(typeof json["target_directory"] === "string")
|
|
||||||
target_directory = json["target_directory"];
|
|
||||||
if(typeof json["base_directory"] === "string")
|
|
||||||
base_path = json["base_directory"];
|
|
||||||
if(typeof json["modular"] === "boolean")
|
|
||||||
module_mode = json["modular"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(verbose) {
|
|
||||||
console.log("Base path: " + base_path);
|
|
||||||
console.log("Input files:");
|
|
||||||
for(const file of source_files)
|
|
||||||
console.log(" - " + file);
|
|
||||||
console.log("Target directory: " + target_directory);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(existsSync(target_directory)) {
|
|
||||||
removeSync(target_directory);
|
|
||||||
if(existsSync(target_directory)) {
|
|
||||||
console.error("Failed to remove target directory (%s)", target_directory);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const negate_files: string[] = [].concat.apply([], exclude_files.map(file => glob.sync(base_path + "/" + file))).map(file => path.normalize(file));
|
|
||||||
|
|
||||||
source_files.forEach(file => {
|
|
||||||
const glob_base = path.normalize(path.join(process.cwd(), base_path));
|
|
||||||
if(verbose)
|
|
||||||
console.log("Globbing %s", glob_base);
|
|
||||||
glob.sync(glob_base + "/" + file).forEach(_file => {
|
|
||||||
_file = path.normalize(_file);
|
|
||||||
if(!_file.startsWith(glob_base)) {
|
|
||||||
/* this should never happen */
|
|
||||||
console.log("Skipping %s because of unmatching base directory.", _file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for(const n_file of negate_files) {
|
|
||||||
if(n_file == _file) {
|
|
||||||
console.log("Skipping %s", _file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const relpath = _file.substr(glob_base.length);
|
|
||||||
let source = ts.createSourceFile(
|
|
||||||
_file,
|
|
||||||
readFileSync(_file).toString(),
|
|
||||||
ts.ScriptTarget.ES2015,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log("Compile %s (%s)", _file, relpath);
|
|
||||||
const decl_nodes = decl.generate(source, {
|
|
||||||
remove_private: true,
|
|
||||||
module_mode: module_mode
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = decl.print(source, declare_fixup.fix_declare_global(import_organizer.remove_unused(source, decl_nodes)));
|
|
||||||
|
|
||||||
let fpath = path.join(base_path, target_directory, relpath);
|
|
||||||
fpath = fpath.substr(0, fpath.lastIndexOf(".")) + ".d.ts";
|
|
||||||
mkdirp(path.normalize(path.dirname(fpath)), error => {
|
|
||||||
if(error) throw error;
|
|
||||||
writeFileSync(fpath, result);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,11 +0,0 @@
|
||||||
export class TestClass {
|
|
||||||
public say_hi() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function say_hello_a() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export namespace X {
|
|
||||||
export class Y {}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
import * as module_a from "./module_a";
|
|
||||||
|
|
||||||
export class C extends module_a.TestClass {}
|
|
||||||
|
|
||||||
export const say_a = module_a.say_hello_a;
|
|
||||||
export function say_b() {
|
|
||||||
console.log("B!");
|
|
||||||
module_a.say_hello_a();
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
/* IMPOTZ COMMENT */
|
|
||||||
import * as module_a from "./module_a";
|
|
||||||
|
|
||||||
/* CLASS COMMENT!*/
|
|
||||||
export class C extends module_a.TestClass {}
|
|
||||||
|
|
||||||
/* Say a comment */
|
|
||||||
export const say_a = module_a.say_hello_a;
|
|
||||||
|
|
||||||
/* Say b comment */
|
|
||||||
export function say_b() {
|
|
||||||
console.log("B!");
|
|
||||||
module_a.say_hello_a();
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
import * as a from "./module_a";
|
|
||||||
|
|
||||||
export declare class PokeModal {
|
|
||||||
//private source_map: a.TestClass[];
|
|
||||||
private _awaiters_unique_ids: {
|
|
||||||
[unique_id: string]: ((resolved: a.TestClass) => any)[];
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
declare global {
|
|
||||||
interface X {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export = {};
|
|
|
@ -1,11 +0,0 @@
|
||||||
enum A {
|
|
||||||
A = "_a",
|
|
||||||
B = 2,
|
|
||||||
C,
|
|
||||||
D = 3,
|
|
||||||
E
|
|
||||||
}
|
|
||||||
|
|
||||||
export type B = {
|
|
||||||
a: A.B
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
/* File: tools\dtsgen\test_modular\test_01.ts */
|
|
||||||
import * as module_a from "./module_a";
|
|
||||||
export declare const say_a;
|
|
||||||
export declare function say_b();
|
|
|
@ -1,47 +0,0 @@
|
||||||
function test() : string {
|
|
||||||
|
|
||||||
return "IDK!";
|
|
||||||
}
|
|
||||||
|
|
||||||
class C {
|
|
||||||
|
|
||||||
}
|
|
||||||
function test2() : C {
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
// @ts-ignore
|
|
||||||
function test4() : D {
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace T {
|
|
||||||
function C() {
|
|
||||||
|
|
||||||
}
|
|
||||||
export function D() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace T {
|
|
||||||
namespace Y {
|
|
||||||
function T() {}
|
|
||||||
|
|
||||||
export function Y() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace T {
|
|
||||||
export async function async_void() {}
|
|
||||||
export async function async_any() : Promise<any> {
|
|
||||||
return "" as any;
|
|
||||||
}
|
|
||||||
export async function async_number() : Promise<number> {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
export async function async_number_string() : Promise<number | string> {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
class A {
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
a() : void{ }
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace B {
|
|
||||||
export class C {
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
a() : void{ }
|
|
||||||
|
|
||||||
get c() { return undefined; }
|
|
||||||
set c(_) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
declare class XXX {
|
|
||||||
private static _audioInstances;
|
|
||||||
private static _globalReplayScheduler;
|
|
||||||
private static _timeIndex;
|
|
||||||
private static _audioDestinationStream;
|
|
||||||
static initializeAudioController(): void;
|
|
||||||
speakerContext: AudioContext;
|
|
||||||
private playerState;
|
|
||||||
private audioCache;
|
|
||||||
private playingAudioCache;
|
|
||||||
private _volume;
|
|
||||||
private _codecCache;
|
|
||||||
private _timeIndex;
|
|
||||||
private _latencyBufferLength;
|
|
||||||
private _buffer_timeout;
|
|
||||||
allowBuffering: boolean;
|
|
||||||
onSpeaking: () => void;
|
|
||||||
onSilence: () => void;
|
|
||||||
constructor();
|
|
||||||
initialize(): void;
|
|
||||||
close(): void;
|
|
||||||
playBuffer(buffer: AudioBuffer): void;
|
|
||||||
private playQueue;
|
|
||||||
private removeNode;
|
|
||||||
stopAudio(now?: boolean): void;
|
|
||||||
private testBufferQueue;
|
|
||||||
private reset_buffer_timeout;
|
|
||||||
volume: number;
|
|
||||||
private applyVolume;
|
|
||||||
codecCache(codec: number): CodecClientCache;
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
enum YY {
|
|
||||||
H = "C",
|
|
||||||
B = "Y"
|
|
||||||
}
|
|
||||||
|
|
||||||
interface X {
|
|
||||||
type: "",
|
|
||||||
c: YY.B
|
|
||||||
}
|
|
||||||
|
|
||||||
class X {
|
|
||||||
static async x();
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
type T = "a" | "b" | "c";
|
|
||||||
|
|
||||||
function _t(parm: T) {}
|
|
||||||
function __t() {}
|
|
||||||
|
|
||||||
function __0(a: "a" | "b") {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
/// <reference path="A" />
|
|
||||||
/// <reference path="B" />
|
|
||||||
|
|
||||||
abstract class InfoManagerBase { }
|
|
||||||
|
|
||||||
/* Simple test case to fix the "decl" merge bug */
|
|
||||||
/*
|
|
||||||
File: C:\Users\WolverinDEV\TeaSpeak\TeaWeb\tools\dtsgen\test\test_05.ts
|
|
||||||
declare /// <reference path="A" />
|
|
||||||
/// <reference path="B" />
|
|
||||||
abstract class InfoManagerBase {
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -1,6 +0,0 @@
|
||||||
/* get <name>() is not allowed within decl files. So declare the variable instead */
|
|
||||||
|
|
||||||
class A {
|
|
||||||
get x() { return "X"; }
|
|
||||||
set x(value: string) {}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
namespace C {
|
|
||||||
type B = string;
|
|
||||||
}
|
|
||||||
namespace C {
|
|
||||||
type B = string;
|
|
||||||
export function test(arg: string) {}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": ".",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"module": "commonjs",
|
|
||||||
"lib": ["es6", "dom"]
|
|
||||||
|
|
||||||
/*
|
|
||||||
"typeRoots": [],
|
|
||||||
"types": [],
|
|
||||||
*/
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"declarator.ts",
|
|
||||||
"index.ts"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import {BrowserInfo} from "detect-browser";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface BuildDefinitions {
|
interface BuildDefinitions {
|
||||||
target: "web" | "client";
|
target: "web" | "client";
|
||||||
|
@ -11,6 +13,13 @@ declare global {
|
||||||
}
|
}
|
||||||
|
|
||||||
const __build: BuildDefinitions;
|
const __build: BuildDefinitions;
|
||||||
|
const __webpack_require__;
|
||||||
|
|
||||||
|
/* Well this isn't a build definition, but we have to declare it somewhere globally */
|
||||||
|
interface Window {
|
||||||
|
detectedBrowser: BrowserInfo,
|
||||||
|
removeLoaderContextMenuHook: () => void
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {};
|
export {};
|
Loading…
Reference in New Issue