{"action":"created","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/6508","repository_url":"https://api.github.com/repos/Microsoft/TypeScript","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/6508/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/6508/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/6508/events","html_url":"https://github.com/Microsoft/TypeScript/issues/6508","id":126975516,"number":6508,"title":"TypeScript extensibility","user":{"login":"billti","id":993909,"avatar_url":"https://avatars.githubusercontent.com/u/993909?v=3","gravatar_id":"","url":"https://api.github.com/users/billti","html_url":"https://github.com/billti","followers_url":"https://api.github.com/users/billti/followers","following_url":"https://api.github.com/users/billti/following{/other_user}","gists_url":"https://api.github.com/users/billti/gists{/gist_id}","starred_url":"https://api.github.com/users/billti/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/billti/subscriptions","organizations_url":"https://api.github.com/users/billti/orgs","repos_url":"https://api.github.com/users/billti/repos","events_url":"https://api.github.com/users/billti/events{/privacy}","received_events_url":"https://api.github.com/users/billti/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/In%20Discussion","name":"In Discussion","color":"556b75"},{"url":"https://api.github.com/repos/Microsoft/TypeScript/labels/Suggestion","name":"Suggestion","color":"006b75"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":18,"created_at":"2016-01-15T22:55:09Z","updated_at":"2016-06-07T22:03:28Z","closed_at":null,"body":"# TypeScript Extensibility\r\n\r\nThis is an umbrella issue for tracking the design of an extensibility model for TypeScript.\r\n\r\nThere have already been a number of issues opened with regards to supporting Angular2 via such a model, (especially for richer template editing support), so this will be the initial focus. This not only ensures rich support for a key TypeScript scenario, but by solving real problems, it also ensures we are not designing in a vacuum.\r\n\r\n## High level problems\r\n\r\nThis section captures an overview of the problems to be solved. These are not of equal priority, and not all features below may be implemented, but are captured here for completeness, and to be considered in the broader picture.\r\n\r\n - Syntax highlighting: Template strings inside a TypeScript file currently show as simple string literals, yet ideally would be colored in a semantically meaninful way.\r\n - Additional file-types and structure: Angular templates may live in a separate file, containing the HTML-like template contents. For React, TypeScript added a new file extension (.tsx) and matching grammar/parser changes for this file type. Ideally this would be an extensibility point, not baked into TypeScript.\r\n - Syntactic and semantic diagnostics: Both the compiler and the language service should be able to surface domain specific errors in areas such as  syntax, type usage, deprecation notices, etc. Such errors should map to original source locations, not intermediate artifacts.\r\n - Rich IDE features: Statement and member completion, signature help, find all references, go to defintion, rename, etc. should work within the template contents as expected.\r\n - Custom commands: Some plugins may provide editors additional functionality not exposed by the existing language service API (e.g. an editor visualization for the component hierarchy). A plugin should be able to expose additional commands for such usage.\r\n \r\n## Challenges\r\n\r\nThis section captures non-trivial challenges to be addressed, either with the problem domain in general or the current TypeScript architecture.\r\n\r\n - Syntax highlighting: Several editors, (e.g. Sublime Text, VSCode, etc.), use a TextMate bundle for syntax highlighting. This is generally a static file describing the grammar for a file type, usually detected by file extension. Expanding the grammar via a plugin is a challenge. Even if statically augmenting the grammar, detecting when a string literal is an Angular template or not, or this .html file is an Angular template or regular .html file, is also challenging to do at parse time (and often depends on type information for inline template, or path resolution for external templates, to determine definitively).\r\n - Syntax highlighting: TextMate aside, other editors (e.g. Visual Studio) do syntax highlighting via other means (such as calling the TypeScript classifier), which would need to be augmented somehow also.\r\n -  Program structure: In order to provide some of the above functionality, it is desirable to generate an intermediate representation (e.g. containing a \"compiled template\") and ask TypeScript questions about this code, then map the results back to the original source. However, the representation of the program that the compiler or language service has is immutable. It is not possible to receive a request about a source location, generate an intermediate representation of it, update the program with the generated code mid-request, then ask TypeScript questions about it before responding.\r\n - Loading: TypeScript runs in environments besides Node.js (e.g. in-process in Visual Studio, or the tsc.exe command-line compiler), thus a plugin can not make assumptions such as being able to call `require` or take dependencies on other Node.js packages.\r\n - Performance: As the program is immutable, a new program is created on every edit. Most language service operations require that the program is bound and type-checked, which is often done on-demand when a question is asked. For acceptable performance, (faster than 50ms response time), processing should be kept to a minimum and done entirely in memory where possible (e.g. avoid serializing/reading generated artifacts on disk such as temporary code, source map files, etc.).\r\n\r\n### Angular specific challenges\r\n - Ambiguity: What if two different components have a `templateUrl` that resolves to the same file on disk? In which context should TypeScript evaluate that file?\r\n - Determination: If a user opens an HTML file, how can the editor determine if this is an Angular template rather than just a regular HTML file without loading the full TypeScript program and resolving all the `templateUrl` properties? \r\n - Path resolution: What if the path on disk doesn't match the path at runtime? Is some type of `baseUrl` or `config` object needed to map paths from the TypeScript source to the template files?\r\n - Dynamic content: TypeScript needs to be able to statically analyze code that may be dynamically generated at runtime. For example, how to handle an inline template that reads `<div>${getStart()}<foo [prop]='expr'/>${getEnd()}</div>`, or analyze the component with the directives given as `directives: getMyDirectives()`?\r\n - Name resolution: Within an expression in a template, scoping is quite different to normal. All instance members are available as top level names (i.e. no `this.` needed), and the usual global members aren't available (i.e. can't reference `Date.now`, `parseInt`, or similar). Thus resolving names and providing completion lists requires quite different logic to the usual TypeScript behavior.\r\n - Micro-syntaxes: Within Angular templates, expressions are *mostly* JavaScript expressions, but not quite. For example, certain operators have different meanings, arguments are passed differently when using pipes, etc. See https://angular.io/docs/ts/latest/guide/template-syntax.html for more info.\r\n \r\n## Current work\r\nThe below is currently experimental work to spike various approaches.\r\n\r\n - TextMate grammar to provide syntax highlighting for inline templates: https://github.com/billti/TypeScript-TmLanguage/tree/ngml\r\n   - Note: This current uses a heuristic of determining if a template string is a value for an object literal property named `template`, or is preceded with a `/** @html */` comment. See https://github.com/billti/TypeScript-TmLanguage/blob/ngml/TypeScript.YAML-tmLanguage#L507\r\n - A fork of TypeScript with a rudimentary plugin model (plugin source lives within the codebase currently) and some initial feature support: https://github.com/billti/TypeScript/tree/ngml\r\n   - TODO: Update with the latest TypeScript and Angular2 releases.\r\n - Usage in VSCode:\r\n   1. Replace the `typescript.tmLanguage` file under the install location at `Contents/Resources/app/extensions/typescript/syntaxes` with the version from the `TypeScript-TmLanguage` repo above (from the `ngml` branch).\r\n   2. Fork the `TypeScript` repo above, checkout the `ngml` branch, and build. \r\n   3. Open the VSCode global settings, and set the `typescript.tsdk` property to the build location in the prior step (e.g. `/src/typescript/built/local`).\r\n   4. To get completions within the template on characters such as `<`, `[`, etc. open `typescriptMain.ts` from the `Contents/Resources/app/extensions/typescript` folder under the VSCode install location, and change the line that calls `registerCompletionItemProvider` to read `vscode_1.languages.registerCompletionItemProvider(modeID, completionItemProvider, '.', '<', '(', '[', '\\'');`\r\n   5. To make changes edit the local TypeScript repo, rebuild, and relaunch VSCode.\r\n\r\n - Limitations:\r\n   - Currently there is no dynamic plugin model. The plugin is compiled into the TypeScript service. To minimize build changes, all plugin code is lumped into one file currently (`src/services/plugin-ngml.ts`), as are some basic unit tests.\r\n   - It currently uses its own rudimentary template parser. I haven't spent the time to figure out how to reuse the code from `angular2/src/compiler` (if possible)\r\n   - All attribute values should be in single quotes. Unquoted or double quoted doesn't parse properly in the textMate grammar yet.\r\n   - Interpolation inside attribute values is not wired up yet, i.e. `<foo name='Hi {{name}}'></foo>` won't work yet.\r\n   - Attribute bindings (i.e. dotting off of `attr`) don't work yet, i.e. `<td [attr.colspan]='expr'>`\r\n   - Only expressions where the first token is a member bind correctly, i.e. `mem1(mem2) + mem3` will only bind `mem1` to the class instance member correctly.\r\n   - Components within components do not work yet (in fact, none of the `directives` values are resolved currently).\r\n   - Special directives, such as `*ngFor='#item of items'`, aren't implemented yet.\r\n   - Angular specific syntax, such as pipes or the  Elvis operator don't work yet, i.e. `mem?.value | mypipe:\"arg1\"`\r\n   - Naming conversion still uses snake-case, and needs to be updated for the Beta release changes to attribute name mapping.\r\n   - Rename isn't working yet (but is simple since the Beta change to simplify name mapping and is nearly done)\r\n   - Still to figure out work for features such as outlets, etc.\r\n\r\n - Current features\r\n   - Completions and errors on HTML tags (using a basic list of HTML elements)\r\n   - Completions on member expressions\r\n   - Syntactic and type errors on member expressions\r\n   - Signature help and tool-tips on expressions\r\n   - Data and event binding using the `[prop]` or `(event)` syntax\r\n   - Introduction of scoped template locals using the `#name` attribute syntax\r\n   - Goto definition on identifers within template expressions\r\n   - The below shows an example of the plugin in action\r\n\r\n![ngmldemo1](https://cloud.githubusercontent.com/assets/993909/12367551/c35da1da-bb97-11e5-92d3-97af06273ea4.gif)\r\n\r\n - TODO\r\n   - Detail the architecture and which of the above challenges informed which choices\r\n   - Figure out how to plug in to the compiler as well as the language service for the errors as build time as well as design time\r\n\r\n## Existing related issues:\r\n - [#5151] typescript checking frontend template files\r\n - [#5730] [tsserver] custom command (ex: to collect Angular2 @Component/selector)\r\n - [#5740] Allow evaluation of a detached buffer in a specified context (angular2 templates)\r\n - [#6477] [tsx] Angular 2 inline templates\r\n"},"comment":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/comments/224428750","html_url":"https://github.com/Microsoft/TypeScript/issues/6508#issuecomment-224428750","issue_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/6508","id":224428750,"user":{"login":"TheLarkInn","id":3408176,"avatar_url":"https://avatars.githubusercontent.com/u/3408176?v=3","gravatar_id":"","url":"https://api.github.com/users/TheLarkInn","html_url":"https://github.com/TheLarkInn","followers_url":"https://api.github.com/users/TheLarkInn/followers","following_url":"https://api.github.com/users/TheLarkInn/following{/other_user}","gists_url":"https://api.github.com/users/TheLarkInn/gists{/gist_id}","starred_url":"https://api.github.com/users/TheLarkInn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TheLarkInn/subscriptions","organizations_url":"https://api.github.com/users/TheLarkInn/orgs","repos_url":"https://api.github.com/users/TheLarkInn/repos","events_url":"https://api.github.com/users/TheLarkInn/events{/privacy}","received_events_url":"https://api.github.com/users/TheLarkInn/received_events","type":"User","site_admin":false},"created_at":"2016-06-07T22:03:28Z","updated_at":"2016-06-07T22:03:28Z","body":"@mhegazy and friends:\r\n\r\nCouple issues that I have come across that may be relevant to this issue:\r\n\r\nThe premier webpack Typescript loaders (ts-loader & awesome-typescript-loader) use LanguageServiceHost Implementation due to the incremental building behavior of webpack. However there are numerous (and continues to grow) custom ts API implementations to perform framework or optimization specific transpilation. (See https://github.com/angular/tsickle). Although CompilerHost and LanguageServiceHost share some functionality, there is no easy way to implement an existing CompilerHost into a LanguageService. \r\n\r\nAdditionally, some sort of Typescript plugin system which manages and aids in 'decorating' or providing easier lifecycle hooks to the transpilation process could help make these custom ts implementations reusable and modular."}}
{"actor":{"display_login":"TheLarkInn"}}