typescript的基本结构_架构概述
层次概述
核心TypeScript编译器
语法分析器(Parser): 以一系列原文件开始, 根据语言的语法, 生成抽象语法树(AST)
联合器(Binder): 使用一个Symbol将针对相同结构的声明联合在一起(例如:同一个接口或模块的不同声明,或拥有相同名字的函数和模块)。这能帮助类型系统推导出这些具名的声明。
类型解析器与检查器(Type resolver / Checker): 解析每种类型的构造,检查读写语义并生成适当的诊断信息。
生成器(Emitter): 从一系列输入文件(.ts和.d.ts)生成输出,它们可以是以下形式之一:JavaScript(.js),声明(.d.ts),或者是source maps(.js.map)。
预处理器(Pre-processor): “编译上下文”指的是某个“程序”里涉及到的所有文件。上下文的创建是通过检查所有从命令行上传入编译器的文件,按顺序,然后再加入这些文件直接引用的其它文件或通过import语句和/// 标签间接引用的其它文件。
沿着引用图走下来你会发现它是一个有序的源文件列表,它们组成了整个程序。 当解析导出(import)的时候,会优先选择“.ts”文件而不是“.d.ts”文件,以确保处理的是最新的文件。 编译器会进行与Nodejs相似的流程来解析导入,沿着目录链查找与将要导入相匹配的带.ts或.d.ts扩展名的文件。 导入失败不会报error,因为可能已经声明了外部模块。
独立编译器(tsc): 批处理编译命令行界面。主要处理针对不同支持的引擎读写文件(比如:Node.js)。
语言服务: “语言服务”在核心编译器管道上暴露了额外的一层,非常适合类编辑器的应用。
语言服务支持一系列典型的编辑器操作比如语句自动补全,函数签名提示,代码格式化和突出高亮,着色等。 基本的重构功能比如重命名,调试接口辅助功能比如验证断点,还有TypeScript特有的功能比如支持增量编译(在命令行上使用--watch)。 语言服务是被设计用来有效的处理在一个长期存在的编译上下文中文件随着时间改变的情况;在这样的情况下,语言服务提供了与其它编译器接口不同的角度来处理程序和源文件。
数据结构
Node: 抽象语法树(AST)的基本组成块。通常Node表示语言语法里的非终结符;一些终结符保存在语法树里比如标识符和字面量。
SourceFile: 给定源文件的AST。SourceFile本身是一个Node;它提供了额外的接口用来访问文件的源码,文件里的引用,文件里的标识符列表和文件里的某个位置与它对应的行号与列号的映射。
Program: SourceFile的集合和一系列编译选项代表一个编译单元。Program是类型系统和生成代码的主入口。
Symbol: 具名的声明。Symbols是做为联合的结果而创建。Symbols连接了树里的声明节点和其它对同一个实体的声明。Symbols是语义系统的基本构建块。
Type: Type是语义系统的其它部分。Type可能被命名(比如,类和接口),或匿名(比如,对象类型)。
Signature: 一共有三种Signature类型:调用签名(call),构造签名(construct)和索引签名(index)。
编译过程概述
整个过程从预处理开始。 预处理器会算出哪些文件参与编译,它会去查找如下引用(/// 标签和import语句)。
语法分析器(Parser)生成抽象语法树(AST)Node. 这些仅为用户输出的抽象表现,以树的形式。 一个SourceFile对象表示一个给定文件的AST并且带有一些额外的信息如文件名及源文件内容。
然后,联合器(Binder)处理AST节点,结合并生成Symbols。 一个Symbol会对应到一个命名实体。 这里有个一微妙的差别,几个声明节点可能会是名字相同的实体。 也就是说,有时候不同的Node具有相同的Symbol,并且每个Symbol保持跟踪它的声明节点。 比如,一个名字相同的class和namespace可以合并,并且拥有相同的Symbol。 联合器也会处理作用域,以确保每个Symbol都在正确的封闭作用域里创建。
生成SourceFile(还带有它的Symbols们)是通过调用createSourceFile API。
到目前为止,Symbol代表的命名实体可以在单个文件里看到,但是有些声明可以从多文件合并,因此下一步就是构建一个全局的包含所有文件的视图,也就是创建一个Program。
一个Program是SourceFile的集合并带有一系列CompilerOptions。 通过调用createProgram API来创建Program。
通过一个Program实例创建TypeChecker。 TypeChecker是TypeScript类型系统的核心。 它负责计算出不同文件里的Symbols之间的关系,将Type赋值给Symbol,并生成任何语义Diagnostic(比如:error)。
TypeChecker首先要做的是合并不同的SourceFile里的Symbol到一个单独的视图,创建单一的Symbol表,合并所有普通的Symbol(比如:不同文件里的namespace)。
在原始状态初始化完成后,TypeChecker就可以解决关于这个程序的任何问题了。 这些“问题”可以是:
这个Node的Symbol是什么?
这个Symbol的Type是什么?
在AST的某个部分里有哪些Symbol是可见的?
某个函数声明的Signature都有哪些?
针对某个文件应该报哪些错误?
TypeChecker计算所有东西都是“懒惰的”;为了回答一个问题它仅“解决”必要的信息。 TypeChecker仅会检测和这个问题有关的Node,Symbol或Type,不会检测额外的实体。
对于一个Program同样会生成一个Emitter。 Emitter负责生成给定SourceFile的输出;它包括:.js,.jsx,.d.ts和.js.map。
术语
完整开始/令牌开始(Full Start/Token Start)
令牌本身就具有我们称为一个“完整开始”和一个“令牌开始”。“令牌开始”是指更自然的版本,它表示在文件中令牌开始的位置。“完整开始”是指从上一个有意义的令牌之后扫描器开始扫描的起始位置。当关心琐事时,我们往往更关心完整开始。
函数
描述
ts.Node.getStart
取得某节点的第一个令牌起始位置。
ts.Node.getFullStart
取得某节点拥有的第一个令牌的完整开始。
琐碎内容(Trivia)
语法的琐碎内容代表源码里那些对理解代码无关紧要的内容,比如空白,注释甚至一些冲突的标记。
因为琐碎内容不是语言正常语法的一部分(不包括ECMAScript API规范)并且可能在任意2个令牌中的任意位置出现,它们不会包含在语法树里。但是,因为它们对于像重构和维护高保真源码很重要,所以需要的时候还是能够通过我们的APIs访问。
因为EndOfFileToken后面可以没有任何内容(令牌和琐碎内容),所有琐碎内容自然地在非琐碎内容之前,而且存在于那个令牌的“完整开始”和“令牌开始”之间。
虽然这个一个方便的标记法来说明一个注释“属于”一个Node。比如,在下面的例子里,可以明显看出genie函数拥有两个注释:
var x = 10; // This is x.
/**
* Postcondition: Grants all three wishes.
*/
function genie([wish1, wish2, wish3]: [Wish, Wish, Wish]) {
while (true) {
}
} // End function
这是尽管事实上,函数声明的完整开始是在var x = 10;后。
我们依据Roslyn's notion of trivia ownership处理注释所有权。通常来讲,一个令牌拥有同一行上的所有的琐碎内容直到下一个令牌开始。任何出现在这行之后的注释都属于下一个令牌。源文件的第一个令牌拥有所有的初始琐碎内容,并且最后面的一系列琐碎内容会添加到end-of-file令牌上。
对于大多数普通用户,注释是“有趣的”琐碎内容。属于一个节点的注释内容可以通过下面的函数来获取:
函数
描述
ts.getLeadingCommentRanges
提供源文件和一个指定位置,返回指定位置后的第一个换行与令牌之间的注释的范围(与ts.Node.getFullStart配合会更有用)。
ts.getTrailingCommentRanges
提供源文件和一个指定位置,返回到指定位置后第一个换行为止的注释的范围(与ts.Node.getEnd配合会更有用)。
做为例子,假设有下面一部分源代码:
debugger;/*hello*/
//bye
/*hi*/ function
function关键字的完整开始是从/*hello*/注释,但是getLeadingCommentRanges仅会返回后面2个注释:
d e b u g g e r ; / * h e l l o * / _ _ _ _ _ [CR] [NL] _ _ _ _ / / b y e [CR] [NL] _ _ / * h i * / _ _ _ _ f u n c t i o n
↑ ↑ ↑ ↑ ↑
完整开始 查找 第一个注释 第二个注释 令牌开始
开始注释
适当地,在debugger语句后调用getTrailingCommentRanges可以提取出/*hello*/注释。
如果你关心令牌流的更多信息,createScanner也有一个skipTrivia标记,你可以设置成false,然后使用setText/setTextPos来扫描文件里的不同位置。
typescript的基本结构_架构概述相关推荐
- typescript的基本结构_上帝视角看 TypeScript
点击蓝色"脑洞前端"关注我哟 加个"星标",带你揭开大前端的神秘面纱! ❝ 这是脑洞前端第「99」篇原创文章 TypeScript 的学习资料非常多,其中也不乏 ...
- mysql 结构化数据库_【MySQL】——MySQL数据库和SQL结构化查询语言概述
[MySQL]--MySQL数据库和SQL结构化查询语言概述 [MySQL]--MySQL数据库和SQL结构化查询语言概述 文章目录数据库和SQL语言[1]数据库概述 [2]SQL语言 [3]MySQ ...
- 1小时学会:最简单的iOS直播推流(二)代码架构概述
最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...
- 第01章_数据库概述
第01章_数据库概述 1. 为什么要使用数据库 持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用.大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上 ...
- Nvidia CUDA初级教程4 GPU体系架构概述
Nvidia CUDA初级教程4 GPU体系架构概述 视频:https://www.bilibili.com/video/BV1kx411m7Fk?p=5 讲师:周斌 本节内容: 为什么需要GPU 三 ...
- elt和etl_ETL和ELT架构概述
elt和etl This article explains what the basic features and differences between ETL and ELT are. I'm a ...
- 【TA-霜狼_may-《百人计划》】图形2.7.2 GPU硬件架构概述
[TA-霜狼_may-<百人计划>]图形2.7.2 GPU硬件架构概述 @[TOC]([TA-霜狼_may-<百人计划>]图形2.7.2 GPU硬件架构概述 GPU是什么 GP ...
- ASP.NET Core 企业开发架构概述
ASP.NET Core 企业开发架构概述 企业开发框架包括垂直方向架构和水平方向架构.垂直方向架构是指一个应用程序的由下到上叠加多层的架构,同时这样的程序又叫整体式程序.水平方向架构是指将大应用分成 ...
- 智能家居开源平台——智汀家庭云(架构概述)
智汀家庭云,立项于2021年,结合国内智能家居各厂商软件特点,研发"智汀家庭云",并对该生态系统全面开源,为国内首个采用智能家居系统全生态开源协议(Apache License, ...
最新文章
- Individual Project-——word_frequency——final requirement
- [搜索]Trie树的一种实现
- DAX2012 R3安装
- .NET Core前后端分离快速开发框架(Core.3.0+AntdVue)
- Vuex在项目中使用
- 归并排序(视频+详解+代码)
- RabbitMQ集群原理介绍
- pom 导入mysql连接,maven项目中的jdbc连接步骤
- webpack4 filemanager-webpack-plugin 打zip包失败问题
- SD2.0-课程等待时候的摘抄
- Android-Splash
- ORACLE ebs 11.5.10 for linux 安装心得
- 我们会不会与操作系统谈一场奋不顾身的爱情──《云端情人》有感
- 纯JS实现简易扫雷小游戏网页项目
- python 批量处理文本文档基础操作
- CAD二次开发(C#) 第二节
- 【从零开始的大数据学习】Flink官方教程学习笔记(一)
- java不会英语可以学习吗,详细说明
- “汉语编程”是解决安全问题的终极之路?
- 使用FME封装一个多线程爬取m3u8在线视频的小玩意
热门文章
- 雷蛇显示服务器,雷蛇(Razer)数据泄漏暴露了游戏玩家的个人信息
- java计算机毕业设计新生报到管理系统源码+数据库+系统+lw文档+mybatis+运行部署
- git pull 无响应_git pull origin master 遇到的问题
- 默安科技再度入选2023杭州准独角兽 中国未来独角兽
- SysFader. IEXPLORE.EXE-应用程序错误解决方法
- 2021年危险化学品经营单位安全管理人员考试资料及危险化学品经营单位安全管理人员模拟考试题
- 暗黑3服务器维护能登录,暗黑3登陆错误原因及解决办法详解
- ListView部分样式属性设置
- ECCV 2022 | 视频插帧中的实时中间流估计
- STM32 DAC DMA 使用