Created
January 7, 2014 03:54
-
-
Save mwheeler/8294415 to your computer and use it in GitHub Desktop.
Example of parsing require()'s in typescript 0.9.5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var fs = require('fs'); | |
var path = require('path'); | |
// dodgy arg parsing | |
var input = process.argv[2]; | |
// import typescript | |
var TypeScript = (function(){ | |
var sandbox = { | |
__filename: __filename, | |
__dirname: __dirname, | |
global: global, | |
process: process, | |
require: require, | |
console: console, | |
exports: null, | |
setInterval: setInterval, | |
setTimeout: setTimeout | |
}; | |
var vm = require('vm'); | |
var typescript_filename = require.resolve('typescript'); | |
var source = fs.readFileSync(typescript_filename, 'utf8'); | |
var script = vm.createScript(source.concat('\n\nexports = TypeScript;'), typescript_filename); | |
script.runInNewContext(sandbox); | |
return sandbox.exports; | |
})(); | |
// Compiler settings | |
var compiler_settings = TypeScript.ImmutableCompilationSettings.fromCompilationSettings({ | |
noImplicitAny: true, | |
useCaseSensitiveFileResolution: true, | |
moduleGenTarget: TypeScript.ModuleGenTarget.Synchronous, | |
codeGenTarget: TypeScript.LanguageVersion.EcmaScript5 | |
}); | |
// Host path helper | |
var host = { | |
getScriptSnapshot: function(filename) | |
{ | |
var contents = fs.readFileSync(filename).toString(); | |
return TypeScript.ScriptSnapshot.fromString(contents); | |
}, | |
resolveRelativePath: function(pathname, dirname) | |
{ | |
return host.resolvePath(pathname, dirname); | |
//return path.relative(dirname, pathname); | |
}, | |
writeFile: function(fileName, contents, writeByteOrderMark) | |
{ | |
fs.writeFileSync(fileName, contents); | |
}, | |
getParentDirectory: function(filepath) | |
{ | |
return path.dirname(filepath); | |
}, | |
fileExists: function(path) | |
{ | |
return fs.existsSync(path); | |
}, | |
directoryExists: function(path) | |
{ | |
return fs.existsSync(path); | |
}, | |
resolvePath: function(filepath, search_paths) | |
{ | |
var search = []; | |
if(filepath[0] !== '/' && filepath[0] !== '\\') | |
{ | |
search = search.concat(search_paths).map(function(x) | |
{ | |
if(x[0] !== '/' && x[0] !== '\\') | |
{ | |
return path.join(process.cwd(), x); | |
} | |
return x; | |
}); | |
// TODO: 'built in' & task-driven search paths | |
} | |
var exts = ['', '.ts', '.js']; | |
for(var ext in exts) | |
{ | |
var args = search.concat(filepath + exts[ext]); | |
var result = path.resolve.apply(path, args); | |
if(result && fs.existsSync(result)) return result; | |
} | |
return filepath; | |
} | |
}; | |
// TypeScript compiler | |
var compiler = new TypeScript.TypeScriptCompiler(new TypeScript.NullLogger(), compiler_settings); | |
// Base input path | |
if(input[0] != '/') input = path.relative(process.cwd(), input); | |
// Add file to compiler | |
compiler.addFile(input, host.getScriptSnapshot(input), TypeScript.ByteOrderMark.Utf8, 0, false, []); | |
// Get top level decls | |
var decl = compiler.topLevelDeclaration(input); | |
// Parse ast | |
function parse_ast(ast) | |
{ | |
var result = {}; | |
switch (ast.kind()/*nodeType()*/) | |
{ | |
case TypeScript.SyntaxKind.List: | |
for(var i = 0; i < ast.childCount(); ++i) | |
{ | |
var child = parse_ast(ast.childAt(i)); | |
if(!child) continue; | |
result[child.name] = child; | |
} | |
return result; | |
case TypeScript.SyntaxKind.Script: | |
ast = ast.topLevelMod; | |
case TypeScript.SyntaxKind.ModuleDeclaration: | |
var module_name = path.basename(ast.name.text()); | |
result.name = module_name; | |
case TypeScript.SyntaxKind.SourceUnit: | |
result.type = 'module'; | |
result.value = parse_ast(ast.moduleElements); | |
return result; | |
case TypeScript.SyntaxKind.ExternalModuleReference: | |
var id = ast.stringLiteral.text().replace(/^'|^"|'$|"$/gm, ''); | |
result.type = 'require'; | |
result.value = id; | |
return result; | |
// import LocalName = require("ModuleName") | |
case TypeScript.SyntaxKind.ImportDeclaration: | |
result.type = 'import'; | |
result.name = ast.identifier.text(); | |
result.value = parse_ast(ast.moduleReference); | |
return result; | |
} | |
return undefined; | |
} | |
console.log(parse_ast(decl.ast())); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment