├── LICENSE.md ├── globals.js ├── dist ├── globals.js ├── main │ ├── bin │ │ ├── atbuild │ │ └── atbuild.js │ ├── atom │ │ ├── signatureProvider.js │ │ ├── commands │ │ │ ├── moveFilesHandling.js │ │ │ ├── reactCommand.js │ │ │ ├── reactCommands.js │ │ │ ├── json2dtsCommands.js │ │ │ └── outputFileCommands.js │ │ ├── components │ │ │ ├── componentRegistry.js │ │ │ └── ts-view.js │ │ ├── debugAtomTs.js │ │ ├── fileStatusCache.js │ │ ├── views │ │ │ ├── plainMessageView.js │ │ │ ├── awesomePanelView.js │ │ │ ├── fileSemanticView.js │ │ │ ├── view.js │ │ │ ├── tooltipView.js │ │ │ ├── fileSymbolsView.js │ │ │ ├── rView.js │ │ │ ├── simpleSelectionView.js │ │ │ ├── lineMessageView.js │ │ │ ├── projectSymbolsView.js │ │ │ ├── contextView.js │ │ │ ├── simpleOverlaySelectionView.js │ │ │ └── documentationView.js │ │ ├── onSaveHandler.js │ │ ├── editorSetup.js │ │ ├── buildView.js │ │ ├── gotoHistory.js │ │ └── atomConfig.js │ ├── react │ │ └── htmltotsx.js │ ├── lang │ │ ├── transformers │ │ │ ├── implementations │ │ │ │ └── nullTransformer.js │ │ │ ├── transformer.js │ │ │ └── transformerRegistry.js │ │ ├── fixmyts │ │ │ ├── quickFix.js │ │ │ ├── quickFixes │ │ │ │ ├── equalsToEquals.js │ │ │ │ ├── quoteToTemplate.js │ │ │ │ ├── quotesToQuotes.js │ │ │ │ ├── singleLineCommentToJsdoc.js │ │ │ │ ├── typeAssertPropertyAccessToAny.js │ │ │ │ ├── typeAssertPropertyAccessToType.js │ │ │ │ ├── addImportStatement.js │ │ │ │ └── implementInterface.js │ │ │ └── quickFixRegistry.js │ │ ├── modules │ │ │ ├── formatting.js │ │ │ ├── programDependencies.js │ │ │ ├── getPathCompletions.js │ │ │ ├── moveFiles.js │ │ │ └── astToText.js │ │ └── core │ │ │ └── project.js │ ├── json2dts │ │ └── json2dts.js │ ├── utils │ │ └── fsUtil.js │ └── tsconfig │ │ └── simpleValidator.js ├── worker │ ├── debug.js │ └── child.js ├── typescript │ └── makeTypeScriptGlobal.js └── linter.js ├── .gitattributes ├── lib ├── main │ ├── atom │ │ ├── components │ │ │ ├── componentRegistry.ts │ │ │ └── ts-view.ts │ │ ├── views │ │ │ ├── semanticViewGlobals.d.ts │ │ │ ├── plainMessageView.ts │ │ │ ├── view.ts │ │ │ ├── awesomePanelView.ts │ │ │ ├── tooltipView.ts │ │ │ ├── fileSymbolsView.ts │ │ │ ├── projectSymbolsView.ts │ │ │ ├── rView.tsx │ │ │ ├── contextView.ts │ │ │ ├── documentationView.ts │ │ │ ├── simpleSelectionView.ts │ │ │ ├── lineMessageView.ts │ │ │ └── simpleOverlaySelectionView.ts │ │ ├── commands │ │ │ ├── moveFilesHandling.ts │ │ │ ├── reactCommands.ts │ │ │ ├── json2dtsCommands.ts │ │ │ └── outputFileCommands.ts │ │ ├── debugAtomTs.ts │ │ ├── signatureProvider.ts │ │ ├── fileStatusCache.ts │ │ ├── atomConfig.ts │ │ ├── onSaveHandler.ts │ │ ├── editorSetup.ts │ │ └── buildView.ts │ ├── lang │ │ ├── transformers │ │ │ └── implementations │ │ │ │ └── nullTransformer.ts │ │ ├── fixmyts │ │ │ ├── quickFixes │ │ │ │ ├── equalsToEquals.ts │ │ │ │ ├── quoteToTemplate.ts │ │ │ │ ├── quotesToQuotes.ts │ │ │ │ ├── singleLineCommentToJsdoc.ts │ │ │ │ ├── typeAssertPropertyAccessToAny.ts │ │ │ │ └── typeAssertPropertyAccessToType.ts │ │ │ ├── quickFixRegistry.ts │ │ │ └── quickFix.ts │ │ ├── modules │ │ │ ├── formatting.ts │ │ │ ├── programDependencies.ts │ │ │ ├── moveFiles.ts │ │ │ └── getPathCompletions.ts │ │ └── core │ │ │ └── project.ts │ ├── react │ │ └── htmltotsx.ts │ ├── json2dts │ │ └── json2dts.ts │ ├── utils │ │ └── fsUtil.ts │ ├── bin │ │ └── atbuild.ts │ └── tsconfig │ │ └── simpleValidator.ts ├── worker │ ├── debug.ts │ └── child.ts ├── typings │ ├── mustache.d.ts │ ├── mixto │ │ └── mixto.d.ts │ ├── mkdirp │ │ └── mkdirp.d.ts │ ├── htmltojsx │ │ └── htmltojsx.d.ts │ ├── tsd.d.ts │ ├── status-bar │ │ └── status-bar.d.ts │ ├── emissary │ │ └── emissary.d.ts │ ├── minimatch │ │ └── minimatch.d.ts │ └── pathwatcher │ │ └── pathwatcher.d.ts ├── typescript │ ├── readme.md │ └── makeTypeScriptGlobal.ts ├── linter.ts └── tsd.json ├── styles ├── atomts-r-view.less ├── atomts-overlay.less ├── atomts-grammar-syntax.less ├── autocomplete-fix.less ├── atomts-main-panel-view.less ├── atom-typescript-tooltip.less ├── ast-view.less ├── atomts-rename-view.less ├── gutter.atom-text-editor.less ├── documentationview.less └── semantic-view.less ├── docs ├── screens │ ├── proj.png │ ├── hover.png │ ├── build errors.png │ ├── emit error.png │ ├── autocomplete1.png │ ├── autocomplete2.png │ ├── build success.png │ ├── compile error.png │ ├── compile success.png │ └── renameRefactoring.png ├── spacepen.md ├── dependency-view.md ├── CHANGELOG.md ├── grammar.md ├── packages.md └── quickfix.md ├── images ├── light-bulb.png └── symbol-icons.woff ├── keymaps ├── autocomplete-keymaps.cson └── atom-typescript.cson ├── .gitignore ├── snippets └── tsconfig-snippets.cson ├── views ├── views.d.ts └── renameView.html.coffee ├── settings └── language-typescript.cson ├── tsd.json ├── menus └── atomts-menus.cson ├── Gruntfile.js ├── VSProj.sln └── package.json /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT -------------------------------------------------------------------------------- /globals.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dist/globals.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # core.autocrlf 2 | * text=auto 3 | -------------------------------------------------------------------------------- /lib/main/atom/components/componentRegistry.ts: -------------------------------------------------------------------------------- 1 | export * from "./ts-view"; -------------------------------------------------------------------------------- /dist/main/bin/atbuild: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | require('./atbuild.js'); 3 | -------------------------------------------------------------------------------- /styles/atomts-r-view.less: -------------------------------------------------------------------------------- 1 | .atomts-r-view{ 2 | background: white; 3 | } 4 | -------------------------------------------------------------------------------- /dist/worker/debug.js: -------------------------------------------------------------------------------- 1 | exports.debugAll = false; 2 | exports.debugSync = false || exports.debugAll; 3 | -------------------------------------------------------------------------------- /docs/screens/proj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/docs/screens/proj.png -------------------------------------------------------------------------------- /images/light-bulb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/images/light-bulb.png -------------------------------------------------------------------------------- /docs/screens/hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/docs/screens/hover.png -------------------------------------------------------------------------------- /images/symbol-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/images/symbol-icons.woff -------------------------------------------------------------------------------- /docs/screens/build errors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/docs/screens/build errors.png -------------------------------------------------------------------------------- /docs/screens/emit error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/docs/screens/emit error.png -------------------------------------------------------------------------------- /docs/screens/autocomplete1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/docs/screens/autocomplete1.png -------------------------------------------------------------------------------- /docs/screens/autocomplete2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/docs/screens/autocomplete2.png -------------------------------------------------------------------------------- /docs/screens/build success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/docs/screens/build success.png -------------------------------------------------------------------------------- /docs/screens/compile error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/docs/screens/compile error.png -------------------------------------------------------------------------------- /dist/main/atom/signatureProvider.js: -------------------------------------------------------------------------------- 1 | function requestHandler(config) { 2 | } 3 | exports.requestHandler = requestHandler; 4 | -------------------------------------------------------------------------------- /docs/screens/compile success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/docs/screens/compile success.png -------------------------------------------------------------------------------- /docs/screens/renameRefactoring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcoury/atom-typescript/master/docs/screens/renameRefactoring.png -------------------------------------------------------------------------------- /dist/main/atom/commands/moveFilesHandling.js: -------------------------------------------------------------------------------- 1 | function registerRenameHandling() { 2 | } 3 | exports.registerRenameHandling = registerRenameHandling; 4 | -------------------------------------------------------------------------------- /lib/main/atom/views/semanticViewGlobals.d.ts: -------------------------------------------------------------------------------- 1 | declare module AtomCore { 2 | export interface IEditor { 3 | showSemanticView: boolean; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /keymaps/autocomplete-keymaps.cson: -------------------------------------------------------------------------------- 1 | 'atom-text-editor[data-grammar^="source ts"]': 2 | 'ctrl-space': 'typescript:autocomplete' 3 | 'cmd-space': 'typescript:autocomplete' 4 | -------------------------------------------------------------------------------- /dist/main/atom/components/componentRegistry.js: -------------------------------------------------------------------------------- 1 | function __export(m) { 2 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; 3 | } 4 | __export(require("./ts-view")); 5 | -------------------------------------------------------------------------------- /styles/atomts-overlay.less: -------------------------------------------------------------------------------- 1 | @import "ui-variables"; 2 | .atomts-overlay { 3 | background: rgba(0,0,0,0.9); 4 | border: 9px solid rgba(0,0,0,0.9); 5 | li { 6 | padding: 5px; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /dist/main/atom/debugAtomTs.js: -------------------------------------------------------------------------------- 1 | var atomConfig = require('./atomConfig'); 2 | function runDebugCode(details) { 3 | if (!atomConfig.debugAtomTs) 4 | return; 5 | } 6 | exports.runDebugCode = runDebugCode; 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .tscache 2 | /.ntvs_analysis.dat 3 | /.ntvs_analysis.dat.tmp 4 | obj/Debug/VSProj.njsproj.FileListAbsolute.txt 5 | ./node_modules 6 | .baseDir.ts 7 | node_modules/immutable/ 8 | node_modules/react/ 9 | node_modules -------------------------------------------------------------------------------- /lib/worker/debug.ts: -------------------------------------------------------------------------------- 1 | /** Set this to true if you want to debug all things */ 2 | export var debugAll = false; 3 | 4 | /** Set this to true to run the child code in the UI thread and just debug using the dev tools */ 5 | export var debugSync = false || debugAll; 6 | -------------------------------------------------------------------------------- /snippets/tsconfig-snippets.cson: -------------------------------------------------------------------------------- 1 | '.source.json': 2 | 'filesGlob': 3 | 'prefix': 'fg' 4 | 'body': """ 5 | "filesGlob": [ 6 | "**/*.ts", 7 | "**/*.tsx", 8 | "!node_modules/**" 9 | ], 10 | """ 11 | -------------------------------------------------------------------------------- /styles/atomts-grammar-syntax.less: -------------------------------------------------------------------------------- 1 | atom-text-editor::shadow { 2 | .source.ts, 3 | .source.tsx { 4 | .require.path, .reference.path, .es6import.path, .amd.path { 5 | text-decoration: underline; 6 | } 7 | .keyword.debugger { 8 | background-color: lime; 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /dist/main/react/htmltotsx.js: -------------------------------------------------------------------------------- 1 | var HTMLtoJSX = require("htmltojsx"); 2 | function convert(content, indentSize) { 3 | var indent = Array(indentSize + 1).join(' '); 4 | var converter = new HTMLtoJSX({ indent: indent, createClass: false }); 5 | var output = converter.convert(content); 6 | return output; 7 | } 8 | exports.convert = convert; 9 | -------------------------------------------------------------------------------- /views/views.d.ts: -------------------------------------------------------------------------------- 1 | 2 | // I find it easiest to create Views in CoffeeScript 3 | // This is because of the way that Atom works 4 | // This means that views a losely coupled with the API which we declare here 5 | // But atleaset the views are readable 6 | 7 | declare class AtomView { 8 | // Methods from base View 9 | remove(); 10 | } 11 | -------------------------------------------------------------------------------- /styles/autocomplete-fix.less: -------------------------------------------------------------------------------- 1 | // Fixing up autocomplete-plus for us 2 | atom-overlay{ 3 | // see https://github.com/atom-community/autocomplete-plus/issues/255 4 | // https://github.com/atom-community/autocomplete-plus/issues/255#issuecomment-74010347 5 | autocomplete-suggestion-list.select-list.popover-list ol.list-group li { 6 | color: inherit; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lib/typings/mustache.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Mustache 0.7 2 | // Project: https://github.com/janl/mustache.js 3 | // Definitions by: Boris Yankov 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | 7 | /*tslint:disable unused*/ 8 | 9 | declare var Mustache: { 10 | render(template: string, data: any): string; 11 | }; 12 | -------------------------------------------------------------------------------- /settings/language-typescript.cson: -------------------------------------------------------------------------------- 1 | '.source.ts': 2 | 'editor': 3 | 'commentStart': '// ' 4 | 'foldEndPattern': '^\\s*\\}|^\\s*\\]|^\\s*\\)' 5 | 'increaseIndentPattern': '(?x) 6 | \\{ [^}"\']* $ 7 | | \\[ [^\\]"\']* $ 8 | | \\( [^)"\']* $ 9 | ' 10 | 'decreaseIndentPattern': '(?x) 11 | ^ \\s* (\\s* /[*] .* [*]/ \\s*)* [}\\])] 12 | ' 13 | -------------------------------------------------------------------------------- /tsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v4", 3 | "repo": "borisyankov/DefinitelyTyped", 4 | "ref": "master", 5 | "path": "typings", 6 | "bundle": "typings/tsd.d.ts", 7 | "installed": { 8 | "d3/d3.d.ts": { 9 | "commit": "2520bce9a8a71b66e67487cbd5b33fec880b0c55" 10 | }, 11 | "source-map/source-map.d.ts": { 12 | "commit": "70737c2a2496f7a13c4da63eb00081cad94d19f1" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /dist/main/atom/fileStatusCache.js: -------------------------------------------------------------------------------- 1 | var fsUtil_1 = require('../utils/fsUtil'); 2 | ; 3 | var fileStatuses = {}; 4 | function getFileStatus(filePath) { 5 | filePath = fsUtil_1.consistentPath(filePath); 6 | if (!fileStatuses[filePath]) { 7 | fileStatuses[filePath] = { modified: false, emitDiffers: false }; 8 | } 9 | return fileStatuses[filePath]; 10 | } 11 | exports.getFileStatus = getFileStatus; 12 | -------------------------------------------------------------------------------- /menus/atomts-menus.cson: -------------------------------------------------------------------------------- 1 | # See https://atom.io/docs/latest/creating-a-package#menus for more details 2 | 'menu': [ 3 | { 4 | 'label': 'Packages' 5 | 'submenu': [ 6 | 'label': 'TypeScript' 7 | 'submenu': [ 8 | { 'label': 'Build', 'command': 'typescript:build' } 9 | { 'label': 'Go To Declaration', 'command': 'typescript:go-to-declaration' } 10 | ] 11 | ] 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /lib/main/lang/transformers/implementations/nullTransformer.ts: -------------------------------------------------------------------------------- 1 | import {Transformer} from "../transformer"; 2 | import {add} from "../transformerRegistry"; 3 | 4 | /** Does no transform whatsoever. This is to test the infrastructure */ 5 | export class NullTransformer implements Transformer { 6 | name = "null"; 7 | 8 | transform(code: string) { 9 | return { code }; 10 | } 11 | } 12 | add(new NullTransformer()); -------------------------------------------------------------------------------- /styles/atomts-main-panel-view.less: -------------------------------------------------------------------------------- 1 | .atomts-panel-body { 2 | height: 170px; 3 | scroll-y: auto; 4 | } 5 | 6 | .atomts-panel-body, 7 | .atomts-panel-header { 8 | padding: 6px; 9 | } 10 | 11 | .atomts-main-panel-view{ 12 | .build-progress.warn::-webkit-progress-value{ 13 | background-color: rgb(255, 155, 0) !important; 14 | } 15 | 16 | .section-pending { 17 | opacity: .5; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /styles/atom-typescript-tooltip.less: -------------------------------------------------------------------------------- 1 | // Most of the styles for this get inherited from the .tooltip class that we apply to the same element in the DOM 2 | .atom-typescript-tooltip { 3 | font-family: Consolas, monospace; 4 | white-space: pre !important; 5 | 6 | border-radius: 5px; 7 | 8 | // This class exists by default and this is what we are using 9 | .tooltip-inner{ 10 | text-align: left; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/typings/mixto/mixto.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for mixto 2 | // Project: https://github.com/atom/mixto 3 | // Definitions by: vvakame 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | declare module Mixto { 7 | interface IMixinStatic { 8 | includeInto(constructor:any):void; 9 | extend(object:any):void; 10 | } 11 | } 12 | 13 | declare module "mixto" { 14 | var _tmp:Mixto.IMixinStatic; 15 | export = _tmp; 16 | } 17 | -------------------------------------------------------------------------------- /lib/main/atom/commands/moveFilesHandling.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * For rename (move) files / folders 3 | * Waiting on https://github.com/atom/tree-view/issues/433 4 | */ 5 | 6 | export function registerRenameHandling() { 7 | /** https://atom.io/docs/api/v0.190.0/Project#instance-onDidChangePaths */ 8 | // var renameListener = atom.project.onDidChangePaths(function(projectPaths) { 9 | // console.log(arguments); 10 | // console.log(projectPaths); 11 | // }); 12 | } 13 | -------------------------------------------------------------------------------- /lib/main/react/htmltotsx.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Take a look at : 3 | * https://github.com/reactjs/react-magic 4 | * https://www.npmjs.com/package/htmltojsx 5 | */ 6 | 7 | import HTMLtoJSX = require("htmltojsx"); 8 | export function convert(content: string, indentSize: number) { 9 | var indent = Array(indentSize + 1).join(' '); 10 | var converter = new HTMLtoJSX({ indent: indent, createClass: false }); 11 | var output = converter.convert(content); 12 | return output; 13 | } 14 | -------------------------------------------------------------------------------- /dist/main/lang/transformers/implementations/nullTransformer.js: -------------------------------------------------------------------------------- 1 | var transformerRegistry_1 = require("../transformerRegistry"); 2 | var NullTransformer = (function () { 3 | function NullTransformer() { 4 | this.name = "null"; 5 | } 6 | NullTransformer.prototype.transform = function (code) { 7 | return { code: code }; 8 | }; 9 | return NullTransformer; 10 | })(); 11 | exports.NullTransformer = NullTransformer; 12 | transformerRegistry_1.add(new NullTransformer()); 13 | -------------------------------------------------------------------------------- /lib/typescript/readme.md: -------------------------------------------------------------------------------- 1 | # Magic 2 | Basically we run `makeTypeScriptGlobal.ts` (both in parent and child) to export `module ts` to the variable `global.ts` so we can just use `ts.` without any imports. 3 | This isn't ideal but it makes it easier to not have a `require('typescript')` all over the code base. Also it makes it easier to swap out `typescript` with something else (we sometimes move to nightly typescript `ntypescript`). Also you can point it to a custom typescript file if you want (we have a package option exposed to atom for this). -------------------------------------------------------------------------------- /styles/ast-view.less: -------------------------------------------------------------------------------- 1 | .ast-view{ 2 | overflow-y: auto; 3 | 4 | // Style the svg 5 | .node rect { 6 | cursor: pointer; 7 | fill: #fff; 8 | fill-opacity: .9; 9 | stroke: black; 10 | stroke-width: 1.5px; 11 | } 12 | 13 | .node text { 14 | font: 11px sans-serif; 15 | font-weight: bold; 16 | pointer-events: none; 17 | fill: white; 18 | } 19 | 20 | path.link { 21 | fill: none; 22 | stroke: #9ecae1; 23 | stroke-width: 1.5px; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/main/atom/debugAtomTs.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | ///ts:import=atomConfig 4 | import atomConfig = require('./atomConfig'); ///ts:import:generated 5 | ///ts:import=typescriptGrammar 6 | import typescriptGrammar = require('./typescriptGrammar'); ///ts:import:generated 7 | 8 | import TokenClass = ts.TokenClass; 9 | 10 | interface AtomTokenizeLineResult { 11 | tokens: any[]; 12 | ruleStack: any[]; 13 | } 14 | 15 | export function runDebugCode(details: { filePath: string; editor: AtomCore.IEditor }) { 16 | if (!atomConfig.debugAtomTs) return; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /lib/typings/mkdirp/mkdirp.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for mkdirp 0.3.0 2 | // Project: http://github.com/substack/node-mkdirp 3 | // Definitions by: Bart van der Schoor 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | declare module 'mkdirp' { 7 | 8 | function mkdirp(dir: string, cb: (err: any, made: string) => void): void; 9 | function mkdirp(dir: string, flags: any, cb: (err: any, made: string) => void): void; 10 | 11 | module mkdirp { 12 | function sync(dir: string, flags?: any): string; 13 | } 14 | export = mkdirp; 15 | } 16 | -------------------------------------------------------------------------------- /dist/worker/child.js: -------------------------------------------------------------------------------- 1 | var typescriptServices = ''; 2 | if (process.argv.length > 2) { 3 | typescriptServices = process.argv[2]; 4 | } 5 | var makeTypeScriptGlobal_1 = require("../typescript/makeTypeScriptGlobal"); 6 | makeTypeScriptGlobal_1.makeTsGlobal(typescriptServices); 7 | var workerLib = require('./lib/workerLib'); 8 | var child = new workerLib.Child(); 9 | var projectCache = require("../main/lang/projectCache"); 10 | projectCache.fixChild(child); 11 | var projectService = require('../main/lang/projectService'); 12 | child.registerAllFunctionsExportedFromAsResponders(projectService); 13 | -------------------------------------------------------------------------------- /lib/typings/htmltojsx/htmltojsx.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for htmltojsx 2 | // Project: https://www.npmjs.com/package/htmltojsx 3 | // Definitions by: Basarat Ali Syed 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | declare module 'htmltojsx' { 7 | class HTMLtoJSX { 8 | constructor(options?: { 9 | createClass?: boolean; 10 | outputClassName?: string; 11 | /** as a string e.g. ' ' or '\t' */ 12 | indent?: string; 13 | }); 14 | convert(html: string): string; 15 | } 16 | export = HTMLtoJSX; 17 | } 18 | -------------------------------------------------------------------------------- /dist/main/atom/commands/reactCommand.js: -------------------------------------------------------------------------------- 1 | var atomUtils = require("../atomUtils"); 2 | function register() { 3 | atom.commands.add('atom-workspace', 'typescript:HTML-to-TSX', function (e) { 4 | if (!atomUtils.commandForTypeScript(e)) 5 | return; 6 | var editor = atom.workspace.getActiveTextEditor(); 7 | var filePath = editor.getPath(); 8 | var selection = editor.getSelectedBufferRange(); 9 | var text = editor.getSelectedText(); 10 | var range = editor.getSelectedBufferRange(); 11 | editor.setTextInBufferRange(range, "foo"); 12 | }); 13 | } 14 | exports.register = register; 15 | -------------------------------------------------------------------------------- /dist/main/lang/fixmyts/quickFix.js: -------------------------------------------------------------------------------- 1 | function getRefactoringsByFilePath(refactorings) { 2 | var loc = {}; 3 | for (var _i = 0; _i < refactorings.length; _i++) { 4 | var refac = refactorings[_i]; 5 | if (!loc[refac.filePath]) 6 | loc[refac.filePath] = []; 7 | loc[refac.filePath].push(refac); 8 | } 9 | for (var filePath in loc) { 10 | var refactorings_1 = loc[filePath]; 11 | refactorings_1.sort(function (a, b) { 12 | return (b.span.start - a.span.start); 13 | }); 14 | } 15 | return loc; 16 | } 17 | exports.getRefactoringsByFilePath = getRefactoringsByFilePath; 18 | -------------------------------------------------------------------------------- /lib/main/atom/signatureProvider.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | ///ts:import=parent 4 | import parent = require('../../worker/parent'); ///ts:import:generated 5 | 6 | 7 | export function requestHandler(config: { 8 | editor: AtomCore.IEditor; 9 | filePath: string; 10 | position: number; 11 | }) { 12 | 13 | /* 14 | try { 15 | console.log(require('views/tooltip')); 16 | } catch (ex) { 17 | console.error(ex); 18 | }*/ 19 | 20 | /* 21 | var signatures = config.program.languageService.getSignatureHelpItems(config.filePath, config.position); 22 | if (!signatures) return; 23 | */ 24 | 25 | // console.log(signatures); 26 | } 27 | -------------------------------------------------------------------------------- /dist/main/json2dts/json2dts.js: -------------------------------------------------------------------------------- 1 | var JSON2DTS = require("json2dts"); 2 | var Json2dts = JSON2DTS.Json2dts; 3 | var toValidJSON = JSON2DTS.toValidJSON; 4 | function convert(content) { 5 | try { 6 | var converter = new Json2dts(); 7 | var text2Obj = JSON.parse(toValidJSON(content)); 8 | if (typeof text2Obj != "string") { 9 | converter.parse(text2Obj, 'RootJson'); 10 | content = converter.getCode(); 11 | } 12 | else { 13 | atom.notifications.addError('Json2dts Invalid JSON'); 14 | } 15 | } 16 | catch (e) { 17 | atom.notifications.addError("Json2dts Invalid JSON error: " + e); 18 | } 19 | return content; 20 | } 21 | exports.convert = convert; 22 | -------------------------------------------------------------------------------- /lib/main/json2dts/json2dts.ts: -------------------------------------------------------------------------------- 1 | var JSON2DTS = require("json2dts"); 2 | var Json2dts = (JSON2DTS).Json2dts; 3 | var toValidJSON = (JSON2DTS).toValidJSON; 4 | 5 | export function convert(content: string) { 6 | try { 7 | var converter = new Json2dts(); 8 | var text2Obj = JSON.parse(toValidJSON(content)); 9 | if (typeof text2Obj != "string") { 10 | converter.parse(text2Obj, 'RootJson'); 11 | content = converter.getCode(); 12 | } 13 | else { 14 | atom.notifications.addError('Json2dts Invalid JSON'); 15 | } 16 | 17 | } catch (e) { 18 | atom.notifications.addError(`Json2dts Invalid JSON error: ${e}`); 19 | } 20 | return content; 21 | } 22 | -------------------------------------------------------------------------------- /dist/typescript/makeTypeScriptGlobal.js: -------------------------------------------------------------------------------- 1 | var vm = require('vm'); 2 | var fs = require('fs'); 3 | global.stack = function () { 4 | console.error((new Error()).stack); 5 | }; 6 | function makeTsGlobal(typescriptServices) { 7 | var sandbox = { 8 | ts: {}, 9 | console: console, 10 | stack: global.stack, 11 | require: require, 12 | module: module, 13 | process: process 14 | }; 15 | vm.createContext(sandbox); 16 | if (typescriptServices) { 17 | vm.runInContext(fs.readFileSync(typescriptServices).toString(), sandbox); 18 | } 19 | else { 20 | sandbox.ts = require('ntypescript'); 21 | } 22 | global.ts = sandbox.ts; 23 | } 24 | exports.makeTsGlobal = makeTsGlobal; 25 | -------------------------------------------------------------------------------- /styles/atomts-rename-view.less: -------------------------------------------------------------------------------- 1 | 2 | .atomts-rename-view{ 3 | .options-label { 4 | color: @text-color-subtle; 5 | position: relative; 6 | 7 | .options { 8 | color: @text-color; 9 | } 10 | } 11 | 12 | .subtle-info-message { 13 | padding-left: 5px; 14 | color: @text-color-subtle; 15 | } 16 | 17 | .find-container, 18 | .replace-container, 19 | .paths-container { 20 | display: -webkit-flex; 21 | -webkit-flex-direction: row; 22 | 23 | .btn-group { 24 | margin-left: @component-padding; 25 | } 26 | 27 | .editor-container { 28 | position: relative; 29 | -webkit-flex: 1; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /dist/main/atom/commands/reactCommands.js: -------------------------------------------------------------------------------- 1 | var atomUtils = require("../atomUtils"); 2 | var htmltotsx_1 = require("../../react/htmltotsx"); 3 | function registerReactCommands() { 4 | atom.commands.add('atom-workspace', 'typescript:HTML-to-TSX', function (e) { 5 | if (!atomUtils.commandForTypeScript(e)) 6 | return; 7 | var editor = atom.workspace.getActiveTextEditor(); 8 | var filePath = editor.getPath(); 9 | var selection = editor.getSelectedBufferRange(); 10 | var text = editor.getSelectedText(); 11 | var range = editor.getSelectedBufferRange(); 12 | editor.setTextInBufferRange(range, htmltotsx_1.convert(text, 4)); 13 | }); 14 | } 15 | exports.registerReactCommands = registerReactCommands; 16 | -------------------------------------------------------------------------------- /dist/main/atom/commands/json2dtsCommands.js: -------------------------------------------------------------------------------- 1 | var atomUtils = require("../atomUtils"); 2 | var json2dts_1 = require("../../json2dts/json2dts"); 3 | function registerJson2dtsCommands() { 4 | atom.commands.add('atom-workspace', 'typescript:JSON-to-Definition', function (e) { 5 | if (!atomUtils.commandForTypeScript(e)) 6 | return; 7 | var editor = atom.workspace.getActiveTextEditor(); 8 | var filePath = editor.getPath(); 9 | var selection = editor.getSelectedBufferRange(); 10 | var text = editor.getSelectedText(); 11 | var range = editor.getSelectedBufferRange(); 12 | editor.setTextInBufferRange(range, json2dts_1.convert(text)); 13 | }); 14 | } 15 | exports.registerJson2dtsCommands = registerJson2dtsCommands; 16 | -------------------------------------------------------------------------------- /lib/main/atom/views/plainMessageView.ts: -------------------------------------------------------------------------------- 1 | import view = require('./view'); 2 | var $ = view.$; 3 | import path = require('path'); 4 | 5 | export interface ViewOptions { 6 | /** your message to the people */ 7 | message: string; 8 | className: string; 9 | } 10 | 11 | export class PlainMessageView extends view.View { 12 | 13 | static content() { 14 | this.div({ 15 | class: 'plain-message' 16 | }); 17 | } 18 | 19 | init() { 20 | this.$.html(this.options.message); 21 | this.$.addClass(this.options.className); 22 | } 23 | 24 | getSummary() { 25 | return { 26 | summary: this.options.message, 27 | rawSummary: true, 28 | className: this.options.className 29 | }; 30 | } 31 | } -------------------------------------------------------------------------------- /lib/main/atom/commands/reactCommands.ts: -------------------------------------------------------------------------------- 1 | import * as atomUtils from "../atomUtils"; 2 | import * as parent from "../../../worker/parent"; 3 | import * as path from "path"; 4 | import {convert} from "../../react/htmltotsx"; 5 | 6 | /** 7 | * register commands 8 | */ 9 | export function registerReactCommands() { 10 | atom.commands.add('atom-workspace', 'typescript:HTML-to-TSX', (e) => { 11 | if (!atomUtils.commandForTypeScript(e)) return; 12 | 13 | var editor = atom.workspace.getActiveTextEditor(); 14 | var filePath = editor.getPath(); 15 | var selection = editor.getSelectedBufferRange(); 16 | 17 | var text = editor.getSelectedText(); 18 | var range = editor.getSelectedBufferRange(); 19 | editor.setTextInBufferRange(range, convert(text, 4)); 20 | }); 21 | } -------------------------------------------------------------------------------- /lib/main/atom/commands/json2dtsCommands.ts: -------------------------------------------------------------------------------- 1 | import * as atomUtils from "../atomUtils"; 2 | import * as parent from "../../../worker/parent"; 3 | import * as path from "path"; 4 | import {convert} from "../../json2dts/json2dts"; 5 | 6 | /** 7 | * register commands 8 | */ 9 | export function registerJson2dtsCommands() { 10 | atom.commands.add('atom-workspace', 'typescript:JSON-to-Definition', (e) => { 11 | if (!atomUtils.commandForTypeScript(e)) return; 12 | var editor = atom.workspace.getActiveTextEditor(); 13 | var filePath = editor.getPath(); 14 | var selection = editor.getSelectedBufferRange(); 15 | var text = editor.getSelectedText(); 16 | var range = editor.getSelectedBufferRange(); 17 | editor.setTextInBufferRange(range, convert(text)); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /styles/gutter.atom-text-editor.less: -------------------------------------------------------------------------------- 1 | // Based on lessons from : 2 | // https://github.com/AtomLinter/Linter/blob/master/styles/gutter.atom-text-editor.less 3 | // And the git package 4 | @import 'ui-variables'; 5 | @import 'octicon-utf-codes'; 6 | .gutter .line-number { 7 | background-size: 0px; 8 | transition: background-size .5s; 9 | &.quickfix 10 | { 11 | background-image: url(atom://atom-typescript/images/light-bulb.png); 12 | background-size: @component-line-height / 1.5; 13 | background-repeat: no-repeat; 14 | background-position: right center; 15 | } 16 | //// If the bright light ends up annoying people; 17 | // .icon-right { 18 | // visibility: visible; 19 | // &:before { 20 | // content: @tools !important; 21 | // } 22 | // } 23 | } 24 | -------------------------------------------------------------------------------- /docs/spacepen.md: -------------------------------------------------------------------------------- 1 | ## Docs 2 | Official docs : https://github.com/atom/space-pen / http://atom.github.io/space-pen/ 3 | 4 | ## Gotchas 5 | 6 | * The `outlet` option does not work on root. `this` is the root jq element 7 | * `initialize` is called after the view is attached to the DOM. The body of the `constructor` executes *after* `initialize` gets called (due to `super()`) so you cannot do `public something` as an argument to constructor. Our workaround is to have an `init` function called from the base view *after* the call to space-pen's `super`. So `init` is where we have the dom available in the clients. 8 | * Tip: You generally want views to be singletons and *not* take options. So don't have an `init` function. 9 | * You need to add the class `native-key-bindings` to your *custom* views for input elements backspace to work and text selection / copy paste to work. 10 | -------------------------------------------------------------------------------- /lib/worker/child.ts: -------------------------------------------------------------------------------- 1 | var typescriptServices = ''; 2 | if (process.argv.length > 2) { 3 | typescriptServices = process.argv[2]; 4 | } 5 | // setup typescript 6 | import {makeTsGlobal} from "../typescript/makeTypeScriptGlobal"; 7 | makeTsGlobal(typescriptServices); 8 | 9 | import workerLib = require('./lib/workerLib'); 10 | 11 | 12 | // Initiate the child logic 13 | var child = new workerLib.Child(); 14 | 15 | /////////////////////////////////////// END INFRASTRUCTURE //////////////////////////////////////////////////// 16 | import * as projectCache from "../main/lang/projectCache"; 17 | // push in child 18 | projectCache.fixChild(child); 19 | 20 | 21 | // Automatically include all functions from "projectService" as a responder 22 | import projectService = require('../main/lang/projectService'); 23 | child.registerAllFunctionsExportedFromAsResponders(projectService); 24 | -------------------------------------------------------------------------------- /lib/main/atom/views/view.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | import sp = require("atom-space-pen-views"); 4 | 5 | export class View extends sp.View { 6 | get $(): JQuery { 7 | return this; 8 | } 9 | 10 | static content() { 11 | throw new Error('Must override the base View static content member'); 12 | } 13 | 14 | constructor(public options: Options) { 15 | super(); 16 | this.init(); 17 | } 18 | init() { } 19 | } 20 | 21 | export var $ = sp.$; 22 | 23 | export class ScrollView extends sp.ScrollView { 24 | get $(): JQuery { 25 | return this; 26 | } 27 | 28 | static content() { 29 | throw new Error('Must override the base View static content member'); 30 | } 31 | 32 | constructor(public options: Options) { 33 | super(); 34 | this.init(); 35 | } 36 | init() { } 37 | } -------------------------------------------------------------------------------- /lib/main/atom/fileStatusCache.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * We keep an in memory cache of certain knowledge points regarding a few file paths 3 | * This file maintains that 4 | */ 5 | import * as path from 'path'; 6 | import {consistentPath} from '../utils/fsUtil'; 7 | 8 | export interface FileStatus { 9 | /** True if the emit on the disk differs from the potential emit of the current ts file */ 10 | emitDiffers: boolean; 11 | /** True if the text in the editor has been modified during the current session */ 12 | modified: boolean; 13 | }; 14 | 15 | let fileStatuses: { [index: string]: FileStatus } = {}; 16 | export function getFileStatus(filePath: string): FileStatus { 17 | filePath = consistentPath(filePath); 18 | if (!fileStatuses[filePath]) { 19 | fileStatuses[filePath] = { modified: false, emitDiffers: false }; 20 | } 21 | return fileStatuses[filePath]; 22 | } 23 | -------------------------------------------------------------------------------- /lib/main/atom/views/awesomePanelView.ts: -------------------------------------------------------------------------------- 1 | import view = require('./view'); 2 | var $ = view.$; 3 | 4 | export class AwesomePanelView extends view.View { 5 | 6 | private something: JQuery; 7 | static content() { 8 | return this.div({ class: 'awesome' }, 9 | () => this.div({ class: 'dude', outlet: 'something' }) 10 | ); 11 | } 12 | 13 | init() { 14 | this.something.html('
tada
'); 15 | } 16 | } 17 | 18 | export var panelView: AwesomePanelView; 19 | export var panel: AtomCore.Panel; 20 | export function attach() { 21 | panelView = new AwesomePanelView({}); 22 | panel = atom.workspace.addModalPanel({ item: panelView, priority: 1000, visible: false }); 23 | 24 | /*setInterval(() => { 25 | panel.isVisible() ? panel.hide() : panel.show(); 26 | console.log('called'); 27 | }, 1000);*/ 28 | 29 | } 30 | -------------------------------------------------------------------------------- /lib/typings/tsd.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | /// 6 | /// 7 | /// 8 | /// 9 | /// 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | -------------------------------------------------------------------------------- /keymaps/atom-typescript.cson: -------------------------------------------------------------------------------- 1 | 'atom-workspace atom-text-editor:not([mini])[data-grammar^="source ts"]': 2 | 'alt-cmd-l': 'typescript:format-code' 3 | 'alt-ctrl-l': 'typescript:format-code' 4 | 'ctrl-;': 'typescript:context-actions' 5 | 'cmd-;': 'typescript:context-actions' 6 | 'f2': 'typescript:rename-refactor' 7 | 'shift-f12': 'typescript:find-references' 8 | 'alt-enter': 'typescript:quick-fix' 9 | 'ctrl-M': 'typescript:output-toggle' 10 | 'cmd-M': 'typescript:output-toggle' 11 | # Debuging 12 | 'f9': 'typescript:toggle-breakpoint' 13 | 14 | # Stronger bindings 15 | 'atom-workspace': 16 | 'f6': 'typescript:build' 17 | 'f12': 'typescript:go-to-declaration' 18 | 'ctrl-\'': 'typescript:sync' 19 | 'cmd-\'': 'typescript:sync' 20 | 21 | # Quick navigations 22 | '.platform-win32, .platform-linux, .platform-darwin': 23 | 'f8': 'typescript:go-to-next' 24 | 'shift-f8': 'typescript:go-to-previous' 25 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | 'use strict'; 3 | 4 | var srcDir = 'lib'; 5 | 6 | grunt.initConfig({ 7 | ts: { 8 | options: { 9 | target: 'es5', 10 | module: 'commonjs', 11 | sourceMap: false, 12 | preserveConstEnums: true, 13 | compiler: './node_modules/ntypescript/bin/tsc' 14 | }, 15 | dev: { 16 | src: [srcDir + '/**/*.ts'], 17 | watch: srcDir, 18 | outDir: './dist/', 19 | baseDir: './lib/' 20 | }, 21 | build: { 22 | src: [srcDir + '/**/*.ts'], 23 | outDir: './dist/', 24 | baseDir: './lib/' 25 | }, 26 | }, 27 | }); 28 | 29 | grunt.loadNpmTasks('grunt-ts'); 30 | grunt.registerTask('default', ['ts:dev']); 31 | grunt.registerTask('build', ['ts:build']); 32 | }; 33 | -------------------------------------------------------------------------------- /VSProj.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "VSProj", "VSProj.njsproj", "{ECF0E459-F515-4390-9257-4C7888CC0494}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {ECF0E459-F515-4390-9257-4C7888CC0494}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {ECF0E459-F515-4390-9257-4C7888CC0494}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {ECF0E459-F515-4390-9257-4C7888CC0494}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {ECF0E459-F515-4390-9257-4C7888CC0494}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /dist/main/utils/fsUtil.js: -------------------------------------------------------------------------------- 1 | function consistentPath(filePath) { 2 | return filePath.split('\\').join('/'); 3 | } 4 | exports.consistentPath = consistentPath; 5 | var path = require("path"); 6 | function resolve() { 7 | var args = []; 8 | for (var _i = 0; _i < arguments.length; _i++) { 9 | args[_i - 0] = arguments[_i]; 10 | } 11 | return consistentPath(path.resolve.apply(path, args)); 12 | } 13 | exports.resolve = resolve; 14 | function isExt(path, ext) { 15 | return path && path.indexOf(ext, path.length - ext.length) !== -1; 16 | } 17 | exports.isExt = isExt; 18 | function makeRelativePath(relativeFolder, filePath) { 19 | var relativePath = path.relative(relativeFolder, filePath).split('\\').join('/'); 20 | if (relativePath[0] !== '.') { 21 | relativePath = './' + relativePath; 22 | } 23 | return relativePath; 24 | } 25 | exports.makeRelativePath = makeRelativePath; 26 | function removeExt(filePath) { 27 | return filePath.substr(0, filePath.lastIndexOf('.')); 28 | } 29 | exports.removeExt = removeExt; 30 | -------------------------------------------------------------------------------- /lib/typings/status-bar/status-bar.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for status-bar 2 | // Project: https://github.com/atom/status-bar 3 | // Definitions by: vvakame 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | /// 8 | 9 | declare module StatusBar { 10 | interface IStatusBarViewStatic { 11 | content():any; 12 | 13 | new(...args:any[]):IStatusBarView; 14 | } 15 | 16 | interface IStatusBarView extends View { 17 | 18 | initialize():any; 19 | attach():any; 20 | destroy():any; 21 | appendLeft(view:View):any; 22 | prependLeft(view:View):any; 23 | appendRight(view:View):any; 24 | prependRight(view:View):any; 25 | getActiveBuffer():TextBuffer.ITextBuffer; 26 | getActiveItem():any; 27 | storeActiveBuffer():TextBuffer.ITextBuffer; 28 | subscribeToBuffer(event:string, callback:Function):any; 29 | subscribeAllToBuffer():any[]; 30 | unsubscribeAllFromBuffer():any[]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /views/renameView.html.coffee: -------------------------------------------------------------------------------- 1 | {$$$, View, TextEditorView} = require 'atom-space-pen-views' 2 | 3 | module.exports = 4 | -> 5 | @div tabIndex: -1, class: 'atomts-rename-view', => 6 | @div class: 'block', => 7 | @div => 8 | @span {outlet: 'title'}, => 'Rename Variable' 9 | @span class: 'subtle-info-message', => 10 | @span 'Close this panel with ' 11 | @span class:'highlight', 'esc' 12 | @span ' key. And commit with the ' 13 | @span class:'highlight', 'enter' 14 | @span 'key.' 15 | 16 | @div class: 'find-container block', => 17 | @div class: 'editor-container', => 18 | @subview 'newNameEditor', new TextEditorView(mini: true, placeholderText: 'new name') 19 | 20 | @div {outlet:'fileCount'}, => return 21 | @br {} 22 | @div {class: 'highlight-error', style:'display:none', outlet:'validationMessage'}, 23 | -------------------------------------------------------------------------------- /lib/typescript/makeTypeScriptGlobal.ts: -------------------------------------------------------------------------------- 1 | ////////////////////////////////// MAGIC 2 | import vm = require('vm'); 3 | import fs = require('fs'); 4 | import os = require('os'); 5 | import path = require('path'); 6 | 7 | global.stack = function() { 8 | console.error((new Error()).stack); 9 | } 10 | 11 | /** Makes the bundled typescript services global or (if passed in) a custom typescriptServices file */ 12 | export function makeTsGlobal(typescriptServices?: string) { 13 | var sandbox = { 14 | // This is going to gather the ts module exports 15 | ts: {}, 16 | console: console, 17 | stack: global.stack, 18 | require: require, 19 | module: module, 20 | process: process 21 | }; 22 | vm.createContext(sandbox); 23 | 24 | if (typescriptServices) { 25 | vm.runInContext(fs.readFileSync(typescriptServices).toString(), sandbox); 26 | } 27 | else { 28 | sandbox.ts = require('ntypescript'); 29 | } 30 | 31 | // Finally export ts to the local global namespace 32 | global.ts = sandbox.ts; 33 | } 34 | -------------------------------------------------------------------------------- /dist/linter.js: -------------------------------------------------------------------------------- 1 | var parent = require('./worker/parent'); 2 | var fs = require('fs'); 3 | var atom_1 = require("atom"); 4 | exports.provider = { 5 | name: 'TS', 6 | grammarScopes: ['source.ts', 'source.tsx'], 7 | scope: 'file', 8 | lintOnFly: true, 9 | lint: function (textEditor) { 10 | if (!textEditor.buffer.file 11 | || !textEditor.buffer.file.path 12 | || !fs.existsSync(textEditor.buffer.file.path)) 13 | return Promise.resolve([]); 14 | var filePath = textEditor.buffer.file.path; 15 | return parent.errorsForFile({ filePath: filePath }) 16 | .then(function (resp) { 17 | var linterErrors = resp.errors.map(function (err) { return ({ 18 | type: "Error", 19 | filePath: filePath, 20 | text: err.message, 21 | range: new atom_1.Range([err.startPos.line, err.startPos.col], [err.endPos.line, err.endPos.col]), 22 | }); }); 23 | return linterErrors; 24 | }) 25 | .catch(function (error) { 26 | return []; 27 | }); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /dist/main/bin/atbuild.js: -------------------------------------------------------------------------------- 1 | var makeTypeScriptGlobal_1 = require("../../typescript/makeTypeScriptGlobal"); 2 | makeTypeScriptGlobal_1.makeTsGlobal(); 3 | var tsconfig = require("../tsconfig/tsconfig"); 4 | var building = require("../lang/modules/building"); 5 | var project_1 = require("../lang/core/project"); 6 | var utils_1 = require("../lang/utils"); 7 | var startLoc; 8 | if (process.argv.length > 2) { 9 | startLoc = process.argv[2]; 10 | } 11 | else { 12 | startLoc = process.cwd(); 13 | } 14 | var projectFile = tsconfig.getProjectSync(startLoc); 15 | console.log("Compiling using project file: " + projectFile.projectFilePath); 16 | var proj = new project_1.Project(projectFile); 17 | var errors = utils_1.selectMany(proj.projectFile.project.files.map(function (filePath) { 18 | var output = building.emitFile(proj, filePath); 19 | return output.errors; 20 | })); 21 | building.emitDts(proj); 22 | if (errors.length == 0) { 23 | console.log('Compile successfull'); 24 | process.exit(0); 25 | } 26 | else { 27 | console.log('Errors:'); 28 | errors.forEach(function (e) { 29 | console.log(e.filePath, e.message); 30 | }); 31 | process.exit(1); 32 | } 33 | -------------------------------------------------------------------------------- /dist/main/atom/views/plainMessageView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var view = require('./view'); 7 | var $ = view.$; 8 | var PlainMessageView = (function (_super) { 9 | __extends(PlainMessageView, _super); 10 | function PlainMessageView() { 11 | _super.apply(this, arguments); 12 | } 13 | PlainMessageView.content = function () { 14 | this.div({ 15 | class: 'plain-message' 16 | }); 17 | }; 18 | PlainMessageView.prototype.init = function () { 19 | this.$.html(this.options.message); 20 | this.$.addClass(this.options.className); 21 | }; 22 | PlainMessageView.prototype.getSummary = function () { 23 | return { 24 | summary: this.options.message, 25 | rawSummary: true, 26 | className: this.options.className 27 | }; 28 | }; 29 | return PlainMessageView; 30 | })(view.View); 31 | exports.PlainMessageView = PlainMessageView; 32 | -------------------------------------------------------------------------------- /dist/main/atom/views/awesomePanelView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var view = require('./view'); 7 | var $ = view.$; 8 | var AwesomePanelView = (function (_super) { 9 | __extends(AwesomePanelView, _super); 10 | function AwesomePanelView() { 11 | _super.apply(this, arguments); 12 | } 13 | AwesomePanelView.content = function () { 14 | var _this = this; 15 | return this.div({ class: 'awesome' }, function () { return _this.div({ class: 'dude', outlet: 'something' }); }); 16 | }; 17 | AwesomePanelView.prototype.init = function () { 18 | this.something.html('
tada
'); 19 | }; 20 | return AwesomePanelView; 21 | })(view.View); 22 | exports.AwesomePanelView = AwesomePanelView; 23 | function attach() { 24 | exports.panelView = new AwesomePanelView({}); 25 | exports.panel = atom.workspace.addModalPanel({ item: exports.panelView, priority: 1000, visible: false }); 26 | } 27 | exports.attach = attach; 28 | -------------------------------------------------------------------------------- /dist/main/lang/fixmyts/quickFixes/equalsToEquals.js: -------------------------------------------------------------------------------- 1 | var EqualsToEquals = (function () { 2 | function EqualsToEquals() { 3 | this.key = EqualsToEquals.name; 4 | } 5 | EqualsToEquals.prototype.canProvideFix = function (info) { 6 | if (info.positionNode.kind === ts.SyntaxKind.EqualsEqualsToken) { 7 | return { display: "Convert == to ===" }; 8 | } 9 | if (info.positionNode.kind === ts.SyntaxKind.ExclamationEqualsToken) { 10 | return { display: "Convert != to !==" }; 11 | } 12 | }; 13 | EqualsToEquals.prototype.provideFix = function (info) { 14 | if (info.positionNode.kind === ts.SyntaxKind.EqualsEqualsToken) { 15 | var newText = '==='; 16 | } 17 | if (info.positionNode.kind === ts.SyntaxKind.ExclamationEqualsToken) { 18 | var newText = '!=='; 19 | } 20 | var refactoring = { 21 | span: { 22 | start: info.positionNode.end - 2, 23 | length: 2 24 | }, 25 | newText: newText, 26 | filePath: info.filePath 27 | }; 28 | return [refactoring]; 29 | }; 30 | return EqualsToEquals; 31 | })(); 32 | exports.EqualsToEquals = EqualsToEquals; 33 | -------------------------------------------------------------------------------- /lib/main/utils/fsUtil.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Wraps fs and path into a nice "consistentPath" API 3 | */ 4 | 5 | /** we work with "/" for all paths (so does the typescript language service) */ 6 | export function consistentPath(filePath: string): string { 7 | return filePath.split('\\').join('/'); 8 | } 9 | 10 | import * as path from "path"; 11 | 12 | /** 13 | * Resolves to to an absolute path. 14 | * @param from,to,to,to... 15 | */ 16 | export function resolve(...args: string[]) { 17 | return consistentPath(path.resolve(...args)); 18 | } 19 | 20 | 21 | /** 22 | * Could be called ends with :) 23 | */ 24 | export function isExt(path: string, ext: string): boolean { 25 | return path && path.indexOf(ext, path.length - ext.length) !== -1; 26 | } 27 | 28 | /** 29 | * Converts "C:\boo" , "C:\boo\foo.ts" => "./foo.ts"; Works on unix as well. 30 | */ 31 | export function makeRelativePath(relativeFolder: string, filePath: string) { 32 | var relativePath = path.relative(relativeFolder, filePath).split('\\').join('/'); 33 | if (relativePath[0] !== '.') { 34 | relativePath = './' + relativePath; 35 | } 36 | return relativePath; 37 | } 38 | 39 | export function removeExt(filePath: string) { 40 | return filePath.substr(0, filePath.lastIndexOf('.')); 41 | } -------------------------------------------------------------------------------- /dist/main/lang/transformers/transformer.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | function isTransformerFile(filePath) { 3 | var ext = path.extname(filePath); 4 | return ext == '.tst'; 5 | } 6 | exports.isTransformerFile = isTransformerFile; 7 | function getPseudoFilePath(filePath) { 8 | if (isTransformerFile(filePath)) { 9 | return getPseudoTsFile(filePath); 10 | } 11 | return filePath; 12 | } 13 | exports.getPseudoFilePath = getPseudoFilePath; 14 | function getPseudoTsFile(filePath) { 15 | return filePath + '.ts'; 16 | } 17 | function getTransformerFile(filePath) { 18 | if (endsWith(filePath, '.tst.ts')) { 19 | filePath = removeExt(filePath); 20 | } 21 | return filePath; 22 | } 23 | exports.getTransformerFile = getTransformerFile; 24 | function isRawFile(filePath) { 25 | return endsWith(filePath, ".raw.ts"); 26 | } 27 | exports.isRawFile = isRawFile; 28 | function isPseudoFile(filePath) { 29 | var ext = path.extname(filePath); 30 | return endsWith(filePath, ".tst.ts"); 31 | } 32 | exports.isPseudoFile = isPseudoFile; 33 | function endsWith(str, suffix) { 34 | return str && str.indexOf(suffix, str.length - suffix.length) !== -1; 35 | } 36 | function removeExt(filePath) { 37 | return filePath && filePath.substr(0, filePath.lastIndexOf('.')); 38 | } 39 | -------------------------------------------------------------------------------- /lib/main/bin/atbuild.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is a work in progress 3 | */ 4 | 5 | import {makeTsGlobal} from "../../typescript/makeTypeScriptGlobal"; 6 | makeTsGlobal(); 7 | 8 | import * as tsconfig from "../tsconfig/tsconfig"; 9 | import * as building from "../lang/modules/building"; 10 | import {Project} from "../lang/core/project"; 11 | import {selectMany} from "../lang/utils"; 12 | 13 | var startLoc; 14 | if (process.argv.length > 2) { 15 | // Read the first additional argument passed to the program 16 | startLoc = process.argv[2]; 17 | } 18 | else { 19 | startLoc = process.cwd(); 20 | } 21 | 22 | var projectFile = tsconfig.getProjectSync(startLoc); 23 | console.log(`Compiling using project file: ${projectFile.projectFilePath}`); 24 | var proj = new Project(projectFile); 25 | 26 | var errors = selectMany(proj.projectFile.project.files.map((filePath) => { 27 | var output = building.emitFile(proj, filePath); 28 | return output.errors; 29 | })); 30 | 31 | // Also optionally emit a root dts: 32 | building.emitDts(proj); 33 | 34 | if (errors.length == 0) { 35 | console.log('Compile successfull'); 36 | process.exit(0); 37 | } 38 | else { 39 | console.log('Errors:'); 40 | errors.forEach(e=> { 41 | console.log(e.filePath, e.message); 42 | }) 43 | process.exit(1); 44 | } -------------------------------------------------------------------------------- /dist/main/atom/views/fileSemanticView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var atomUtils = require("../atomUtils"); 7 | function showForCurrentEditor() { 8 | var ed = atomUtils.getActiveEditor(); 9 | showForEditor(ed); 10 | } 11 | exports.showForCurrentEditor = showForCurrentEditor; 12 | function showForEditor(ed) { 13 | // atom.notifications.addInfo('Semantic view coming soon'); 14 | } 15 | exports.showForEditor = showForEditor; 16 | var view_1 = require("./view"); 17 | var FileSemanticView = (function (_super) { 18 | __extends(FileSemanticView, _super); 19 | function FileSemanticView(options) { 20 | _super.call(this, options); 21 | } 22 | FileSemanticView.prototype.init = function () { 23 | var _this = this; 24 | this.stopChangingListener = this.options.editor.onDidStopChanging(function () { 25 | }); 26 | this.destroyListener = this.options.editor.onDidDestroy(function () { 27 | _this.destroyListener.dispose(); 28 | _this.stopChangingListener.dispose(); 29 | }); 30 | }; 31 | return FileSemanticView; 32 | })(view_1.ScrollView); 33 | -------------------------------------------------------------------------------- /lib/main/atom/components/ts-view.ts: -------------------------------------------------------------------------------- 1 | // Some docs 2 | // http://www.html5rocks.com/en/tutorials/webcomponents/customelements/ (look at lifecycle callback methods) 3 | 4 | export class TsView extends HTMLElement { 5 | editorElement; 6 | editor; 7 | createdCallback() { 8 | var preview = this.innerText; 9 | this.innerText = ""; 10 | 11 | // Based on markdown editor 12 | // https://github.com/atom/markdown-preview/blob/2bcbadac3980f1aeb455f7078bd1fdfb4e6fe6b1/lib/renderer.coffee#L111 13 | var editorElement = this.editorElement = document.createElement('atom-text-editor'); 14 | editorElement.setAttributeNode(document.createAttribute('gutter-hidden')); 15 | editorElement.removeAttribute('tabindex'); // make read-only 16 | var editor = this.editor = (editorElement).getModel(); 17 | editor.getDecorations({ class: 'cursor-line', type: 'line' })[0].destroy(); // remove the default selection of a line in each editor 18 | editor.setText(preview); 19 | var grammar = (atom).grammars.grammarForScopeName("source.ts") 20 | editor.setGrammar(grammar); 21 | editor.setSoftWrapped(true); 22 | 23 | this.appendChild(editorElement); 24 | } 25 | 26 | // API 27 | text(text: string) { 28 | this.editor.setText(text); 29 | } 30 | } 31 | 32 | (document).registerElement('ts-view', TsView); -------------------------------------------------------------------------------- /dist/main/lang/modules/formatting.js: -------------------------------------------------------------------------------- 1 | function formatDocument(proj, filePath) { 2 | var textChanges = proj.languageService.getFormattingEditsForDocument(filePath, proj.projectFile.project.formatCodeOptions); 3 | var edits = textChanges.map(function (change) { 4 | return { 5 | start: proj.languageServiceHost.getPositionFromIndex(filePath, change.span.start), 6 | end: proj.languageServiceHost.getPositionFromIndex(filePath, change.span.start + change.span.length), 7 | newText: change.newText 8 | }; 9 | }); 10 | return edits; 11 | } 12 | exports.formatDocument = formatDocument; 13 | function formatDocumentRange(proj, filePath, start, end) { 14 | var st = proj.languageServiceHost.getIndexFromPosition(filePath, start); 15 | var ed = proj.languageServiceHost.getIndexFromPosition(filePath, end); 16 | var textChanges = proj.languageService.getFormattingEditsForRange(filePath, st, ed, proj.projectFile.project.formatCodeOptions); 17 | var edits = textChanges.map(function (change) { 18 | return { 19 | start: proj.languageServiceHost.getPositionFromIndex(filePath, change.span.start), 20 | end: proj.languageServiceHost.getPositionFromIndex(filePath, change.span.start + change.span.length), 21 | newText: change.newText 22 | }; 23 | }); 24 | return edits; 25 | } 26 | exports.formatDocumentRange = formatDocumentRange; 27 | -------------------------------------------------------------------------------- /dist/main/atom/components/ts-view.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var TsView = (function (_super) { 7 | __extends(TsView, _super); 8 | function TsView() { 9 | _super.apply(this, arguments); 10 | } 11 | TsView.prototype.createdCallback = function () { 12 | var preview = this.innerText; 13 | this.innerText = ""; 14 | var editorElement = this.editorElement = document.createElement('atom-text-editor'); 15 | editorElement.setAttributeNode(document.createAttribute('gutter-hidden')); 16 | editorElement.removeAttribute('tabindex'); 17 | var editor = this.editor = editorElement.getModel(); 18 | editor.getDecorations({ class: 'cursor-line', type: 'line' })[0].destroy(); 19 | editor.setText(preview); 20 | var grammar = atom.grammars.grammarForScopeName("source.ts"); 21 | editor.setGrammar(grammar); 22 | editor.setSoftWrapped(true); 23 | this.appendChild(editorElement); 24 | }; 25 | TsView.prototype.text = function (text) { 26 | this.editor.setText(text); 27 | }; 28 | return TsView; 29 | })(HTMLElement); 30 | exports.TsView = TsView; 31 | document.registerElement('ts-view', TsView); 32 | -------------------------------------------------------------------------------- /lib/main/lang/fixmyts/quickFixes/equalsToEquals.ts: -------------------------------------------------------------------------------- 1 | import {QuickFix, QuickFixQueryInformation, Refactoring, CanProvideFixResponse} from "../quickFix"; 2 | import * as ast from "../astUtils"; 3 | import {EOL} from "os"; 4 | 5 | export class EqualsToEquals implements QuickFix { 6 | key = EqualsToEquals.name; 7 | 8 | canProvideFix(info: QuickFixQueryInformation): CanProvideFixResponse { 9 | if (info.positionNode.kind === ts.SyntaxKind.EqualsEqualsToken) { 10 | return { display: "Convert == to ===" }; 11 | } 12 | if (info.positionNode.kind === ts.SyntaxKind.ExclamationEqualsToken) { 13 | return { display: "Convert != to !==" }; 14 | } 15 | } 16 | 17 | provideFix(info: QuickFixQueryInformation): Refactoring[] { 18 | 19 | if (info.positionNode.kind === ts.SyntaxKind.EqualsEqualsToken) { 20 | var newText = '==='; 21 | } 22 | if (info.positionNode.kind === ts.SyntaxKind.ExclamationEqualsToken) { 23 | var newText = '!=='; 24 | } 25 | 26 | var refactoring: Refactoring = { 27 | span: { 28 | // Since TypeScript stores trivia at with the node `pos` we only want 2 steps behind the `end` instead of `pos` 29 | start: info.positionNode.end - 2, 30 | length: 2 31 | }, 32 | newText, 33 | filePath: info.filePath 34 | }; 35 | 36 | return [refactoring]; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /dist/main/lang/fixmyts/quickFixes/quoteToTemplate.js: -------------------------------------------------------------------------------- 1 | var QuoteToTemplate = (function () { 2 | function QuoteToTemplate() { 3 | this.key = QuoteToTemplate.name; 4 | } 5 | QuoteToTemplate.prototype.canProvideFix = function (info) { 6 | if (info.positionNode.kind === ts.SyntaxKind.StringLiteral) { 7 | return { display: "Convert to Template String" }; 8 | } 9 | }; 10 | QuoteToTemplate.prototype.provideFix = function (info) { 11 | var text = info.positionNode.getText(); 12 | var quoteCharacter = text.trim()[0]; 13 | var nextQuoteCharacter = '`'; 14 | var quoteRegex = new RegExp(quoteCharacter, 'g'); 15 | var escapedQuoteRegex = new RegExp("\\\\" + quoteCharacter, 'g'); 16 | var nextQuoteRegex = new RegExp(nextQuoteCharacter, 'g'); 17 | var newText = text 18 | .replace(nextQuoteRegex, "\\" + nextQuoteCharacter) 19 | .replace(escapedQuoteRegex, quoteCharacter); 20 | newText = nextQuoteCharacter + newText.substr(1, newText.length - 2) + nextQuoteCharacter; 21 | var refactoring = { 22 | span: { 23 | start: info.positionNode.getStart(), 24 | length: info.positionNode.end - info.positionNode.getStart() 25 | }, 26 | newText: newText, 27 | filePath: info.filePath 28 | }; 29 | return [refactoring]; 30 | }; 31 | return QuoteToTemplate; 32 | })(); 33 | exports.QuoteToTemplate = QuoteToTemplate; 34 | -------------------------------------------------------------------------------- /lib/main/lang/modules/formatting.ts: -------------------------------------------------------------------------------- 1 | import project = require('../core/project'); 2 | 3 | export function formatDocument(proj: project.Project, filePath: string): CodeEdit[] { 4 | var textChanges = proj.languageService.getFormattingEditsForDocument(filePath, proj.projectFile.project.formatCodeOptions); 5 | 6 | var edits: CodeEdit[] = textChanges.map(change=> { 7 | return { 8 | start: proj.languageServiceHost.getPositionFromIndex(filePath, change.span.start), 9 | end: proj.languageServiceHost.getPositionFromIndex(filePath, change.span.start + change.span.length), 10 | newText: change.newText 11 | }; 12 | }); 13 | 14 | return edits; 15 | } 16 | export function formatDocumentRange(proj: project.Project, filePath: string, start: EditorPosition, end: EditorPosition): CodeEdit[] { 17 | var st = proj.languageServiceHost.getIndexFromPosition(filePath, start); 18 | var ed = proj.languageServiceHost.getIndexFromPosition(filePath, end); 19 | var textChanges = proj.languageService.getFormattingEditsForRange(filePath, st, ed, proj.projectFile.project.formatCodeOptions); 20 | 21 | var edits: CodeEdit[] = textChanges.map(change=> { 22 | return { 23 | start: proj.languageServiceHost.getPositionFromIndex(filePath, change.span.start), 24 | end: proj.languageServiceHost.getPositionFromIndex(filePath, change.span.start + change.span.length), 25 | newText: change.newText 26 | }; 27 | }); 28 | return edits; 29 | } 30 | -------------------------------------------------------------------------------- /lib/main/lang/modules/programDependencies.ts: -------------------------------------------------------------------------------- 1 | 2 | import {TypeScriptProjectFileDetails, pathIsRelative} from "../../tsconfig/tsconfig"; 3 | import {consistentPath} from "../../utils/fsUtil"; 4 | import tsconfig = require("../../tsconfig/tsconfig"); 5 | import * as path from "path"; 6 | import * as fs from "fs"; 7 | import {getSourceFileImports} from "../fixmyts/astUtils"; 8 | 9 | export default function getDependencies(projectFile: TypeScriptProjectFileDetails, program: ts.Program): FileDependency[] { 10 | var links: FileDependency[] = []; 11 | var projectDir = projectFile.projectFileDirectory; 12 | for (let file of program.getSourceFiles()) { 13 | let filePath = file.fileName; 14 | var dir = path.dirname(filePath); 15 | 16 | var targets = getSourceFileImports(file) 17 | .filter((fileReference) => pathIsRelative(fileReference)) 18 | .map(fileReference => { 19 | var file = path.resolve(dir, fileReference + '.ts'); 20 | if (!fs.existsSync(file)) { 21 | file = path.resolve(dir, fileReference + '.d.ts'); 22 | } 23 | return file; 24 | }); 25 | 26 | for (let target of targets) { 27 | var targetPath = consistentPath(path.relative(projectDir, consistentPath(target))); 28 | var sourcePath = consistentPath(path.relative(projectDir, filePath)); 29 | links.push({ 30 | sourcePath, 31 | targetPath 32 | }) 33 | } 34 | } 35 | return links; 36 | } 37 | -------------------------------------------------------------------------------- /lib/main/lang/fixmyts/quickFixRegistry.ts: -------------------------------------------------------------------------------- 1 | import {QuickFix} from "./quickFix"; 2 | /** 3 | * This exists to register the quick fixes 4 | */ 5 | import {AddClassMember} from "./quickFixes/addClassMember"; 6 | import {AddClassMethod} from "./quickFixes/addClassMethod"; 7 | import {AddImportStatement} from "./quickFixes/addImportStatement"; 8 | import {EqualsToEquals} from "./quickFixes/equalsToEquals"; 9 | import {ExtractVariable} from "./quickFixes/extractVariable"; 10 | import {WrapInProperty} from "./quickFixes/wrapInProperty"; 11 | import {QuotesToQuotes} from "./quickFixes/quotesToQuotes"; 12 | import {QuoteToTemplate} from "./quickFixes/quoteToTemplate"; 13 | import {StringConcatToTemplate} from "./quickFixes/stringConcatToTemplate"; 14 | import {TypeAssertPropertyAccessToAny} from "./quickFixes/typeAssertPropertyAccessToAny"; 15 | import {TypeAssertPropertyAccessToType} from "./quickFixes/typeAssertPropertyAccessToType"; 16 | import {ImplementInterface} from "./quickFixes/implementInterface"; 17 | import {SingleLineCommentToJsdoc} from "./quickFixes/singleLineCommentToJsdoc"; 18 | export var allQuickFixes: QuickFix[] = [ 19 | new AddClassMethod(), 20 | new AddClassMember(), 21 | new AddImportStatement(), 22 | new WrapInProperty(), 23 | new EqualsToEquals(), 24 | new ExtractVariable(), 25 | new StringConcatToTemplate(), 26 | new QuotesToQuotes(), 27 | new QuoteToTemplate(), 28 | new TypeAssertPropertyAccessToAny(), 29 | new TypeAssertPropertyAccessToType(), 30 | new ImplementInterface(), 31 | new SingleLineCommentToJsdoc() 32 | ]; 33 | -------------------------------------------------------------------------------- /lib/main/atom/views/tooltipView.ts: -------------------------------------------------------------------------------- 1 | import view = require('./view'); 2 | var $ = view.$; 3 | 4 | interface Rect { 5 | left: number; 6 | right: number; 7 | top: number; 8 | bottom: number; 9 | } 10 | 11 | export class TooltipView extends view.View { 12 | 13 | constructor(public rect: Rect) { 14 | super(rect); 15 | $(document.body).append(this.$); 16 | this.updatePosition() 17 | } 18 | 19 | private inner: JQuery; 20 | static content() { 21 | return this.div({ class: 'atom-typescript-tooltip tooltip' }, () => { 22 | this.div({ class: 'tooltip-inner', outlet: 'inner' }) 23 | }); 24 | } 25 | 26 | updateText(text: string) { 27 | this.inner.html(text); 28 | this.updatePosition(); 29 | this.$.fadeTo(300, 1); 30 | } 31 | 32 | updatePosition() { 33 | var offset = 10; 34 | var left = this.rect.right; 35 | var top = this.rect.bottom; 36 | var right = undefined; 37 | 38 | // X axis adjust 39 | if (left + this.$[0].offsetWidth >= view.$(document.body).width()) 40 | left = view.$(document.body).width() - this.$[0].offsetWidth - offset; 41 | if (left < 0) { 42 | this.$.css({ 'white-space': 'pre-wrap' }) 43 | left = offset 44 | right = offset 45 | } 46 | 47 | // Y axis adjust 48 | if (top + this.$[0].offsetHeight >= $(document.body).height()) { 49 | top = this.rect.top - this.$[0].offsetHeight 50 | } 51 | 52 | this.$.css({ left, top, right }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /dist/main/atom/onSaveHandler.js: -------------------------------------------------------------------------------- 1 | var atomUtils = require("./atomUtils"); 2 | var parent = require('../../worker/parent'); 3 | var mainPanelView_1 = require("./views/mainPanelView"); 4 | var fileStatusCache_1 = require("./fileStatusCache"); 5 | function handle(event) { 6 | var textUpdated = parent.updateText({ filePath: event.filePath, text: event.editor.getText() }); 7 | textUpdated.then(function () { 8 | atomUtils.triggerLinter(); 9 | parent.errorsForFile({ filePath: event.filePath }) 10 | .then(function (resp) { return mainPanelView_1.errorView.setErrors(event.filePath, resp.errors); }); 11 | }); 12 | mainPanelView_1.show(); 13 | parent.getProjectFileDetails({ filePath: event.filePath }).then(function (fileDetails) { 14 | if (fileDetails.project.compileOnSave 15 | && !fileDetails.project.compilerOptions.out 16 | && !fileDetails.project.buildOnSave) { 17 | textUpdated.then(function () { return parent.emitFile({ filePath: event.filePath }); }) 18 | .then(function (res) { 19 | var status = fileStatusCache_1.getFileStatus(event.filePath); 20 | status.modified = false; 21 | status.emitDiffers = res.emitError; 22 | mainPanelView_1.panelView.updateFileStatus(event.filePath); 23 | mainPanelView_1.errorView.showEmittedMessage(res); 24 | }); 25 | } 26 | if (fileDetails.project.buildOnSave) { 27 | atom.commands.dispatch(atom.views.getView(event.editor), 'typescript:build'); 28 | } 29 | }); 30 | } 31 | exports.handle = handle; 32 | -------------------------------------------------------------------------------- /docs/dependency-view.md: -------------------------------------------------------------------------------- 1 | # In Out 2 | * Nodes that do not depend on anything are colored green : These are probably utilities. 3 | * Nodes that only depend on other stuff are colored blue: These are probably application entry points. 4 | 5 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/dependencyView/inOut.png) 6 | 7 | # Circular 8 | Circular dependencies are highlighted in red 9 | 10 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/dependencyView/circular.png) 11 | 12 | # Filter 13 | You can filter particular nodes by specifying their name 14 | 15 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/dependencyView/filter.png) 16 | 17 | # Hover 18 | When you hover over a node 19 | * Red arrow denote stuff this file depends upon. Implies that this file cannot be extracted without also moving these files. 20 | * Green arrows denote stuff that depends on this file. Green as this means the code in this file is moveable to another project and these links will play no part in that. 21 | 22 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/dependencyView/teaser.png) 23 | 24 | # Size 25 | Size is based on average of in-degree and out-degree: 26 | 27 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/dependencyView/size.png) 28 | 29 | # Distance 30 | Distance is determined by how much of the file path is common between two nodes: 31 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/dependencyView/distance.png) 32 | -------------------------------------------------------------------------------- /dist/main/lang/modules/programDependencies.js: -------------------------------------------------------------------------------- 1 | var tsconfig_1 = require("../../tsconfig/tsconfig"); 2 | var fsUtil_1 = require("../../utils/fsUtil"); 3 | var path = require("path"); 4 | var fs = require("fs"); 5 | var astUtils_1 = require("../fixmyts/astUtils"); 6 | function getDependencies(projectFile, program) { 7 | var links = []; 8 | var projectDir = projectFile.projectFileDirectory; 9 | for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { 10 | var file = _a[_i]; 11 | var filePath = file.fileName; 12 | var dir = path.dirname(filePath); 13 | var targets = astUtils_1.getSourceFileImports(file) 14 | .filter(function (fileReference) { return tsconfig_1.pathIsRelative(fileReference); }) 15 | .map(function (fileReference) { 16 | var file = path.resolve(dir, fileReference + '.ts'); 17 | if (!fs.existsSync(file)) { 18 | file = path.resolve(dir, fileReference + '.d.ts'); 19 | } 20 | return file; 21 | }); 22 | for (var _b = 0; _b < targets.length; _b++) { 23 | var target = targets[_b]; 24 | var targetPath = fsUtil_1.consistentPath(path.relative(projectDir, fsUtil_1.consistentPath(target))); 25 | var sourcePath = fsUtil_1.consistentPath(path.relative(projectDir, filePath)); 26 | links.push({ 27 | sourcePath: sourcePath, 28 | targetPath: targetPath 29 | }); 30 | } 31 | } 32 | return links; 33 | } 34 | Object.defineProperty(exports, "__esModule", { value: true }); 35 | exports.default = getDependencies; 36 | -------------------------------------------------------------------------------- /docs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Breaking Changes 2 | 3 | We only plan to *strictly* document the breaking changes. The rest is optional. 4 | 5 | # Planned 6 | (No breaking changes staged) 7 | 8 | # v7.0.0 9 | * Removed the (already ignored in any significant way) `version` option from tsconfig. [More](https://github.com/TypeStrong/atom-typescript/issues/617) 10 | 11 | # v6.0.0 12 | * Bring back `dts-generator` as using the other mechanism has a few gotchas that might surprise new users. We will remove this feature once [https://github.com/Microsoft/TypeScript/issues/2338] is officially supported. 13 | 14 | # v5.0.0 15 | * We no longer *automatically* create a `tsconfig.json`. However we provide a *command* "TypeScript: Create tsconfig.json project file". 16 | 17 | # v4.8.0 18 | * Feature: Added ReactJS / `.tsx` support 19 | 20 | # v4 21 | * Removed `dts-generator` support. Reason is that it pollutes the global namespace and is no longer the recommended way for sharing TypeScript code. See https://github.com/Microsoft/TypeScript/issues/2338 for the way forward. 22 | 23 | # v3 24 | * We will now resolve a parent `package.json` for you *automatically* so that its *one less thing you need to configure*. :rose: 25 | 26 | # v2 27 | * New default shortcuts for `build` : `F6` an `goto definition`: `F12`. Because I don't want to mess with your atom defaults and a major use base is VS users. [Link #145](https://github.com/TypeStrong/atom-typescript/issues/145) 28 | 29 | # v1 30 | * `format` -> `formatCodeOptions` https://github.com/TypeStrong/atom-typescript/issues/178 31 | * `compileOnSave` is now a tsconfig option : https://github.com/TypeStrong/atom-typescript/issues/187 32 | 33 | # 0.x 34 | * Initial releases 35 | 36 | -------------------------------------------------------------------------------- /lib/main/lang/fixmyts/quickFixes/quoteToTemplate.ts: -------------------------------------------------------------------------------- 1 | import {QuickFix, QuickFixQueryInformation, Refactoring, CanProvideFixResponse} from "../quickFix"; 2 | import * as ast from "../astUtils"; 3 | import {EOL} from "os"; 4 | 5 | export class QuoteToTemplate implements QuickFix { 6 | key = QuoteToTemplate.name; 7 | 8 | canProvideFix(info: QuickFixQueryInformation): CanProvideFixResponse { 9 | if (info.positionNode.kind === ts.SyntaxKind.StringLiteral) { 10 | return { display: `Convert to Template String` }; 11 | } 12 | } 13 | 14 | provideFix(info: QuickFixQueryInformation): Refactoring[] { 15 | 16 | var text = info.positionNode.getText(); 17 | var quoteCharacter = text.trim()[0]; 18 | var nextQuoteCharacter = '`'; 19 | 20 | // The following code is same as `quotesToQuotes. Refactor!` 21 | 22 | var quoteRegex = new RegExp(quoteCharacter, 'g') 23 | var escapedQuoteRegex = new RegExp(`\\\\${quoteCharacter}`, 'g') 24 | var nextQuoteRegex = new RegExp(nextQuoteCharacter, 'g') 25 | 26 | var newText = text 27 | .replace(nextQuoteRegex, `\\${nextQuoteCharacter}`) 28 | .replace(escapedQuoteRegex, quoteCharacter); 29 | 30 | newText = nextQuoteCharacter + newText.substr(1, newText.length - 2) + nextQuoteCharacter 31 | 32 | var refactoring: Refactoring = { 33 | span: { 34 | start: info.positionNode.getStart(), 35 | length: info.positionNode.end - info.positionNode.getStart() 36 | }, 37 | newText, 38 | filePath: info.filePath 39 | }; 40 | 41 | return [refactoring]; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /dist/main/atom/views/view.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var sp = require("atom-space-pen-views"); 7 | var View = (function (_super) { 8 | __extends(View, _super); 9 | function View(options) { 10 | _super.call(this); 11 | this.options = options; 12 | this.init(); 13 | } 14 | Object.defineProperty(View.prototype, "$", { 15 | get: function () { 16 | return this; 17 | }, 18 | enumerable: true, 19 | configurable: true 20 | }); 21 | View.content = function () { 22 | throw new Error('Must override the base View static content member'); 23 | }; 24 | View.prototype.init = function () { }; 25 | return View; 26 | })(sp.View); 27 | exports.View = View; 28 | exports.$ = sp.$; 29 | var ScrollView = (function (_super) { 30 | __extends(ScrollView, _super); 31 | function ScrollView(options) { 32 | _super.call(this); 33 | this.options = options; 34 | this.init(); 35 | } 36 | Object.defineProperty(ScrollView.prototype, "$", { 37 | get: function () { 38 | return this; 39 | }, 40 | enumerable: true, 41 | configurable: true 42 | }); 43 | ScrollView.content = function () { 44 | throw new Error('Must override the base View static content member'); 45 | }; 46 | ScrollView.prototype.init = function () { }; 47 | return ScrollView; 48 | })(sp.ScrollView); 49 | exports.ScrollView = ScrollView; 50 | -------------------------------------------------------------------------------- /dist/main/lang/fixmyts/quickFixes/quotesToQuotes.js: -------------------------------------------------------------------------------- 1 | var QuotesToQuotes = (function () { 2 | function QuotesToQuotes() { 3 | this.key = QuotesToQuotes.name; 4 | } 5 | QuotesToQuotes.prototype.canProvideFix = function (info) { 6 | if (info.positionNode.kind === ts.SyntaxKind.StringLiteral) { 7 | if (info.positionNode.getText().trim()[0] === "'") { 8 | return { display: "Convert ' to \"" }; 9 | } 10 | if (info.positionNode.getText().trim()[0] === "\"") { 11 | return { display: "Convert \" to '" }; 12 | } 13 | } 14 | }; 15 | QuotesToQuotes.prototype.provideFix = function (info) { 16 | var text = info.positionNode.getText(); 17 | var quoteCharacter = text.trim()[0]; 18 | var nextQuoteCharacter = quoteCharacter === "'" ? '"' : "'"; 19 | var quoteRegex = new RegExp(quoteCharacter, 'g'); 20 | var escapedQuoteRegex = new RegExp("\\\\" + quoteCharacter, 'g'); 21 | var nextQuoteRegex = new RegExp(nextQuoteCharacter, 'g'); 22 | var newText = text 23 | .replace(nextQuoteRegex, "\\" + nextQuoteCharacter) 24 | .replace(escapedQuoteRegex, quoteCharacter); 25 | newText = nextQuoteCharacter + newText.substr(1, newText.length - 2) + nextQuoteCharacter; 26 | var refactoring = { 27 | span: { 28 | start: info.positionNode.getStart(), 29 | length: info.positionNode.end - info.positionNode.getStart() 30 | }, 31 | newText: newText, 32 | filePath: info.filePath 33 | }; 34 | return [refactoring]; 35 | }; 36 | return QuotesToQuotes; 37 | })(); 38 | exports.QuotesToQuotes = QuotesToQuotes; 39 | -------------------------------------------------------------------------------- /dist/main/lang/fixmyts/quickFixRegistry.js: -------------------------------------------------------------------------------- 1 | var addClassMember_1 = require("./quickFixes/addClassMember"); 2 | var addClassMethod_1 = require("./quickFixes/addClassMethod"); 3 | var addImportStatement_1 = require("./quickFixes/addImportStatement"); 4 | var equalsToEquals_1 = require("./quickFixes/equalsToEquals"); 5 | var extractVariable_1 = require("./quickFixes/extractVariable"); 6 | var wrapInProperty_1 = require("./quickFixes/wrapInProperty"); 7 | var quotesToQuotes_1 = require("./quickFixes/quotesToQuotes"); 8 | var quoteToTemplate_1 = require("./quickFixes/quoteToTemplate"); 9 | var stringConcatToTemplate_1 = require("./quickFixes/stringConcatToTemplate"); 10 | var typeAssertPropertyAccessToAny_1 = require("./quickFixes/typeAssertPropertyAccessToAny"); 11 | var typeAssertPropertyAccessToType_1 = require("./quickFixes/typeAssertPropertyAccessToType"); 12 | var implementInterface_1 = require("./quickFixes/implementInterface"); 13 | var singleLineCommentToJsdoc_1 = require("./quickFixes/singleLineCommentToJsdoc"); 14 | exports.allQuickFixes = [ 15 | new addClassMethod_1.AddClassMethod(), 16 | new addClassMember_1.AddClassMember(), 17 | new addImportStatement_1.AddImportStatement(), 18 | new wrapInProperty_1.WrapInProperty(), 19 | new equalsToEquals_1.EqualsToEquals(), 20 | new extractVariable_1.ExtractVariable(), 21 | new stringConcatToTemplate_1.StringConcatToTemplate(), 22 | new quotesToQuotes_1.QuotesToQuotes(), 23 | new quoteToTemplate_1.QuoteToTemplate(), 24 | new typeAssertPropertyAccessToAny_1.TypeAssertPropertyAccessToAny(), 25 | new typeAssertPropertyAccessToType_1.TypeAssertPropertyAccessToType(), 26 | new implementInterface_1.ImplementInterface(), 27 | new singleLineCommentToJsdoc_1.SingleLineCommentToJsdoc() 28 | ]; 29 | -------------------------------------------------------------------------------- /dist/main/atom/editorSetup.js: -------------------------------------------------------------------------------- 1 | var utils_1 = require("../lang/utils"); 2 | var parent = require("../../worker/parent"); 3 | var atomUtils = require("./atomUtils"); 4 | var transformer_1 = require("../lang/transformers/transformer"); 5 | function setupEditor(editor) { 6 | var quickFixDecoration = null; 7 | var quickFixMarker = null; 8 | function clearExistingQuickfixDecoration() { 9 | if (quickFixDecoration) { 10 | quickFixDecoration.destroy(); 11 | quickFixDecoration = null; 12 | } 13 | if (quickFixMarker) { 14 | quickFixMarker.destroy(); 15 | quickFixMarker = null; 16 | } 17 | } 18 | var queryForQuickFix = utils_1.debounce(function (filePathPosition) { 19 | parent.getQuickFixes(filePathPosition).then(function (res) { 20 | clearExistingQuickfixDecoration(); 21 | if (res.fixes.length) { 22 | quickFixMarker = editor.markBufferRange(editor.getSelectedBufferRange()); 23 | quickFixDecoration = editor.decorateMarker(quickFixMarker, { type: "line-number", class: "quickfix" }); 24 | } 25 | }); 26 | }, 500); 27 | var cursorObserver = editor.onDidChangeCursorPosition(function () { 28 | try { 29 | var pathPos = atomUtils.getFilePathPosition(); 30 | if (transformer_1.isTransformerFile(pathPos.filePath)) { 31 | clearExistingQuickfixDecoration(); 32 | return; 33 | } 34 | queryForQuickFix(pathPos); 35 | } 36 | catch (ex) { 37 | clearExistingQuickfixDecoration(); 38 | } 39 | }); 40 | var destroyObserver = editor.onDidDestroy(function () { 41 | cursorObserver.dispose(); 42 | destroyObserver.dispose(); 43 | }); 44 | } 45 | exports.setupEditor = setupEditor; 46 | -------------------------------------------------------------------------------- /dist/main/lang/modules/getPathCompletions.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var tsconfig = require("../../tsconfig/tsconfig"); 3 | var utils = require("../utils"); 4 | var fuzzaldrin = require('fuzzaldrin'); 5 | function getExternalModuleNames(program) { 6 | var entries = []; 7 | program.getSourceFiles().forEach(function (sourceFile) { 8 | ts.forEachChild(sourceFile, function (child) { 9 | if (child.kind === ts.SyntaxKind.ModuleDeclaration && child.name.kind === ts.SyntaxKind.StringLiteral) { 10 | entries.push(child.name.text); 11 | } 12 | }); 13 | }); 14 | return entries; 15 | } 16 | function getPathCompletions(query) { 17 | var project = query.project; 18 | var sourceDir = path.dirname(query.filePath); 19 | var filePaths = project.projectFile.project.files.filter(function (p) { return p !== query.filePath; }); 20 | var files = []; 21 | if (query.includeExternalModules) { 22 | var externalModules = getExternalModuleNames(project.languageService.getProgram()); 23 | externalModules.forEach(function (e) { return files.push({ 24 | name: "" + e, 25 | relativePath: e, 26 | fullPath: e 27 | }); }); 28 | } 29 | filePaths.forEach(function (p) { 30 | files.push({ 31 | name: path.basename(p, '.ts'), 32 | relativePath: tsconfig.removeExt(tsconfig.makeRelativePath(sourceDir, p)), 33 | fullPath: p 34 | }); 35 | }); 36 | var endsInPunctuation = utils.prefixEndsInPunctuation(query.prefix); 37 | if (!endsInPunctuation) 38 | files = fuzzaldrin.filter(files, query.prefix, { key: 'name' }); 39 | var response = { 40 | files: files, 41 | endsInPunctuation: endsInPunctuation 42 | }; 43 | return response; 44 | } 45 | exports.getPathCompletions = getPathCompletions; 46 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "atom-typescript", 3 | "version": "7.6.3", 4 | "main": "./dist/main/atomts", 5 | "bin": { 6 | "atbuild": "./dist/main/bin/atbuild" 7 | }, 8 | "preferGlobal": "true", 9 | "description": "The only TypeScript plugin you will ever need.", 10 | "engines": { 11 | "atom": ">=0.199.0 <2.0.0", 12 | "node": "*" 13 | }, 14 | "providedServices": { 15 | "autocomplete.provider": { 16 | "versions": { 17 | "2.0.0": "provide" 18 | } 19 | }, 20 | "linter": { 21 | "versions": { 22 | "1.0.0": "provideLinter" 23 | } 24 | } 25 | }, 26 | "consumedServices": { 27 | "snippets": { 28 | "versions": { 29 | "0.1.0": "consumeSnippets" 30 | } 31 | } 32 | }, 33 | "homepage": "http://atom.io/packages/atom-typescript", 34 | "repository": { 35 | "type": "git", 36 | "url": "https://github.com/TypeStrong/atom-typescript.git" 37 | }, 38 | "license": "MIT", 39 | "bugs": { 40 | "url": "https://github.com/TypeStrong/atom-typescript/issues" 41 | }, 42 | "dependencies": { 43 | "atom-package-deps": "^2.0.3", 44 | "atom-space-pen-views": "^2.0.4", 45 | "babel": "^5.6.23", 46 | "basarat-text-buffer": "6.0.0", 47 | "d3": "^3.5.5", 48 | "detect-indent": "^4.0.0", 49 | "emissary": "^1.3.3", 50 | "escape-html": "^1.0.1", 51 | "fuzzaldrin": "^2.1.0", 52 | "glob": "^5.0.15", 53 | "htmltojsx": "0.2.4", 54 | "immutable": "^3.7.3", 55 | "json2dts": "0.0.1", 56 | "mkdirp": "^0.5.0", 57 | "ntypescript": "1.201510270605.1", 58 | "react": "^0.13.3", 59 | "season": "^5.1.4", 60 | "tsconfig": "^2.1.0", 61 | "xtend": "^4.0.0" 62 | }, 63 | "devDependencies": {}, 64 | "package-deps": [ 65 | "linter" 66 | ], 67 | "keywords": [ 68 | "typescript", 69 | "javascript", 70 | "html" 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /lib/main/atom/atomConfig.ts: -------------------------------------------------------------------------------- 1 | import {getName} from "../lang/utils"; 2 | 3 | // Documentation https://atom.io/docs/api/v0.177.0/Config and http://json-schema.org/examples.html 4 | // To add a new setting you need to add to 5 | // schema 6 | // getter/setter 7 | 8 | var packageName = 'atom-typescript'; 9 | function getConfig(nameLambda: () => any): T { 10 | return atom.config.get(packageName + '.' + getName(nameLambda)); 11 | } 12 | function setConfig(nameLambda: () => any, value: T): T { 13 | return atom.config.set(packageName + '.' + getName(nameLambda), value); 14 | } 15 | 16 | class Config { 17 | schema = { 18 | debugAtomTs: { 19 | title: 'Debug: Atom-TypeScript. Please do not use.', 20 | type: 'boolean', 21 | default: false 22 | }, 23 | preferredQuoteCharacter: { 24 | title: 'Preferred quote character', 25 | type: 'string', 26 | default: 'none' 27 | }, 28 | typescriptServices: { 29 | title: 'Full path (including file name) to a custom `typescriptServices.js`', 30 | type: 'string', 31 | default: '' 32 | }, 33 | showSemanticView: { 34 | title: 'Show semantic view', 35 | type: 'boolean', 36 | default: false 37 | } 38 | } 39 | get debugAtomTs() { return getConfig(() => this.schema.debugAtomTs) } 40 | get preferredQuoteCharacter() { return getConfig(() => this.schema.preferredQuoteCharacter) } 41 | get typescriptServices() { return getConfig(() => this.schema.typescriptServices) } 42 | get showSemanticView() { return getConfig(() => this.schema.showSemanticView) } 43 | set showSemanticView(value: boolean) { setConfig(() => this.schema.showSemanticView, value) } 44 | } 45 | var config = new Config(); 46 | export = config; 47 | -------------------------------------------------------------------------------- /dist/main/atom/views/tooltipView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var view = require('./view'); 7 | var $ = view.$; 8 | var TooltipView = (function (_super) { 9 | __extends(TooltipView, _super); 10 | function TooltipView(rect) { 11 | _super.call(this, rect); 12 | this.rect = rect; 13 | $(document.body).append(this.$); 14 | this.updatePosition(); 15 | } 16 | TooltipView.content = function () { 17 | var _this = this; 18 | return this.div({ class: 'atom-typescript-tooltip tooltip' }, function () { 19 | _this.div({ class: 'tooltip-inner', outlet: 'inner' }); 20 | }); 21 | }; 22 | TooltipView.prototype.updateText = function (text) { 23 | this.inner.html(text); 24 | this.updatePosition(); 25 | this.$.fadeTo(300, 1); 26 | }; 27 | TooltipView.prototype.updatePosition = function () { 28 | var offset = 10; 29 | var left = this.rect.right; 30 | var top = this.rect.bottom; 31 | var right = undefined; 32 | if (left + this.$[0].offsetWidth >= view.$(document.body).width()) 33 | left = view.$(document.body).width() - this.$[0].offsetWidth - offset; 34 | if (left < 0) { 35 | this.$.css({ 'white-space': 'pre-wrap' }); 36 | left = offset; 37 | right = offset; 38 | } 39 | if (top + this.$[0].offsetHeight >= $(document.body).height()) { 40 | top = this.rect.top - this.$[0].offsetHeight; 41 | } 42 | this.$.css({ left: left, top: top, right: right }); 43 | }; 44 | return TooltipView; 45 | })(view.View); 46 | exports.TooltipView = TooltipView; 47 | -------------------------------------------------------------------------------- /dist/main/lang/transformers/transformerRegistry.js: -------------------------------------------------------------------------------- 1 | var allTransformers = []; 2 | function add(transformer) { 3 | transformer.regex = (new RegExp("transform:" + transformer.name + "{[.\\s]*}transform:" + transformer.name, 'g')); 4 | allTransformers.push(transformer); 5 | } 6 | exports.add = add; 7 | function getNames() { 8 | return allTransformers.map(function (at) { return at.name; }); 9 | } 10 | exports.getNames = getNames; 11 | function getRegexes() { 12 | return allTransformers.map(function (at) { return at.regex; }); 13 | } 14 | exports.getRegexes = getRegexes; 15 | var transformFinderRegex = /transform:(.*){/g; 16 | var transformEndFinderRegexGenerator = function (name) { return new RegExp("}transform:" + name); }; 17 | function getInitialTransformation(code) { 18 | var transforms = []; 19 | var processedSrcUpto = 0; 20 | var srcCode = code; 21 | var destCode = ''; 22 | var destDelta = 0; 23 | while (true) { 24 | var remainingCode = code.substr(processedSrcUpto); 25 | var matches = transformFinderRegex.exec(remainingCode); 26 | if (!matches || !matches.length || matches.length < 2) 27 | return { transforms: transforms }; 28 | var nextTransformName = matches.slice[1]; 29 | } 30 | return { transforms: transforms }; 31 | } 32 | exports.getInitialTransformation = getInitialTransformation; 33 | function transform(name, code) { 34 | var transformer = allTransformers.filter(function (at) { return at.name == name; })[0]; 35 | if (!transformer) { 36 | console.error('No transformer registered with name: ', name); 37 | return { code: '' }; 38 | } 39 | return transformer.transform(code); 40 | } 41 | exports.transform = transform; 42 | var glob = require('glob'); 43 | var files = glob.sync('./implementations/*.js', { 44 | nodir: true, 45 | cwd: __dirname 46 | }); 47 | files = files.map(function (f) { return require(f); }); 48 | -------------------------------------------------------------------------------- /lib/main/atom/views/fileSymbolsView.ts: -------------------------------------------------------------------------------- 1 | import sp = require('atom-space-pen-views'); 2 | import mainPanelView = require('./mainPanelView'); 3 | import atomUtils = require("../atomUtils"); 4 | 5 | 6 | /** 7 | * https://github.com/atom/atom-space-pen-views 8 | */ 9 | export class FileSymbolsView extends sp.SelectListView { 10 | 11 | get $(): JQuery { 12 | return this; 13 | } 14 | 15 | public filePath: string; 16 | public setNavBarItems(tsItems: NavigationBarItem[], filePath) { 17 | 18 | var items: NavigationBarItem[] = tsItems; 19 | 20 | this.filePath = filePath; 21 | 22 | super.setItems(items) 23 | } 24 | 25 | /** override */ 26 | viewForItem(item: NavigationBarItem) { 27 | return ` 28 |
  • 29 |
    ${ Array(item.indent * 2).join(' ') + (item.indent ? "\u221F " : '') + item.text}
    30 |
    ${item.kind}
    31 |
    line: ${item.position.line + 1}
    32 |
  • 33 | `; 34 | } 35 | 36 | /** override */ 37 | confirmed(item: NavigationBarItem) { 38 | atom.workspace.open(this.filePath, { 39 | initialLine: item.position.line, 40 | initialColumn: item.position.col 41 | }); 42 | 43 | this.hide(); 44 | } 45 | 46 | getFilterKey() { return 'text'; } 47 | 48 | panel: AtomCore.Panel = null; 49 | show() { 50 | this.storeFocusedElement(); 51 | if (!this.panel) this.panel = atom.workspace.addModalPanel({ item: this }); 52 | this.panel.show() 53 | 54 | this.focusFilterEditor(); 55 | } 56 | hide() { 57 | this.panel.hide(); 58 | this.restoreFocus(); 59 | } 60 | 61 | cancelled() { 62 | this.hide(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /dist/main/lang/modules/moveFiles.js: -------------------------------------------------------------------------------- 1 | var astUtils_1 = require("../fixmyts/astUtils"); 2 | var path = require("path"); 3 | var tsconfig_1 = require("../../tsconfig/tsconfig"); 4 | var fsUtil_1 = require("../../utils/fsUtil"); 5 | function getRenameFilesRefactorings(program, oldDirectoryOrFile, newDirectoryOrFile) { 6 | oldDirectoryOrFile = fsUtil_1.consistentPath(oldDirectoryOrFile); 7 | newDirectoryOrFile = fsUtil_1.consistentPath(newDirectoryOrFile); 8 | var oldFileNoExt = tsconfig_1.removeExt(oldDirectoryOrFile); 9 | var newFileNoExt = tsconfig_1.removeExt(newDirectoryOrFile); 10 | var refactorings = []; 11 | var sourceFiles = program.getSourceFiles(); 12 | sourceFiles.forEach(function (sourceFile) { 13 | var imports = astUtils_1.getSourceFileImportsWithTextRange(sourceFile) 14 | .filter(function (fileReference) { return tsconfig_1.pathIsRelative(fileReference.text); }) 15 | .map(function (ref) { 16 | return { 17 | path: fsUtil_1.consistentPath(path.resolve(path.dirname(sourceFile.fileName), ref.text)), 18 | range: ref.range 19 | }; 20 | }); 21 | var matches = imports.filter(function (f) { return f.path == oldFileNoExt; }); 22 | if (matches.length) { 23 | for (var _i = 0; _i < matches.length; _i++) { 24 | var match = matches[_i]; 25 | refactorings.push({ 26 | filePath: sourceFile.fileName, 27 | span: { 28 | start: match.range.pos, 29 | length: match.range.end - match.range.pos 30 | }, 31 | newText: tsconfig_1.makeRelativePath(path.dirname(sourceFile.fileName), newFileNoExt) 32 | }); 33 | } 34 | } 35 | }); 36 | return refactorings; 37 | } 38 | exports.getRenameFilesRefactorings = getRenameFilesRefactorings; 39 | -------------------------------------------------------------------------------- /lib/main/lang/fixmyts/quickFixes/quotesToQuotes.ts: -------------------------------------------------------------------------------- 1 | import {QuickFix, QuickFixQueryInformation, Refactoring, CanProvideFixResponse} from "../quickFix"; 2 | import * as ast from "../astUtils"; 3 | import {EOL} from "os"; 4 | 5 | export class QuotesToQuotes implements QuickFix { 6 | key = QuotesToQuotes.name; 7 | 8 | canProvideFix(info: QuickFixQueryInformation): CanProvideFixResponse { 9 | if (info.positionNode.kind === ts.SyntaxKind.StringLiteral) { 10 | if (info.positionNode.getText().trim()[0] === `'`) { 11 | return { display: `Convert ' to "` }; 12 | } 13 | if (info.positionNode.getText().trim()[0] === `"`) { 14 | return { display: `Convert " to '` }; 15 | } 16 | } 17 | } 18 | 19 | provideFix(info: QuickFixQueryInformation): Refactoring[] { 20 | 21 | var text = info.positionNode.getText(); 22 | var quoteCharacter = text.trim()[0]; 23 | var nextQuoteCharacter = quoteCharacter === "'" ? '"' : "'"; 24 | 25 | // STOLEN : https://github.com/atom/toggle-quotes/blob/master/lib/toggle-quotes.coffee 26 | var quoteRegex = new RegExp(quoteCharacter, 'g') 27 | var escapedQuoteRegex = new RegExp(`\\\\${quoteCharacter}`, 'g') 28 | var nextQuoteRegex = new RegExp(nextQuoteCharacter, 'g') 29 | 30 | var newText = text 31 | .replace(nextQuoteRegex, `\\${nextQuoteCharacter}`) 32 | .replace(escapedQuoteRegex, quoteCharacter); 33 | 34 | newText = nextQuoteCharacter + newText.substr(1, newText.length - 2) + nextQuoteCharacter 35 | 36 | var refactoring: Refactoring = { 37 | span: { 38 | start: info.positionNode.getStart(), 39 | length: info.positionNode.end - info.positionNode.getStart() 40 | }, 41 | newText, 42 | filePath: info.filePath 43 | }; 44 | 45 | return [refactoring]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /docs/grammar.md: -------------------------------------------------------------------------------- 1 | # CSON Grammar 2 | What is meant by `name` and `captures` 3 | https://discuss.atom.io/t/grammar-understanding-captures-vs-name/14783 4 | 5 | Generally the best docs: 6 | http://manual.macromates.com/en/language_grammars.html 7 | 8 | # Dynamic Grammar 9 | We used dynamic (code driven) grammar initially. Following are the lessons still worth sharing but we are using the CSON grammar now. 10 | 11 | I am using `atom` and `first-mate` interchangeably here. There isn't a documented way of creating a grammar from *code*. We found a hacky way by reading a *lot of source code*. Please look at `typeScriptGrammar.ts`. Basically you inherit from `Grammar` and let that do the heavy lifting. Then all you need is to return `AtomTokens` from `tokenizeLine`. The way the atom grammar works is that they will store the returned `ruleSet` for any line and call `tokenizeLine` for the next line passing in that `ruleSet`. As soon as you edit a line all the following lines are invalidated and `tokenizeLine` is called for them again. This works beautifully with the `ts.createClassifier` which is a quick syntactic classifier provided by the TS language service. It only depends on a `finalLexState` (e.g. did the previous line have a continuing multiline comment) and that is what we store in the `ruleSet`. 12 | 13 | **Warnings**: 14 | * Atom is stingy about you calling its `createToken` in the *right order* so don't just call it unless you have the classification at exactly the right time. 15 | * Atom doesn't want you to classify the BOM. It will give it to you as a part of the string, its up to you to carefully ignore it and don't call `createToken` for it. 16 | * Do not mutate the `ruleSet` that is passed into you. Its for the previous line. Create your own `ruleSet` for your line! 17 | * Also see [#159](https://github.com/TypeStrong/atom-typescript/issues/159) to see how editor settings (still using regex copied from language-javascript) + forcefully tokenizing empty lines plays with autoindent. 18 | 19 | 20 | -------------------------------------------------------------------------------- /dist/main/lang/core/project.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | exports.languageServiceHost = require('./languageServiceHost2'); 3 | var tsconfig = require('../../tsconfig/tsconfig'); 4 | var transformerRegistry = require("../transformers/transformerRegistry"); 5 | var Project = (function () { 6 | function Project(projectFile) { 7 | var _this = this; 8 | this.projectFile = projectFile; 9 | this.languageServiceHost = new exports.languageServiceHost.LanguageServiceHost(projectFile); 10 | var transformerRegexes = transformerRegistry.getRegexes(); 11 | projectFile.project.files.forEach(function (file) { 12 | if (tsconfig.endsWith(file, '.tst.ts')) { 13 | var rawContent = fs.readFileSync(tsconfig.removeExt(file), 'utf-8'); 14 | var withoutTransform = rawContent; 15 | transformerRegexes.forEach(function (transformer) { 16 | withoutTransform = withoutTransform.replace(transformer, ''); 17 | ; 18 | }); 19 | _this.languageServiceHost.addScript(file, withoutTransform); 20 | } 21 | else { 22 | _this.languageServiceHost.addScript(file); 23 | } 24 | }); 25 | this.languageService = ts.createLanguageService(this.languageServiceHost, ts.createDocumentRegistry()); 26 | } 27 | Project.prototype.getProjectSourceFiles = function () { 28 | var libFile = exports.languageServiceHost.getDefaultLibFilePath(this.projectFile.project.compilerOptions); 29 | var files = this.languageService.getProgram().getSourceFiles().filter(function (x) { return x.fileName !== libFile; }); 30 | return files; 31 | }; 32 | Project.prototype.includesSourceFile = function (fileName) { 33 | return (this.getProjectSourceFiles().filter(function (f) { return f.fileName === fileName; }).length === 1); 34 | }; 35 | return Project; 36 | })(); 37 | exports.Project = Project; 38 | -------------------------------------------------------------------------------- /lib/linter.ts: -------------------------------------------------------------------------------- 1 | // This file is only called from linter 2 | // See : https://github.com/AtomLinter/Linter/issues/337 3 | 4 | ///ts:import=utils 5 | import utils = require('./main/lang/utils'); ///ts:import:generated 6 | ///ts:import=parent 7 | import parent = require('./worker/parent'); ///ts:import:generated 8 | 9 | import fs = require('fs'); 10 | import {Range} from "atom"; 11 | 12 | interface LinterMessage { 13 | type: string, // "Error" or "Warning" 14 | text?: string, 15 | html?: string, 16 | filePath?: string, 17 | range?: TextBuffer.IRange, 18 | // trace?: Array // We don't care about this so I have this commented out 19 | } 20 | 21 | export var provider = { 22 | name: 'TS', 23 | grammarScopes: ['source.ts', 'source.tsx'], 24 | scope: 'file', // # or 'project' 25 | lintOnFly: true, // # must be false for scope: 'project' 26 | lint: (textEditor: AtomCore.IEditor): Promise => { 27 | 28 | // We do not support files not on disk 29 | if (!textEditor.buffer.file 30 | || !textEditor.buffer.file.path 31 | || !fs.existsSync(textEditor.buffer.file.path)) return Promise.resolve([]); 32 | 33 | var filePath = textEditor.buffer.file.path; 34 | 35 | return parent.errorsForFile({ filePath: filePath }) 36 | .then((resp) => { 37 | var linterErrors: LinterMessage[] = resp.errors.map((err) => ({ 38 | type: "Error", 39 | filePath, 40 | text: err.message, 41 | range: new Range([err.startPos.line, err.startPos.col], [err.endPos.line, err.endPos.col]), 42 | })); 43 | return linterErrors; 44 | }) 45 | .catch((error) => { 46 | /** 47 | * We catch these errors as the linter will do a full blown notification message on error 48 | */ 49 | return []; 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /docs/packages.md: -------------------------------------------------------------------------------- 1 | # Our package recommendations 2 | 3 | ## Critical 4 | 5 | ### autocomplete-plus 6 | We will install this for you to give a good autocomplete experience 7 | 8 | ### linter 9 | We will install this for you to give a good error highlight experience 10 | 11 | ## Misc 12 | We don't install these but highly recommend them 13 | 14 | ### Manage your projects 15 | https://github.com/danielbrodin/atom-project-manager 16 | Atom works on the basis of "folder" based project. It remembers the settings / state for when you open a project. 17 | 18 | This package allows you to quickly open a specific folder. You can even store config options specific to a project e.g. at my work we don't remove whitespace or add a new line to allow people to use whatever editor and not get insignificant diffs on legacy code: 19 | 20 | ```cson 21 | 'work': 22 | 'title': 'work' 23 | 'paths': [ 24 | 'C:\\dev\\work' 25 | ], 26 | 'settings': 27 | 'whitespace.removeTrailingWhitespace': false 28 | 'whitespace.ensureSingleTrailingNewline': false 29 | ``` 30 | 31 | It also allows you to configure options of `atom-typescript` on a per project basis e.g. 32 | ```cson 33 | 'work': 34 | 'title': 'work' 35 | 'paths': [ 36 | 'C:\\dev\\work' 37 | ], 38 | 'settings': 39 | 'atom-typescript.debugAtomTs': false 40 | ``` 41 | 42 | ### Jumpy 43 | https://atom.io/packages/jumpy saves a lot of wrist pain. 44 | 45 | ### last-cursor-position 46 | https://atom.io/packages/last-cursor-position Like visual studio go back to previous location. Really useful when you navigate to stuff and want to go back to where you were working. 47 | 48 | ### Find selection 49 | https://atom.io/packages/find-selection who has time to bring up the find and replace dialog for a quick find word. 50 | 51 | ### Pain Split 52 | https://atom.io/packages/pain-split a better pane splitting mechanism. 53 | 54 | ### Documentation 55 | https://atom.io/packages/docblockr for easier jsdocing 56 | 57 | ### Styles 58 | [Here's my styles.less](https://gist.github.com/basarat/87d0a17a850b74a1cc07) -------------------------------------------------------------------------------- /lib/main/lang/fixmyts/quickFixes/singleLineCommentToJsdoc.ts: -------------------------------------------------------------------------------- 1 | import utils = require("../../utils"); 2 | import {QuickFix, QuickFixQueryInformation, Refactoring, CanProvideFixResponse} from "../quickFix"; 3 | import * as ast from "../astUtils"; 4 | import {EOL} from "os"; 5 | 6 | export class SingleLineCommentToJsdoc implements QuickFix { 7 | key = SingleLineCommentToJsdoc.name; 8 | 9 | validNodes = utils.createMap([ 10 | ts.SyntaxKind.ExportKeyword, 11 | ts.SyntaxKind.VarKeyword, 12 | ts.SyntaxKind.LetKeyword, 13 | ts.SyntaxKind.ConstKeyword, 14 | ts.SyntaxKind.FunctionKeyword, 15 | ]); 16 | 17 | canProvideFix(info: QuickFixQueryInformation): CanProvideFixResponse { 18 | if (this.validNodes[info.positionNode.kind]) { 19 | let comments = ts.getLeadingCommentRangesOfNode(info.positionNode, info.sourceFile); 20 | if (!comments) return; 21 | 22 | const mapped = comments.map(c=> info.sourceFileText.substring(c.pos, c.end)); 23 | if (!mapped.length) return; 24 | 25 | let relevantComment = mapped[mapped.length - 1]; 26 | 27 | if (relevantComment.startsWith('//')) 28 | return { display: 'Convert comment to jsDoc' }; 29 | } 30 | } 31 | 32 | provideFix(info: QuickFixQueryInformation): Refactoring[] { 33 | 34 | let comments = ts.getLeadingCommentRangesOfNode(info.positionNode, info.sourceFile); 35 | let relevantComment = comments[comments.length - 1]; 36 | var oldText = info.sourceFileText.substring(relevantComment.pos, relevantComment.end); 37 | let newText = "/** " + oldText.substr(2).trim() + " */"; 38 | 39 | var refactoring: Refactoring = { 40 | span: { 41 | start: relevantComment.pos, 42 | length: relevantComment.end - relevantComment.pos 43 | }, 44 | newText, 45 | filePath: info.filePath 46 | }; 47 | 48 | return [refactoring]; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /dist/main/lang/fixmyts/quickFixes/singleLineCommentToJsdoc.js: -------------------------------------------------------------------------------- 1 | var utils = require("../../utils"); 2 | var SingleLineCommentToJsdoc = (function () { 3 | function SingleLineCommentToJsdoc() { 4 | this.key = SingleLineCommentToJsdoc.name; 5 | this.validNodes = utils.createMap([ 6 | ts.SyntaxKind.ExportKeyword, 7 | ts.SyntaxKind.VarKeyword, 8 | ts.SyntaxKind.LetKeyword, 9 | ts.SyntaxKind.ConstKeyword, 10 | ts.SyntaxKind.FunctionKeyword, 11 | ]); 12 | } 13 | SingleLineCommentToJsdoc.prototype.canProvideFix = function (info) { 14 | if (this.validNodes[info.positionNode.kind]) { 15 | var comments = ts.getLeadingCommentRangesOfNode(info.positionNode, info.sourceFile); 16 | if (!comments) 17 | return; 18 | var mapped = comments.map(function (c) { return info.sourceFileText.substring(c.pos, c.end); }); 19 | if (!mapped.length) 20 | return; 21 | var relevantComment = mapped[mapped.length - 1]; 22 | if (relevantComment.startsWith('//')) 23 | return { display: 'Convert comment to jsDoc' }; 24 | } 25 | }; 26 | SingleLineCommentToJsdoc.prototype.provideFix = function (info) { 27 | var comments = ts.getLeadingCommentRangesOfNode(info.positionNode, info.sourceFile); 28 | var relevantComment = comments[comments.length - 1]; 29 | var oldText = info.sourceFileText.substring(relevantComment.pos, relevantComment.end); 30 | var newText = "/** " + oldText.substr(2).trim() + " */"; 31 | var refactoring = { 32 | span: { 33 | start: relevantComment.pos, 34 | length: relevantComment.end - relevantComment.pos 35 | }, 36 | newText: newText, 37 | filePath: info.filePath 38 | }; 39 | return [refactoring]; 40 | }; 41 | return SingleLineCommentToJsdoc; 42 | })(); 43 | exports.SingleLineCommentToJsdoc = SingleLineCommentToJsdoc; 44 | -------------------------------------------------------------------------------- /lib/main/atom/views/projectSymbolsView.ts: -------------------------------------------------------------------------------- 1 | import sp = require('atom-space-pen-views'); 2 | import mainPanelView = require('./mainPanelView'); 3 | import atomUtils = require("../atomUtils"); 4 | 5 | 6 | /** 7 | * https://github.com/atom/atom-space-pen-views 8 | */ 9 | export class ProjectSymbolsView extends sp.SelectListView { 10 | 11 | get $(): JQuery { 12 | return this; 13 | } 14 | 15 | get filterView(): { 16 | $: JQuery, 17 | model: AtomCore.IEditor 18 | } { 19 | return { 20 | $: this.filterEditorView, 21 | model: (this.filterEditorView).model 22 | }; 23 | } 24 | 25 | public setNavBarItems(tsItems: NavigateToItem[]) { 26 | super.setMaxItems(40); 27 | 28 | var items: NavigateToItem[] = tsItems; 29 | super.setItems(items) 30 | } 31 | 32 | /** override */ 33 | viewForItem(item: NavigateToItem) { 34 | return ` 35 |
  • 36 |
    ${item.name}
    37 |
    ${item.kind}
    38 |
    ${item.fileName} : ${item.position.line + 1}
    39 |
  • 40 | `; 41 | } 42 | 43 | /** override */ 44 | confirmed(item: NavigateToItem) { 45 | atom.workspace.open(item.filePath, { 46 | initialLine: item.position.line, 47 | initialColumn: item.position.col 48 | }); 49 | 50 | this.hide(); 51 | } 52 | 53 | getFilterKey() { return 'name'; } 54 | 55 | panel: AtomCore.Panel = null; 56 | show() { 57 | this.storeFocusedElement(); 58 | if (!this.panel) this.panel = atom.workspace.addModalPanel({ item: this }); 59 | this.panel.show() 60 | 61 | this.focusFilterEditor(); 62 | } 63 | hide() { 64 | this.panel.hide(); 65 | this.restoreFocus(); 66 | } 67 | 68 | cancelled() { 69 | this.hide(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/typings/emissary/emissary.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for emissary 2 | // Project: https://github.com/atom/emissary 3 | // Definitions by: vvakame 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | 8 | declare module Emissary { 9 | interface IEmitterStatic extends Mixto.IMixinStatic { 10 | new ():IEmitter; 11 | } 12 | 13 | interface IEmitter { 14 | on(eventNames:string, handler:Function):any; // return value type are Signal 15 | once(eventName:string, handler:Function):any; // return value type are Signal 16 | signal(eventName:string):void; 17 | behavior(eventName:string, initialValue:any):void; 18 | emit(eventName:string, ...args:any[]):void; 19 | off(eventNames:string, handler:Function):void; 20 | pauseEvents(eventNames:string):void; 21 | resumeEvents(eventNames:string):void; 22 | incrementSubscriptionCount(eventName:string):number; 23 | decrementSubscriptionCount(eventName:string):number; 24 | getSubscriptionCount(eventName:string):number; 25 | hasSubscriptions(eventName:string):boolean; 26 | } 27 | 28 | interface ISubscriberStatic extends Mixto.IMixinStatic { 29 | new ():ISubscriber; 30 | } 31 | 32 | interface ISubscriber { 33 | subscribeWith(eventEmitter:any, methodName:string, args:any):ISubscription; 34 | 35 | addSubscription(subscription:any):ISubscription; 36 | 37 | subscribe(eventEmitterOrSubscription:any, ...args:any[]):ISubscription; 38 | 39 | subscribeToCommand(eventEmitter:any, ...args:any[]):ISubscription; 40 | 41 | unsubscribe(object?:any):any; 42 | } 43 | 44 | interface ISubscriptionStatic { 45 | new (emitter: any, eventNames:string, handler:Function):ISubscription; 46 | } 47 | 48 | interface ISubscription extends IEmitter { 49 | cancelled:boolean; 50 | 51 | off():any; 52 | } 53 | } 54 | 55 | declare module "emissary" { 56 | var Emitter:Emissary.IEmitterStatic; 57 | var Subscriber:Emissary.ISubscriberStatic; 58 | var Signal:Function; // TODO 59 | var Behavior:Function; // TODO 60 | var combine:Function; // TODO 61 | } 62 | -------------------------------------------------------------------------------- /dist/main/lang/fixmyts/quickFixes/typeAssertPropertyAccessToAny.js: -------------------------------------------------------------------------------- 1 | var TypeAssertPropertyAccessToAny = (function () { 2 | function TypeAssertPropertyAccessToAny() { 3 | this.key = TypeAssertPropertyAccessToAny.name; 4 | } 5 | TypeAssertPropertyAccessToAny.prototype.canProvideFix = function (info) { 6 | var relevantError = info.positionErrors.filter(function (x) { return x.code == ts.Diagnostics.Property_0_does_not_exist_on_type_1.code; })[0]; 7 | if (!relevantError) 8 | return; 9 | if (info.positionNode.kind !== ts.SyntaxKind.Identifier) 10 | return; 11 | var match = getIdentifierName(info.positionErrorMessages[0]); 12 | if (!match) 13 | return; 14 | var identifierName = match.identifierName; 15 | return { display: "Assert \"any\" for property access \"" + identifierName + "\"" }; 16 | }; 17 | TypeAssertPropertyAccessToAny.prototype.provideFix = function (info) { 18 | var parent = info.positionNode.parent; 19 | if (parent.kind == ts.SyntaxKind.PropertyAccessExpression) { 20 | var propertyAccess = parent; 21 | var start = propertyAccess.getStart(); 22 | var end = propertyAccess.dotToken.getStart(); 23 | var oldText = propertyAccess.getText().substr(0, end - start); 24 | var refactoring = { 25 | filePath: info.filePath, 26 | span: { 27 | start: start, 28 | length: end - start, 29 | }, 30 | newText: "(" + oldText + " as any)" 31 | }; 32 | return [refactoring]; 33 | } 34 | return []; 35 | }; 36 | return TypeAssertPropertyAccessToAny; 37 | })(); 38 | exports.TypeAssertPropertyAccessToAny = TypeAssertPropertyAccessToAny; 39 | function getIdentifierName(errorText) { 40 | var match = /Property \'(\w+)\' does not exist on type \.*/.exec(errorText); 41 | if (!match) 42 | return; 43 | var identifierName = match[1]; 44 | return { identifierName: identifierName }; 45 | } 46 | -------------------------------------------------------------------------------- /lib/typings/minimatch/minimatch.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Minimatch 2.0.8 2 | // Project: https://github.com/isaacs/minimatch 3 | // Definitions by: vvakame 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | declare module "minimatch" { 7 | 8 | function M(target: string, pattern: string, options?: M.IOptions): boolean; 9 | 10 | module M { 11 | function match(list: string[], pattern: string, options?: IOptions): string[]; 12 | function filter(pattern: string, options?: IOptions): (element: string, indexed: number, array: string[]) => boolean; 13 | function makeRe(pattern: string, options?: IOptions): RegExp; 14 | 15 | var Minimatch: IMinimatchStatic; 16 | 17 | interface IOptions { 18 | debug?: boolean; 19 | nobrace?: boolean; 20 | noglobstar?: boolean; 21 | dot?: boolean; 22 | noext?: boolean; 23 | nocase?: boolean; 24 | nonull?: boolean; 25 | matchBase?: boolean; 26 | nocomment?: boolean; 27 | nonegate?: boolean; 28 | flipNegate?: boolean; 29 | } 30 | 31 | interface IMinimatchStatic { 32 | new (pattern: string, options?: IOptions): IMinimatch; 33 | prototype: IMinimatch; 34 | } 35 | 36 | interface IMinimatch { 37 | pattern: string; 38 | options: IOptions; 39 | /** 2-dimensional array of regexp or string expressions. */ 40 | set: any[][]; // (RegExp | string)[][] 41 | regexp: RegExp; 42 | negate: boolean; 43 | comment: boolean; 44 | empty: boolean; 45 | 46 | makeRe(): RegExp; // regexp or boolean 47 | match(fname: string): boolean; 48 | matchOne(files: string[], pattern: string[], partial: boolean): boolean; 49 | 50 | /** Deprecated. For internal use. */ 51 | debug(): void; 52 | /** Deprecated. For internal use. */ 53 | make(): void; 54 | /** Deprecated. For internal use. */ 55 | parseNegate(): void; 56 | /** Deprecated. For internal use. */ 57 | braceExpand(pattern: string, options: IOptions): void; 58 | /** Deprecated. For internal use. */ 59 | parse(pattern: string, isSub?: boolean): void; 60 | } 61 | } 62 | 63 | export = M; 64 | } 65 | -------------------------------------------------------------------------------- /lib/tsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v4", 3 | "repo": "borisyankov/DefinitelyTyped", 4 | "ref": "master", 5 | "path": "typings", 6 | "bundle": "typings/tsd.d.ts", 7 | "installed": { 8 | "emissary/emissary.d.ts": { 9 | "commit": "69bdfb0884020e41f17a1dd80ad4c77de2636874" 10 | }, 11 | "pathwatcher/pathwatcher.d.ts": { 12 | "commit": "69bdfb0884020e41f17a1dd80ad4c77de2636874" 13 | }, 14 | "mixto/mixto.d.ts": { 15 | "commit": "69bdfb0884020e41f17a1dd80ad4c77de2636874" 16 | }, 17 | "atom/atom.d.ts": { 18 | "commit": "69bdfb0884020e41f17a1dd80ad4c77de2636874" 19 | }, 20 | "text-buffer/text-buffer.d.ts": { 21 | "commit": "69bdfb0884020e41f17a1dd80ad4c77de2636874" 22 | }, 23 | "status-bar/status-bar.d.ts": { 24 | "commit": "69bdfb0884020e41f17a1dd80ad4c77de2636874" 25 | }, 26 | "space-pen/space-pen.d.ts": { 27 | "commit": "69bdfb0884020e41f17a1dd80ad4c77de2636874" 28 | }, 29 | "jquery/jquery.d.ts": { 30 | "commit": "69bdfb0884020e41f17a1dd80ad4c77de2636874" 31 | }, 32 | "node/node.d.ts": { 33 | "commit": "66f88ec51858bb21bc375fa91a963c04bc09401e" 34 | }, 35 | "q/Q.d.ts": { 36 | "commit": "69bdfb0884020e41f17a1dd80ad4c77de2636874" 37 | }, 38 | "mkdirp/mkdirp.d.ts": { 39 | "commit": "69bdfb0884020e41f17a1dd80ad4c77de2636874" 40 | }, 41 | "d3/d3.d.ts": { 42 | "commit": "2520bce9a8a71b66e67487cbd5b33fec880b0c55" 43 | }, 44 | "source-map/source-map.d.ts": { 45 | "commit": "70737c2a2496f7a13c4da63eb00081cad94d19f1" 46 | }, 47 | "react/react.d.ts": { 48 | "commit": "6f04d25ad38982d372cc3cda62fa4c0eef9e24d7" 49 | }, 50 | "react/react-jsx.d.ts": { 51 | "commit": "6f04d25ad38982d372cc3cda62fa4c0eef9e24d7" 52 | }, 53 | "htmltojsx/htmltojsx.d.ts": { 54 | "commit": "1632606f82cfbaf89d4b96b8dccacfaf2a6ae2f3" 55 | }, 56 | "glob/glob.d.ts": { 57 | "commit": "66f88ec51858bb21bc375fa91a963c04bc09401e" 58 | }, 59 | "minimatch/minimatch.d.ts": { 60 | "commit": "66f88ec51858bb21bc375fa91a963c04bc09401e" 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lib/main/atom/views/rView.tsx: -------------------------------------------------------------------------------- 1 | // Sample implementation of a react view 2 | // DOCS: 3 | // http://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#es6-classes 4 | // https://facebook.github.io/react/docs/component-specs.html 5 | 6 | import {uriForPath} from "../atomUtils"; 7 | import * as sp from "atom-space-pen-views"; 8 | 9 | import React = require('react'); 10 | 11 | interface Props { initialCount: number } 12 | interface State { count: number } 13 | 14 | class MyComponent extends React.Component{ 15 | 16 | static defaultProps = { count: 0 }; 17 | state = { count: 0 }; 18 | constructor(props: Props) { 19 | super(props); 20 | } 21 | 22 | interval: number; 23 | componentDidMount() { 24 | this.interval = setInterval(() => { 25 | this.setState({ count: this.state.count + 1 }); 26 | }); 27 | } 28 | 29 | stop = () => { 30 | clearInterval(this.interval); 31 | } 32 | 33 | render() { 34 | return
    35 | This is a test: {this.state.count} 36 |
    37 | } 38 | } 39 | 40 | 41 | /** 42 | * A base class for creating React based views in atom 43 | */ 44 | export class RView extends sp.ScrollView { 45 | 46 | public mainContent: JQuery; 47 | public get rootDomElement() { 48 | return this.mainContent[0]; 49 | } 50 | static content() { 51 | return this.div({ class: 'atomts atomts-r-view native-key-bindings' }, () => { 52 | this.div({ outlet: 'mainContent layout' }); 53 | }); 54 | } 55 | 56 | constructor(public config: { 57 | icon: string; 58 | title: string; 59 | filePath: string; 60 | }) { 61 | super(); 62 | 63 | React.render(React.createElement(MyComponent, {}), this.rootDomElement); 64 | } 65 | 66 | 67 | /** Override */ 68 | static protocol: string = 'atomtsview:'; 69 | 70 | public get $() { return this as any as JQuery; } 71 | private getURI = () => uriForPath((this.constructor as any).protocol, this.config.filePath); 72 | private getTitle = () => this.config.title; 73 | private getIconName = () => this.config.icon; 74 | } 75 | -------------------------------------------------------------------------------- /dist/main/atom/buildView.js: -------------------------------------------------------------------------------- 1 | var mainPanelView = require('./views/mainPanelView'); 2 | var lineMessageView = require('./views/lineMessageView'); 3 | var gotoHistory = require('./gotoHistory'); 4 | function getTitle(errorCount) { 5 | var title = ' TypeScript Build'; 6 | if (errorCount > 0) { 7 | title = title + (" (\n " + errorCount + " \n error" + (errorCount === 1 ? "" : "s") + " \n )"); 8 | } 9 | return title; 10 | } 11 | function setBuildOutput(buildOutput) { 12 | mainPanelView.panelView.clearBuild(); 13 | if (buildOutput.counts.errors) { 14 | mainPanelView.panelView.setBuildPanelCount(buildOutput.counts.errors); 15 | } 16 | else { 17 | mainPanelView.panelView.setBuildPanelCount(0); 18 | } 19 | gotoHistory.buildOutput.members = []; 20 | buildOutput.outputs.forEach(function (output) { 21 | if (output.success) { 22 | return; 23 | } 24 | output.errors.forEach(function (error) { 25 | mainPanelView.panelView.addBuild(new lineMessageView.LineMessageView({ 26 | goToLine: function (filePath, line, col) { return gotoHistory.gotoLine(filePath, line, col, gotoHistory.buildOutput); }, 27 | message: error.message, 28 | line: error.startPos.line + 1, 29 | col: error.startPos.col, 30 | file: error.filePath, 31 | preview: error.preview 32 | })); 33 | gotoHistory.buildOutput.members.push({ filePath: error.filePath, line: error.startPos.line + 1, col: error.startPos.col }); 34 | }); 35 | }); 36 | if (!buildOutput.counts.errors) { 37 | atom.notifications.addSuccess("Build success"); 38 | } 39 | else if (buildOutput.counts.emitErrors) { 40 | atom.notifications.addError("Emits errors: " + buildOutput.counts.emitErrors + " files."); 41 | } 42 | else { 43 | atom.notifications.addWarning('Compile failed but emit succeeded'); 44 | } 45 | } 46 | exports.setBuildOutput = setBuildOutput; 47 | -------------------------------------------------------------------------------- /styles/documentationview.less: -------------------------------------------------------------------------------- 1 | // Ref https://github.com/tststs/atom-ternjs/blob/4616908855ac2efd1e2f3a1129a4eb4e47b78b52/stylesheets/atom-ternjs.less 2 | @import "ui-variables"; 3 | @atom-ts-height: 180px; 4 | 5 | .atom-ts-documentation > div, atom-ts-reference > div > div { 6 | max-height: @atom-ts-height; 7 | overflow-y: auto; 8 | } 9 | 10 | .atom-ts-documentation { 11 | position: absolute; 12 | right: calc(@component-padding + 10); 13 | background: fade(@overlay-background-color, 90%); 14 | border: 1px solid fade(@base-border-color, 20%); 15 | color: @text-color; 16 | border-radius: @component-border-radius; 17 | width: 40%; 18 | min-height: @atom-ts-height; 19 | max-width: 640px; 20 | opacity: 0; 21 | pointer-events: none; 22 | transition: opacity .2s ease; 23 | 24 | // I shouldn't need to do this. Check why we have to do this 25 | // also should use @scrollbar-background-color; at some point : https://github.com/TypeStrong/atom-typescript/issues/120 26 | ::-webkit-scrollbar { 27 | width: 8px; 28 | height: 8px; 29 | } 30 | ::-webkit-scrollbar-track, 31 | ::-webkit-scrollbar-corner { 32 | background: @pane-item-background-color; 33 | } 34 | ::-webkit-scrollbar-thumb { 35 | background: @base-border-color; 36 | border-radius: 5px; 37 | box-shadow: 0 0 1px black inset; 38 | } 39 | 40 | &.active { 41 | opacity: 1; 42 | pointer-events: auto; 43 | } 44 | 45 | &.top { 46 | top: calc(@component-padding + 36); 47 | } 48 | 49 | &.middle { 50 | top: calc(~'50% - '(@atom-ts-height / 2)); 51 | } 52 | 53 | &.bottom { 54 | bottom: calc(@component-padding + 26); 55 | } 56 | 57 | h2 { 58 | margin: 0; 59 | line-height: 1.4em; 60 | margin-top: -0.2em; 61 | } 62 | 63 | p { 64 | margin-top: 10px; 65 | > span { 66 | display: block; 67 | padding-top: 4px; 68 | } 69 | } 70 | 71 | .link { 72 | cursor: pointer; 73 | color: @text-color-highlight; 74 | &:hover { 75 | text-decoration: underline; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /dist/main/lang/fixmyts/quickFixes/typeAssertPropertyAccessToType.js: -------------------------------------------------------------------------------- 1 | var TypeAssertPropertyAccessToType = (function () { 2 | function TypeAssertPropertyAccessToType() { 3 | this.key = TypeAssertPropertyAccessToType.name; 4 | } 5 | TypeAssertPropertyAccessToType.prototype.canProvideFix = function (info) { 6 | var relevantError = info.positionErrors.filter(function (x) { return x.code == ts.Diagnostics.Property_0_does_not_exist_on_type_1.code; })[0]; 7 | if (!relevantError) 8 | return; 9 | if (info.positionNode.kind !== ts.SyntaxKind.Identifier) 10 | return; 11 | var match = getIdentifierName(info.positionErrorMessages[0]); 12 | if (!match) 13 | return; 14 | var identifierName = match.identifierName; 15 | return { display: "Assert for property access \"" + identifierName + "\"", isNewTextSnippet: true }; 16 | }; 17 | TypeAssertPropertyAccessToType.prototype.provideFix = function (info) { 18 | var parent = info.positionNode.parent; 19 | if (parent.kind == ts.SyntaxKind.PropertyAccessExpression) { 20 | var propertyAccess = parent; 21 | var start = propertyAccess.getStart(); 22 | var end = propertyAccess.dotToken.getStart(); 23 | var oldText = propertyAccess.getText().substr(0, end - start); 24 | var refactoring = { 25 | filePath: info.filePath, 26 | span: { 27 | start: start, 28 | length: propertyAccess.name.end - start, 29 | }, 30 | newText: "(" + oldText + " as ${1:any})${2:." + propertyAccess.name.getText() + "}${3}", 31 | isNewTextSnippet: true, 32 | }; 33 | return [refactoring]; 34 | } 35 | return []; 36 | }; 37 | return TypeAssertPropertyAccessToType; 38 | })(); 39 | exports.TypeAssertPropertyAccessToType = TypeAssertPropertyAccessToType; 40 | function getIdentifierName(errorText) { 41 | var match = /Property \'(\w+)\' does not exist on type \.*/.exec(errorText); 42 | if (!match) 43 | return; 44 | var identifierName = match[1]; 45 | return { identifierName: identifierName }; 46 | } 47 | -------------------------------------------------------------------------------- /lib/main/atom/onSaveHandler.ts: -------------------------------------------------------------------------------- 1 | import atomUtils = require("./atomUtils"); 2 | 3 | ///ts:import=atomConfig 4 | import atomConfig = require('./atomConfig'); ///ts:import:generated 5 | 6 | ///ts:import=parent 7 | import parent = require('../../worker/parent'); ///ts:import:generated 8 | 9 | import {errorView, show, panelView} from "./views/mainPanelView"; 10 | 11 | import {getFileStatus} from "./fileStatusCache"; 12 | 13 | ///ts:import=debugAtomTs 14 | import debugAtomTs = require('./debugAtomTs'); ///ts:import:generated 15 | 16 | export function handle(event: { filePath: string; editor: AtomCore.IEditor }) { 17 | // As a fall back to make sure we sync up in case of anything bad happening elsewhere. 18 | var textUpdated = parent.updateText({ filePath: event.filePath, text: event.editor.getText() }); 19 | 20 | // Refresh errors for file 21 | textUpdated.then(() => { 22 | // also invalidate linter 23 | atomUtils.triggerLinter(); 24 | 25 | parent.errorsForFile({ filePath: event.filePath }) 26 | .then((resp) => errorView.setErrors(event.filePath, resp.errors)); 27 | }) 28 | 29 | show(); 30 | 31 | // Compile on save 32 | parent.getProjectFileDetails({ filePath: event.filePath }).then(fileDetails => { 33 | if (fileDetails.project.compileOnSave 34 | && !fileDetails.project.compilerOptions.out 35 | && !fileDetails.project.buildOnSave) { 36 | 37 | textUpdated.then(() => parent.emitFile({ filePath: event.filePath })) 38 | .then((res) => { 39 | let status = getFileStatus(event.filePath); 40 | status.modified = false; 41 | 42 | // If there was a compilation error, the file differs from the one on the disk 43 | status.emitDiffers = res.emitError; 44 | panelView.updateFileStatus(event.filePath); 45 | errorView.showEmittedMessage(res); 46 | }); 47 | } 48 | 49 | if (fileDetails.project.buildOnSave) { 50 | // Trigger a build ;) 51 | atom.commands.dispatch( 52 | atom.views.getView(event.editor), 53 | 'typescript:build'); 54 | } 55 | 56 | }); 57 | } 58 | -------------------------------------------------------------------------------- /lib/main/atom/views/contextView.ts: -------------------------------------------------------------------------------- 1 | import sp = require('atom-space-pen-views'); 2 | import mainPanelView = require('./mainPanelView'); 3 | import * as semanticView from "./semanticView"; 4 | 5 | interface ContextViewItem { 6 | title: string; 7 | } 8 | 9 | var titles = { 10 | togglePanel: 'Toggle TypeScript Panel', 11 | tabErrors: 'Tab: Errors in Open Files', 12 | tabLastBuild: 'Tab: Last Build Output', 13 | tabReferences: 'Tab: Find References', 14 | fileSemantics: 'Toggle: File Semantics', 15 | } 16 | 17 | var items = Object.keys(titles).map(item=> { return { title: titles[item] } }); 18 | 19 | /** 20 | * https://github.com/atom/atom-space-pen-views 21 | */ 22 | export class ContextView extends sp.SelectListView { 23 | 24 | get $(): JQuery { 25 | return this; 26 | } 27 | 28 | public setItems(items: ContextViewItem[]) { super.setItems(items) } 29 | 30 | /** override */ 31 | viewForItem(item: ContextViewItem) { 32 | return `
  • ${item.title}
  • `; 33 | } 34 | 35 | /** override */ 36 | confirmed(item: ContextViewItem) { 37 | if (item.title == titles.togglePanel) { 38 | mainPanelView.panelView.toggle(); 39 | } 40 | if (item.title == titles.tabErrors) { 41 | mainPanelView.panelView.errorPanelSelected(); 42 | } 43 | if (item.title == titles.tabLastBuild) { 44 | mainPanelView.panelView.buildPanelSelected(); 45 | } 46 | if (item.title == titles.tabReferences) { 47 | mainPanelView.panelView.referencesPanelSelected(); 48 | } 49 | if (item.title == titles.fileSemantics){ 50 | semanticView.toggle(); 51 | } 52 | 53 | this.hide(); 54 | } 55 | 56 | getFilterKey() { return 'title'; } 57 | 58 | panel: AtomCore.Panel = null; 59 | show() { 60 | this.storeFocusedElement(); 61 | if (!this.panel) this.panel = atom.workspace.addModalPanel({ item: this }); 62 | this.panel.show() 63 | 64 | this.setItems(items); 65 | this.focusFilterEditor(); 66 | } 67 | hide() { 68 | this.panel.hide(); 69 | this.restoreFocus(); 70 | } 71 | 72 | cancelled() { 73 | this.hide(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /dist/main/lang/modules/astToText.js: -------------------------------------------------------------------------------- 1 | var astUtils_1 = require("../fixmyts/astUtils"); 2 | function astToText(srcFile) { 3 | var nodeIndex = 0; 4 | function nodeToNodeDisplay(node, depth) { 5 | var kind = astUtils_1.syntaxKindToString(node.kind); 6 | var children = []; 7 | ts.forEachChild(node, function (cNode) { 8 | var child = nodeToNodeDisplay(cNode, depth + 1); 9 | children.push(child); 10 | }); 11 | var ret = { 12 | kind: kind, 13 | children: children, 14 | pos: node.pos, 15 | end: node.end, 16 | depth: depth, 17 | nodeIndex: nodeIndex, 18 | rawJson: prettyJSONNoParent(node) 19 | }; 20 | nodeIndex++; 21 | return ret; 22 | } 23 | var root = nodeToNodeDisplay(srcFile, 0); 24 | return root; 25 | } 26 | exports.astToText = astToText; 27 | function astToTextFull(srcFile) { 28 | var nodeIndex = 0; 29 | function nodeToNodeDisplay(node, depth) { 30 | var kind = astUtils_1.syntaxKindToString(node.kind); 31 | var children = []; 32 | node.getChildren().forEach(function (cNode) { 33 | var child = nodeToNodeDisplay(cNode, depth + 1); 34 | children.push(child); 35 | }); 36 | var ret = { 37 | kind: kind, 38 | children: children, 39 | pos: node.pos, 40 | end: node.end, 41 | depth: depth, 42 | nodeIndex: nodeIndex, 43 | rawJson: prettyJSONNoParent(node) 44 | }; 45 | nodeIndex++; 46 | return ret; 47 | } 48 | var root = nodeToNodeDisplay(srcFile, 0); 49 | return root; 50 | } 51 | exports.astToTextFull = astToTextFull; 52 | function prettyJSONNoParent(object) { 53 | var cache = []; 54 | var value = JSON.stringify(object, function (key, value) { 55 | if (key == 'parent') { 56 | return; 57 | } 58 | if (typeof value === 'object' && value !== null) { 59 | if (cache.indexOf(value) !== -1) { 60 | return; 61 | } 62 | cache.push(value); 63 | } 64 | return value; 65 | }, 4); 66 | cache = null; 67 | return value; 68 | } 69 | -------------------------------------------------------------------------------- /docs/quickfix.md: -------------------------------------------------------------------------------- 1 | # Quick Fix 2 | Press the `TypeScript: Quick Fix` shortcut `alt+enter` at an error location to trigger quick fixes. Select the quick fix you want and press `enter` to commit e.g 3 | 4 | ## Add class and interface members 5 | 6 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/addClassMember.gif) 7 | 8 | ## Type assert 9 | Insert type assertions on property access for easier migration from JS code 10 | 11 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/typeAssertPropertyAccess.gif) 12 | 13 | 14 | ## Toggle quote characters 15 | 16 | Single to double, double to single 17 | 18 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/quotesToQuotes.gif) 19 | 20 | ## Quotes to template 21 | Convert strings to template strings to get rid of those `\` 22 | 23 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/quotesToTemplate.gif) 24 | 25 | ## String concate to template 26 | Convert string concatenations to a template string 27 | 28 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/stringConcatToTemplate.gif) 29 | 30 | ## Equals to Equals 31 | `==` and `!=` (because typing another `=` is hard) 32 | 33 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/equalsToEquals.gif) 34 | 35 | ## Wrap in read only property 36 | From constructor argument 37 | 38 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/quickfix/wrapInReadonlyProperty.gif) 39 | 40 | ## Import file 41 | If the file prefix matches 42 | 43 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/addImportStatement.gif) 44 | 45 | 46 | ## Single Line Comment To JsDoc 47 | JsDoc are associated with the next node. Single line comments are not. So this quickfix does the conversion for you 48 | 49 | ![](https://raw.githubusercontent.com/TypeStrong/atom-typescript-examples/master/screens/quickfix/singleLineCommentToJsDoc.gif) 50 | 51 | 52 | # Contributing 53 | 54 | We have some guidance on creating your own quickfixes [within our CONTRIBUTING.md](https://github.com/TypeStrong/atom-typescript/blob/master/CONTRIBUTING.md#quickfix). They are quite fun to write! -------------------------------------------------------------------------------- /dist/main/atom/commands/outputFileCommands.js: -------------------------------------------------------------------------------- 1 | var atomUtils = require("../atomUtils"); 2 | var parent = require("../../../worker/parent"); 3 | var child_process_1 = require("child_process"); 4 | var path = require("path"); 5 | function register() { 6 | atom.commands.add('atom-workspace', 'typescript:output-toggle', function (e) { 7 | if (!atomUtils.commandForTypeScript(e)) 8 | return; 9 | var query = atomUtils.getFilePath(); 10 | var previousActivePane = atom.workspace.getActivePane(); 11 | parent.getOutputJs(query).then(function (res) { 12 | if (!res.jsFilePath) { 13 | atom.notifications.addInfo('AtomTS: No emit for this file'); 14 | return; 15 | } 16 | else { 17 | var uri = res.jsFilePath.split("/").join(path.sep); 18 | var previewPane = atom.workspace.paneForURI(uri); 19 | if (previewPane) { 20 | previewPane.destroyItem(previewPane.itemForURI(uri)); 21 | } 22 | else { 23 | atom.workspace.open(res.jsFilePath, { split: "right" }).then(function () { 24 | previousActivePane.activate(); 25 | }); 26 | } 27 | } 28 | }); 29 | }); 30 | atom.commands.add('atom-workspace', 'typescript:output-file-execute-in-node', function (e) { 31 | if (!atomUtils.commandForTypeScript(e)) 32 | return; 33 | var query = atomUtils.getFilePath(); 34 | parent.getOutputJs(query).then(function (res) { 35 | if (!res.jsFilePath) { 36 | atom.notifications.addInfo('AtomTS: No emit for this file'); 37 | return; 38 | } 39 | else { 40 | var command = "node " + path.basename(res.jsFilePath); 41 | console.log(command); 42 | child_process_1.exec(command, { cwd: path.dirname(res.jsFilePath), env: { ATOM_SHELL_INTERNAL_RUN_AS_NODE: '1' } }, function (err, stdout, stderr) { 43 | console.log(stdout); 44 | if (stderr.toString().trim().length) { 45 | console.error(stderr); 46 | } 47 | }); 48 | } 49 | }); 50 | }); 51 | } 52 | exports.register = register; 53 | -------------------------------------------------------------------------------- /lib/main/lang/modules/moveFiles.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Gets the refactorings you would need if you move files around 3 | */ 4 | 5 | import {Refactoring} from "../fixmyts/quickFix"; 6 | import {getSourceFileImportsWithTextRange} from "../fixmyts/astUtils"; 7 | import * as path from "path"; 8 | import { 9 | removeExt, 10 | pathIsRelative, 11 | makeRelativePath 12 | } from "../../tsconfig/tsconfig"; 13 | import {consistentPath} from "../../utils/fsUtil"; 14 | 15 | /** 16 | * will return the refactorings for what needs to change in the source files if the old path becomes new path 17 | */ 18 | export function getRenameFilesRefactorings(program: ts.Program, oldDirectoryOrFile: string, newDirectoryOrFile: string): Refactoring[] { 19 | oldDirectoryOrFile = consistentPath(oldDirectoryOrFile); 20 | newDirectoryOrFile = consistentPath(newDirectoryOrFile); 21 | 22 | var oldFileNoExt = removeExt(oldDirectoryOrFile); 23 | var newFileNoExt = removeExt(newDirectoryOrFile); 24 | 25 | /** 26 | * Go through all the files in the program and find the ones that referece the "oldDirectoryOrFile" 27 | * The refactoring is to just find a relative path to the newDirectoryOrFile (just the contents of the string without quotes) 28 | */ 29 | 30 | var refactorings: Refactoring[] = []; 31 | 32 | var sourceFiles = program.getSourceFiles(); 33 | 34 | sourceFiles.forEach(sourceFile => { 35 | let imports = getSourceFileImportsWithTextRange(sourceFile) 36 | .filter((fileReference) => pathIsRelative(fileReference.text)) 37 | .map(ref=> { 38 | return { 39 | path: consistentPath(path.resolve(path.dirname(sourceFile.fileName), ref.text)), 40 | range: ref.range 41 | }; 42 | }) 43 | var matches = imports.filter(f=> f.path == oldFileNoExt); 44 | if (matches.length) { 45 | for (let match of matches) { 46 | refactorings.push({ 47 | filePath: sourceFile.fileName, 48 | span: { 49 | start: match.range.pos, 50 | length: match.range.end - match.range.pos 51 | }, 52 | newText: makeRelativePath(path.dirname(sourceFile.fileName), newFileNoExt) 53 | }); 54 | } 55 | } 56 | }); 57 | 58 | return refactorings; 59 | } 60 | -------------------------------------------------------------------------------- /lib/main/lang/fixmyts/quickFixes/typeAssertPropertyAccessToAny.ts: -------------------------------------------------------------------------------- 1 | import {QuickFix, QuickFixQueryInformation, Refactoring, CanProvideFixResponse} from "../quickFix"; 2 | import * as ast from "../astUtils"; 3 | 4 | 5 | export class TypeAssertPropertyAccessToAny implements QuickFix { 6 | key = TypeAssertPropertyAccessToAny.name; 7 | 8 | canProvideFix(info: QuickFixQueryInformation): CanProvideFixResponse { 9 | var relevantError = info.positionErrors.filter(x=> x.code == ts.Diagnostics.Property_0_does_not_exist_on_type_1.code)[0]; 10 | if (!relevantError) return; 11 | if (info.positionNode.kind !== ts.SyntaxKind.Identifier) return; 12 | 13 | var match = getIdentifierName(info.positionErrorMessages[0]); 14 | 15 | if (!match) return; 16 | 17 | var {identifierName} = match; 18 | return { display: `Assert "any" for property access "${identifierName}"` }; 19 | } 20 | 21 | provideFix(info: QuickFixQueryInformation): Refactoring[] { 22 | /** 23 | * We want the largest property access expressing `a.b.c` starting at the identifer `c` 24 | * Since this gets tokenized as `a.b` `.` `c` so its just the parent :) 25 | */ 26 | let parent = info.positionNode.parent; 27 | if (parent.kind == ts.SyntaxKind.PropertyAccessExpression) { 28 | let propertyAccess = parent; 29 | let start = propertyAccess.getStart(); 30 | let end = propertyAccess.dotToken.getStart(); 31 | 32 | let oldText = propertyAccess.getText().substr(0, end - start); 33 | 34 | let refactoring: Refactoring = { 35 | filePath: info.filePath, 36 | span: { 37 | start: start, 38 | length: end - start, 39 | }, 40 | newText: `(${oldText} as any)` 41 | }; 42 | 43 | return [refactoring]; 44 | } 45 | return []; 46 | } 47 | } 48 | 49 | function getIdentifierName(errorText: string) { 50 | // see https://github.com/Microsoft/TypeScript/blob/6637f49209ceb5ed719573998381eab010fa48c9/src/compiler/diagnosticMessages.json#L842 51 | var match = /Property \'(\w+)\' does not exist on type \.*/.exec(errorText); 52 | 53 | if (!match) return; 54 | 55 | var [, identifierName] = match; 56 | return { identifierName }; 57 | } 58 | -------------------------------------------------------------------------------- /lib/main/lang/core/project.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | import path = require('path'); 4 | import fs = require('fs'); 5 | import os = require('os'); 6 | 7 | export import languageServiceHost = require('./languageServiceHost2'); 8 | import tsconfig = require('../../tsconfig/tsconfig'); 9 | import utils = require('../utils'); 10 | import * as transformerRegistry from "../transformers/transformerRegistry"; 11 | 12 | /** 13 | * Wraps up `langaugeService` `languageServiceHost` and `projectFile` in a single package 14 | */ 15 | export class Project { 16 | public languageServiceHost: languageServiceHost.LanguageServiceHost; 17 | public languageService: ts.LanguageService; 18 | 19 | constructor(public projectFile: tsconfig.TypeScriptProjectFileDetails) { 20 | this.languageServiceHost = new languageServiceHost.LanguageServiceHost(projectFile); 21 | var transformerRegexes = transformerRegistry.getRegexes(); 22 | 23 | // Add all the files 24 | projectFile.project.files.forEach((file) => { 25 | if (tsconfig.endsWith(file, '.tst.ts')) { 26 | // initially add without transform sections. 27 | var rawContent = fs.readFileSync(tsconfig.removeExt(file), 'utf-8'); 28 | 29 | var withoutTransform = rawContent; 30 | transformerRegexes.forEach(transformer => { 31 | withoutTransform = withoutTransform.replace(transformer, '');; 32 | }); 33 | 34 | this.languageServiceHost.addScript(file, withoutTransform); 35 | // TODO: update with transform sections 36 | } 37 | else { 38 | this.languageServiceHost.addScript(file); 39 | } 40 | }); 41 | 42 | 43 | this.languageService = ts.createLanguageService(this.languageServiceHost, ts.createDocumentRegistry()); 44 | } 45 | 46 | /** all files except lib.d.ts */ 47 | public getProjectSourceFiles(): ts.SourceFile[] { 48 | var libFile = languageServiceHost.getDefaultLibFilePath(this.projectFile.project.compilerOptions); 49 | var files 50 | = this.languageService.getProgram().getSourceFiles().filter(x=> x.fileName !== libFile); 51 | return files; 52 | } 53 | 54 | public includesSourceFile(fileName: string) { 55 | return (this.getProjectSourceFiles().filter((f) => f.fileName === fileName).length === 1); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lib/main/atom/views/documentationView.ts: -------------------------------------------------------------------------------- 1 | import view = require('./view'); 2 | var $ = view.$; 3 | 4 | export class DocumentationView extends view.View { 5 | 6 | private header: JQuery; 7 | private documentation: JQuery; 8 | static content() { 9 | return this.div({ class: 'atom-ts-documentation padded top' }, 10 | () => this.div( // TODO: repeat for each documentation entry 11 | () => { 12 | this.h2({ outlet: 'header' }); 13 | this.p({ outlet: 'documentation' }); 14 | }) 15 | ); 16 | } 17 | 18 | 19 | private shown = false; 20 | show() { this.$.addClass('active'); this.shown = true; } 21 | hide() { this.$.removeClass('active'); this.shown = false; } 22 | toggle() { if (this.shown) { this.hide(); } else { this.show(); } } 23 | 24 | setContent(content: { display: string; documentation: string; filePath: string }) { 25 | this.header.html(content.display); 26 | content.documentation = content.documentation.replace(/(?:\r\n|\r|\n)/g, '
    '); 27 | this.documentation.html(content.documentation); 28 | } 29 | 30 | autoPosition() { 31 | var editor = atom.workspace.getActiveTextEditor(); 32 | var cursor = editor.getCursors()[0]; 33 | var cursorTop = cursor.getPixelRect().top - editor.getScrollTop(); 34 | var editorHeight = editor.getHeight(); 35 | 36 | if (editorHeight - cursorTop < 100) { 37 | this.$.removeClass('bottom'); 38 | this.$.addClass('top'); 39 | } 40 | else { 41 | this.$.removeClass('top'); 42 | this.$.addClass('bottom') 43 | } 44 | } 45 | } 46 | 47 | export var docView: DocumentationView; 48 | 49 | export function attach() { 50 | if (docView) return; 51 | docView = new DocumentationView({}); 52 | $(atom.views.getView(atom.workspace)).append(docView.$); 53 | // testDocumentationView(); 54 | } 55 | 56 | export function testDocumentationView() { 57 | docView.setContent({ 58 | display: "this is awesome", documentation: ` 59 | some docs 60 | over 61 | many 62 | many li 63 | 64 | lines 65 | long 66 | so 67 | long 68 | that 69 | it 70 | should 71 | 72 | start 73 | to 74 | scroll 75 | `, filePath: "some filepath" 76 | }); 77 | docView.show(); 78 | } 79 | -------------------------------------------------------------------------------- /lib/main/atom/editorSetup.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Setup all the stuff we need from an editor instance and clear on editor close 3 | */ 4 | import {debounce} from "../lang/utils"; 5 | import * as parent from "../../worker/parent"; 6 | import * as atomUtils from "./atomUtils"; 7 | import {isTransformerFile} from "../lang/transformers/transformer"; 8 | 9 | export function setupEditor(editor: AtomCore.IEditor) { 10 | 11 | // Quick fix decoration stuff 12 | var quickFixDecoration: AtomCore.Decoration = null; 13 | var quickFixMarker: any = null; 14 | function clearExistingQuickfixDecoration() { 15 | if (quickFixDecoration) { 16 | quickFixDecoration.destroy(); 17 | quickFixDecoration = null; 18 | } 19 | if (quickFixMarker) { 20 | quickFixMarker.destroy(); 21 | quickFixMarker = null; 22 | } 23 | } 24 | var queryForQuickFix = debounce((filePathPosition:{filePath:string;position:number}) => { 25 | parent.getQuickFixes(filePathPosition).then(res=> { 26 | clearExistingQuickfixDecoration(); 27 | if (res.fixes.length) { 28 | quickFixMarker = editor.markBufferRange(editor.getSelectedBufferRange()); 29 | quickFixDecoration = editor.decorateMarker(quickFixMarker, 30 | { type: "line-number", class: "quickfix" }); 31 | } 32 | }) 33 | }, 500); 34 | var cursorObserver = editor.onDidChangeCursorPosition(() => { 35 | try { 36 | // This line seems to throw an exception sometimes. 37 | // https://github.com/TypeStrong/atom-typescript/issues/325 38 | // https://github.com/TypeStrong/atom-typescript/issues/310 39 | let pathPos = atomUtils.getFilePathPosition(); 40 | 41 | // TODO: implement quickfix logic for transformed files 42 | if (isTransformerFile(pathPos.filePath)) { 43 | clearExistingQuickfixDecoration(); 44 | return; 45 | } 46 | 47 | queryForQuickFix(pathPos); 48 | } 49 | catch (ex) { 50 | clearExistingQuickfixDecoration(); 51 | } 52 | }); 53 | 54 | 55 | /** 56 | * On final dispose 57 | */ 58 | var destroyObserver = editor.onDidDestroy(() => { 59 | // Clear editor observers 60 | cursorObserver.dispose(); 61 | destroyObserver.dispose(); 62 | }); 63 | } 64 | -------------------------------------------------------------------------------- /dist/main/tsconfig/simpleValidator.js: -------------------------------------------------------------------------------- 1 | exports.types = { 2 | string: 'string', 3 | boolean: 'boolean', 4 | number: 'number' 5 | }; 6 | var SimpleValidator = (function () { 7 | function SimpleValidator(validationInfo) { 8 | var _this = this; 9 | this.validationInfo = validationInfo; 10 | this.potentialLowerCaseMatch = {}; 11 | Object.keys(validationInfo).forEach(function (k) { return _this.potentialLowerCaseMatch[k.toLowerCase()] = k; }); 12 | } 13 | SimpleValidator.prototype.validate = function (config) { 14 | var _this = this; 15 | var keys = Object.keys(config); 16 | var errors = { invalidValues: [], extraKeys: [], errorMessage: '' }; 17 | keys.forEach(function (k) { 18 | if (!_this.validationInfo[k]) { 19 | if (_this.potentialLowerCaseMatch[k]) { 20 | errors.extraKeys.push("Key: '" + k + "' is a potential lower case match for '" + _this.potentialLowerCaseMatch[k] + "'. Fix the casing."); 21 | } 22 | else { 23 | errors.extraKeys.push("Unknown Option: " + k); 24 | } 25 | } 26 | else { 27 | var validationInfo = _this.validationInfo[k]; 28 | var value = config[k]; 29 | if (validationInfo.validValues && validationInfo.validValues.length) { 30 | var validValues = validationInfo.validValues; 31 | if (!validValues.some(function (valid) { return valid.toLowerCase() === value.toLowerCase(); })) { 32 | errors.invalidValues.push("Key: '" + k + "' has an invalid value: " + value); 33 | } 34 | } 35 | if (validationInfo.type && typeof value !== validationInfo.type) { 36 | errors.invalidValues.push("Key: '" + k + "' has an invalid type: " + typeof value); 37 | } 38 | } 39 | }); 40 | var total = errors.invalidValues.concat(errors.extraKeys); 41 | if (total.length) { 42 | errors.errorMessage = total.join("\n"); 43 | } 44 | return errors; 45 | }; 46 | return SimpleValidator; 47 | })(); 48 | exports.SimpleValidator = SimpleValidator; 49 | function createMap(arr) { 50 | return arr.reduce(function (result, key) { 51 | result[key] = true; 52 | return result; 53 | }, {}); 54 | } 55 | exports.createMap = createMap; 56 | -------------------------------------------------------------------------------- /dist/main/atom/views/fileSymbolsView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var sp = require('atom-space-pen-views'); 7 | var atomUtils = require("../atomUtils"); 8 | var FileSymbolsView = (function (_super) { 9 | __extends(FileSymbolsView, _super); 10 | function FileSymbolsView() { 11 | _super.apply(this, arguments); 12 | this.panel = null; 13 | } 14 | Object.defineProperty(FileSymbolsView.prototype, "$", { 15 | get: function () { 16 | return this; 17 | }, 18 | enumerable: true, 19 | configurable: true 20 | }); 21 | FileSymbolsView.prototype.setNavBarItems = function (tsItems, filePath) { 22 | var items = tsItems; 23 | this.filePath = filePath; 24 | _super.prototype.setItems.call(this, items); 25 | }; 26 | FileSymbolsView.prototype.viewForItem = function (item) { 27 | return "\n
  • \n
    " + (Array(item.indent * 2).join(' ') + (item.indent ? "\u221F " : '') + item.text) + "
    \n
    " + item.kind + "
    \n
    line: " + (item.position.line + 1) + "
    \n
  • \n "; 28 | }; 29 | FileSymbolsView.prototype.confirmed = function (item) { 30 | atom.workspace.open(this.filePath, { 31 | initialLine: item.position.line, 32 | initialColumn: item.position.col 33 | }); 34 | this.hide(); 35 | }; 36 | FileSymbolsView.prototype.getFilterKey = function () { return 'text'; }; 37 | FileSymbolsView.prototype.show = function () { 38 | this.storeFocusedElement(); 39 | if (!this.panel) 40 | this.panel = atom.workspace.addModalPanel({ item: this }); 41 | this.panel.show(); 42 | this.focusFilterEditor(); 43 | }; 44 | FileSymbolsView.prototype.hide = function () { 45 | this.panel.hide(); 46 | this.restoreFocus(); 47 | }; 48 | FileSymbolsView.prototype.cancelled = function () { 49 | this.hide(); 50 | }; 51 | return FileSymbolsView; 52 | })(sp.SelectListView); 53 | exports.FileSymbolsView = FileSymbolsView; 54 | -------------------------------------------------------------------------------- /lib/main/atom/commands/outputFileCommands.ts: -------------------------------------------------------------------------------- 1 | import * as atomUtils from "../atomUtils"; 2 | import * as parent from "../../../worker/parent"; 3 | import {spawn, exec} from "child_process"; 4 | import * as path from "path"; 5 | 6 | /** 7 | * Command related to output files 8 | */ 9 | export function register() { 10 | atom.commands.add('atom-workspace', 'typescript:output-toggle', (e) => { 11 | if (!atomUtils.commandForTypeScript(e)) return; 12 | 13 | var query = atomUtils.getFilePath(); 14 | var previousActivePane = atom.workspace.getActivePane() 15 | parent.getOutputJs(query).then(res=> { 16 | if (!res.jsFilePath) { 17 | atom.notifications.addInfo('AtomTS: No emit for this file'); 18 | return; 19 | } 20 | else { 21 | // pane for uri needs file system path so: 22 | var uri = res.jsFilePath.split("/").join(path.sep); 23 | let previewPane = atom.workspace.paneForURI(uri); 24 | if (previewPane) { 25 | previewPane.destroyItem(previewPane.itemForURI(uri)) 26 | } 27 | else { 28 | atom.workspace.open(res.jsFilePath, { split: "right" }).then(() => { 29 | previousActivePane.activate(); 30 | }); 31 | } 32 | } 33 | }); 34 | }); 35 | 36 | atom.commands.add('atom-workspace', 'typescript:output-file-execute-in-node', (e) => { 37 | if (!atomUtils.commandForTypeScript(e)) return; 38 | 39 | var query = atomUtils.getFilePath(); 40 | parent.getOutputJs(query).then(res=> { 41 | if (!res.jsFilePath) { 42 | atom.notifications.addInfo('AtomTS: No emit for this file'); 43 | return; 44 | } 45 | else { 46 | // spawn('cmd', ['/C', 'start ' + "node " + res.output.outputFiles[0].name]); 47 | var command = `node ${path.basename(res.jsFilePath) }`; 48 | console.log(command); 49 | 50 | exec(command, { cwd: path.dirname(res.jsFilePath), env: { ATOM_SHELL_INTERNAL_RUN_AS_NODE: '1' } }, (err, stdout, stderr) => { 51 | console.log(stdout); 52 | if (stderr.toString().trim().length) { 53 | console.error(stderr); 54 | } 55 | }); 56 | } 57 | }); 58 | }); 59 | } 60 | -------------------------------------------------------------------------------- /lib/main/atom/views/simpleSelectionView.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A functional form of the SelectListView 3 | * Only one of these bad boys is allowed on the screen at one time 4 | */ 5 | 6 | export interface SelectListViewOptions { 7 | items: T[]; 8 | /** everything except the `li` which is required */ 9 | viewForItem: (item: T) => string | JQuery; 10 | 11 | /** some property on item */ 12 | filterKey: string; 13 | confirmed: (item: T) => any; 14 | } 15 | 16 | var singleton: SimpleSelectListView; 17 | 18 | export function simpleSelectionView(options: SelectListViewOptions): SimpleSelectListView { 19 | if (!singleton) singleton = new SimpleSelectListView(options); 20 | else { singleton.options = options; } 21 | 22 | singleton.setItems(); 23 | singleton.show(); 24 | return singleton; 25 | } 26 | 27 | /** 28 | * Various Utility section 29 | */ 30 | 31 | import sp = require('atom-space-pen-views'); 32 | import $ = sp.$; 33 | import * as atomUtils from "../atomUtils"; 34 | 35 | export class SimpleSelectListView extends sp.SelectListView { 36 | 37 | constructor(public options: SelectListViewOptions) { 38 | super(); 39 | } 40 | 41 | get $(): JQuery { 42 | return this; 43 | } 44 | 45 | public setItems() { 46 | super.setItems(this.options.items) 47 | } 48 | 49 | /** override */ 50 | viewForItem(item: T): any { 51 | var view = this.options.viewForItem(item); 52 | if (typeof view === "string") { 53 | return `
  • 54 | ${view} 55 |
  • `; 56 | } 57 | else { 58 | return $('
  • ').append(view); 59 | }; 60 | } 61 | 62 | /** override */ 63 | confirmed(item: T) { 64 | this.options.confirmed(item); 65 | this.hide(); 66 | } 67 | 68 | /** override */ 69 | getFilterKey() { 70 | return this.options.filterKey; 71 | } 72 | 73 | panel: AtomCore.Panel = null; 74 | show() { 75 | this.storeFocusedElement(); 76 | if (!this.panel) this.panel = atom.workspace.addModalPanel({ item: this }); 77 | this.panel.show() 78 | 79 | this.focusFilterEditor(); 80 | // debugger; // DEBUG: the UI in the inspector so that it doesn't change on you 81 | } 82 | hide() { 83 | this.panel.hide(); 84 | this.restoreFocus(); 85 | } 86 | 87 | cancelled() { 88 | this.hide(); 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /lib/main/lang/fixmyts/quickFixes/typeAssertPropertyAccessToType.ts: -------------------------------------------------------------------------------- 1 | import {QuickFix, QuickFixQueryInformation, Refactoring, CanProvideFixResponse} from "../quickFix"; 2 | import * as ast from "../astUtils"; 3 | 4 | 5 | export class TypeAssertPropertyAccessToType implements QuickFix { 6 | key = TypeAssertPropertyAccessToType.name; 7 | 8 | canProvideFix(info: QuickFixQueryInformation): CanProvideFixResponse { 9 | var relevantError = info.positionErrors.filter(x=> x.code == ts.Diagnostics.Property_0_does_not_exist_on_type_1.code)[0]; 10 | if (!relevantError) return; 11 | if (info.positionNode.kind !== ts.SyntaxKind.Identifier) return; 12 | 13 | var match = getIdentifierName(info.positionErrorMessages[0]); 14 | 15 | if (!match) return; 16 | 17 | var {identifierName} = match; 18 | return {display: `Assert for property access "${identifierName}"`, isNewTextSnippet: true}; 19 | } 20 | 21 | provideFix(info: QuickFixQueryInformation): Refactoring[] { 22 | /** 23 | * We want the largest property access expressing `a.b.c` starting at the identifer `c` 24 | * Since this gets tokenized as `a.b` `.` `c` so its just the parent :) 25 | */ 26 | let parent = info.positionNode.parent; 27 | if (parent.kind == ts.SyntaxKind.PropertyAccessExpression) { 28 | let propertyAccess = parent; 29 | let start = propertyAccess.getStart(); 30 | let end = propertyAccess.dotToken.getStart(); 31 | 32 | let oldText = propertyAccess.getText().substr(0, end - start); 33 | 34 | let refactoring: Refactoring = { 35 | filePath: info.filePath, 36 | span: { 37 | start: start, 38 | length: propertyAccess.name.end - start, 39 | }, 40 | newText: `(${oldText} as \${1:any})\${2:.${propertyAccess.name.getText()}}\${3}`, 41 | isNewTextSnippet: true, 42 | }; 43 | 44 | return [refactoring]; 45 | } 46 | return []; 47 | } 48 | } 49 | 50 | function getIdentifierName(errorText: string) { 51 | // see https://github.com/Microsoft/TypeScript/blob/6637f49209ceb5ed719573998381eab010fa48c9/src/compiler/diagnosticMessages.json#L842 52 | var match = /Property \'(\w+)\' does not exist on type \.*/.exec(errorText); 53 | 54 | if (!match) return; 55 | 56 | var [, identifierName] = match; 57 | return { identifierName }; 58 | } 59 | -------------------------------------------------------------------------------- /lib/main/atom/buildView.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | ///ts:import=utils 4 | import utils = require('../lang/utils'); ///ts:import:generated 5 | ///ts:import=project 6 | import project = require('../lang/core/project'); ///ts:import:generated 7 | 8 | import os = require('os') 9 | 10 | import mainPanelView = require('./views/mainPanelView'); 11 | import lineMessageView = require('./views/lineMessageView'); 12 | import gotoHistory = require('./gotoHistory'); 13 | 14 | function getTitle(errorCount: number): string { 15 | var title = ' TypeScript Build'; 16 | if (errorCount > 0) { 17 | title = title + ` ( 18 | ${errorCount} 19 | error${errorCount === 1 ? "" : "s"} 20 | )`; 21 | } 22 | return title; 23 | } 24 | 25 | 26 | export function setBuildOutput(buildOutput: BuildOutput) { 27 | 28 | mainPanelView.panelView.clearBuild(); 29 | 30 | if (buildOutput.counts.errors) { 31 | mainPanelView.panelView.setBuildPanelCount(buildOutput.counts.errors); 32 | } 33 | else { 34 | mainPanelView.panelView.setBuildPanelCount(0); 35 | } 36 | 37 | // Update the errors list for goto history 38 | gotoHistory.buildOutput.members = []; 39 | 40 | buildOutput.outputs.forEach(output => { 41 | if (output.success) { 42 | return; 43 | } 44 | output.errors.forEach(error => { 45 | mainPanelView.panelView.addBuild(new lineMessageView.LineMessageView({ 46 | goToLine: (filePath, line, col) => gotoHistory.gotoLine(filePath, line, col, gotoHistory.buildOutput), 47 | message: error.message, 48 | line: error.startPos.line + 1, 49 | col: error.startPos.col, 50 | file: error.filePath, 51 | preview: error.preview 52 | })); 53 | // Update the errors list for goto history 54 | gotoHistory.buildOutput.members.push({ filePath: error.filePath, line: error.startPos.line + 1, col: error.startPos.col }); 55 | }); 56 | }); 57 | 58 | if (!buildOutput.counts.errors) { 59 | atom.notifications.addSuccess("Build success"); 60 | } 61 | else if (buildOutput.counts.emitErrors) { 62 | atom.notifications.addError("Emits errors: " + buildOutput.counts.emitErrors + " files."); 63 | } else { 64 | atom.notifications.addWarning('Compile failed but emit succeeded'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /dist/main/atom/gotoHistory.js: -------------------------------------------------------------------------------- 1 | exports.errorsInOpenFiles = { members: [] }; 2 | exports.buildOutput = { members: [] }; 3 | exports.referencesOutput = { members: [] }; 4 | exports.activeList = exports.errorsInOpenFiles; 5 | function gotoLine(filePath, line, col, list) { 6 | var activeFile, activeEditor = atom.workspace.getActiveTextEditor(); 7 | if (activeEditor !== undefined && activeEditor !== null) { 8 | activeFile = activeEditor.getPath(); 9 | } 10 | if (filePath !== activeFile) { 11 | atom.workspace.open(filePath, { 12 | initialLine: line - 1, 13 | initialColumn: col 14 | }); 15 | } 16 | else { 17 | atom.workspace.getActiveTextEditor().cursors[0].setBufferPosition([line - 1, col]); 18 | } 19 | list.lastPosition = { filePath: filePath, line: line, col: col }; 20 | } 21 | exports.gotoLine = gotoLine; 22 | function findCurrentIndexInList() { 23 | if (!exports.activeList.members.length) { 24 | atom.notifications.addInfo('AtomTS: no go-to members in active list'); 25 | return -1; 26 | } 27 | if (!exports.activeList.lastPosition) 28 | return 0; 29 | var lastPosition = exports.activeList.lastPosition; 30 | var index = indexOf(exports.activeList.members, function (item) { return item.filePath == lastPosition.filePath && item.line == lastPosition.line; }); 31 | if (index == -1) { 32 | return 0; 33 | } 34 | return index; 35 | } 36 | function gotoNext() { 37 | var currentIndex = findCurrentIndexInList(); 38 | if (currentIndex == -1) 39 | return; 40 | var nextIndex = currentIndex + 1; 41 | if (nextIndex == exports.activeList.members.length) { 42 | nextIndex = 0; 43 | } 44 | var next = exports.activeList.members[nextIndex]; 45 | gotoLine(next.filePath, next.line, next.col, exports.activeList); 46 | } 47 | exports.gotoNext = gotoNext; 48 | function gotoPrevious() { 49 | var currentIndex = findCurrentIndexInList(); 50 | if (currentIndex == -1) 51 | return; 52 | var previousIndex = currentIndex - 1; 53 | if (previousIndex == -1) { 54 | previousIndex = exports.activeList.members.length - 1; 55 | } 56 | var previous = exports.activeList.members[previousIndex]; 57 | gotoLine(previous.filePath, previous.line, previous.col, exports.activeList); 58 | } 59 | exports.gotoPrevious = gotoPrevious; 60 | function indexOf(items, filter) { 61 | for (var i = 0; i < items.length; i++) { 62 | if (filter(items[i])) { 63 | return i; 64 | } 65 | } 66 | return -1; 67 | } 68 | -------------------------------------------------------------------------------- /dist/main/atom/views/rView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var atomUtils_1 = require("../atomUtils"); 7 | var sp = require("atom-space-pen-views"); 8 | var React = require('react'); 9 | var MyComponent = (function (_super) { 10 | __extends(MyComponent, _super); 11 | function MyComponent(props) { 12 | var _this = this; 13 | _super.call(this, props); 14 | this.state = { count: 0 }; 15 | this.stop = function () { 16 | clearInterval(_this.interval); 17 | }; 18 | } 19 | MyComponent.prototype.componentDidMount = function () { 20 | var _this = this; 21 | this.interval = setInterval(function () { 22 | _this.setState({ count: _this.state.count + 1 }); 23 | }); 24 | }; 25 | MyComponent.prototype.render = function () { 26 | return React.createElement("div", {"onClick": this.stop}, "This is a test: ", this.state.count); 27 | }; 28 | MyComponent.defaultProps = { count: 0 }; 29 | return MyComponent; 30 | })(React.Component); 31 | var RView = (function (_super) { 32 | __extends(RView, _super); 33 | function RView(config) { 34 | var _this = this; 35 | _super.call(this); 36 | this.config = config; 37 | this.getURI = function () { return atomUtils_1.uriForPath(_this.constructor.protocol, _this.config.filePath); }; 38 | this.getTitle = function () { return _this.config.title; }; 39 | this.getIconName = function () { return _this.config.icon; }; 40 | React.render(React.createElement(MyComponent, {}), this.rootDomElement); 41 | } 42 | Object.defineProperty(RView.prototype, "rootDomElement", { 43 | get: function () { 44 | return this.mainContent[0]; 45 | }, 46 | enumerable: true, 47 | configurable: true 48 | }); 49 | RView.content = function () { 50 | var _this = this; 51 | return this.div({ class: 'atomts atomts-r-view native-key-bindings' }, function () { 52 | _this.div({ outlet: 'mainContent layout' }); 53 | }); 54 | }; 55 | Object.defineProperty(RView.prototype, "$", { 56 | get: function () { return this; }, 57 | enumerable: true, 58 | configurable: true 59 | }); 60 | RView.protocol = 'atomtsview:'; 61 | return RView; 62 | })(sp.ScrollView); 63 | exports.RView = RView; 64 | -------------------------------------------------------------------------------- /lib/main/lang/fixmyts/quickFix.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interfaces for quick fixes 3 | */ 4 | import project = require("../core/project"); 5 | 6 | 7 | 8 | export interface Refactoring extends ts.TextChange { 9 | filePath: string; 10 | 11 | /** If you want to insert a snippet. Be careful that you shouldn't return more than one refatoring if you want to use this */ 12 | isNewTextSnippet?: boolean; 13 | } 14 | 15 | 16 | /** Note this interface has a few redundant stuff. This is intentional to precompute once */ 17 | export interface QuickFixQueryInformation { 18 | project: project.Project; 19 | service: ts.LanguageService; 20 | program: ts.Program; 21 | typeChecker: ts.TypeChecker; 22 | sourceFile: ts.SourceFile; 23 | sourceFileText: string; 24 | fileErrors: ts.Diagnostic[]; 25 | positionErrors: ts.Diagnostic[]; 26 | positionErrorMessages: string[]; 27 | position: number; 28 | positionNode: ts.Node; 29 | filePath: string; 30 | 31 | /** 32 | * Either the previous or the current. 33 | * This needs more thinking e.g. 'rename' already does the right thing. See how it is implemented 34 | */ 35 | oneOfPositionNodesOfType?(kind: ts.SyntaxKind): boolean; 36 | } 37 | 38 | export interface CanProvideFixResponse { 39 | /** 40 | * Return '' if you can't provide a fix 41 | * return 'Some string to display' if you can provide a string 42 | */ 43 | display: string; 44 | isNewTextSnippet?: boolean; 45 | } 46 | 47 | export interface QuickFix { 48 | /** Some unique key. Classname works best ;) */ 49 | key: string; 50 | 51 | canProvideFix(info: QuickFixQueryInformation): CanProvideFixResponse; 52 | 53 | provideFix(info: QuickFixQueryInformation): Refactoring[]; 54 | } 55 | 56 | 57 | /** You don't need to create this manually. Just use the util function */ 58 | export interface RefactoringsByFilePath { 59 | [filePath: string]: Refactoring[]; 60 | } 61 | 62 | /** Utility method. Reason is we want to transact by file path */ 63 | export function getRefactoringsByFilePath(refactorings: Refactoring[]) { 64 | var loc: RefactoringsByFilePath = {}; 65 | for (let refac of refactorings) { 66 | if (!loc[refac.filePath]) loc[refac.filePath] = []; 67 | loc[refac.filePath].push(refac); 68 | } 69 | 70 | // sort each of these in descending by start location 71 | for (let filePath in loc) { 72 | let refactorings = loc[filePath]; 73 | refactorings.sort((a: Refactoring, b: Refactoring) => { 74 | return (b.span.start - a.span.start); 75 | }); 76 | } 77 | 78 | return loc; 79 | } 80 | -------------------------------------------------------------------------------- /dist/main/atom/views/simpleSelectionView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var singleton; 7 | function simpleSelectionView(options) { 8 | if (!singleton) 9 | singleton = new SimpleSelectListView(options); 10 | else { 11 | singleton.options = options; 12 | } 13 | singleton.setItems(); 14 | singleton.show(); 15 | return singleton; 16 | } 17 | exports.simpleSelectionView = simpleSelectionView; 18 | var sp = require('atom-space-pen-views'); 19 | var $ = sp.$; 20 | var SimpleSelectListView = (function (_super) { 21 | __extends(SimpleSelectListView, _super); 22 | function SimpleSelectListView(options) { 23 | _super.call(this); 24 | this.options = options; 25 | this.panel = null; 26 | } 27 | Object.defineProperty(SimpleSelectListView.prototype, "$", { 28 | get: function () { 29 | return this; 30 | }, 31 | enumerable: true, 32 | configurable: true 33 | }); 34 | SimpleSelectListView.prototype.setItems = function () { 35 | _super.prototype.setItems.call(this, this.options.items); 36 | }; 37 | SimpleSelectListView.prototype.viewForItem = function (item) { 38 | var view = this.options.viewForItem(item); 39 | if (typeof view === "string") { 40 | return "
  • \n " + view + "\n
  • "; 41 | } 42 | else { 43 | return $('
  • ').append(view); 44 | } 45 | ; 46 | }; 47 | SimpleSelectListView.prototype.confirmed = function (item) { 48 | this.options.confirmed(item); 49 | this.hide(); 50 | }; 51 | SimpleSelectListView.prototype.getFilterKey = function () { 52 | return this.options.filterKey; 53 | }; 54 | SimpleSelectListView.prototype.show = function () { 55 | this.storeFocusedElement(); 56 | if (!this.panel) 57 | this.panel = atom.workspace.addModalPanel({ item: this }); 58 | this.panel.show(); 59 | this.focusFilterEditor(); 60 | }; 61 | SimpleSelectListView.prototype.hide = function () { 62 | this.panel.hide(); 63 | this.restoreFocus(); 64 | }; 65 | SimpleSelectListView.prototype.cancelled = function () { 66 | this.hide(); 67 | }; 68 | return SimpleSelectListView; 69 | })(sp.SelectListView); 70 | exports.SimpleSelectListView = SimpleSelectListView; 71 | -------------------------------------------------------------------------------- /dist/main/atom/views/lineMessageView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var view = require('./view'); 7 | var $ = view.$; 8 | var LineMessageView = (function (_super) { 9 | __extends(LineMessageView, _super); 10 | function LineMessageView() { 11 | _super.apply(this, arguments); 12 | } 13 | LineMessageView.content = function () { 14 | var _this = this; 15 | return this.div({ 16 | class: 'line-message' 17 | }, function () { 18 | _this.div({ 19 | class: 'text-subtle inline-block', 20 | outlet: 'position', 21 | click: 'goToLine', 22 | style: 'cursor: pointer;' 23 | }); 24 | _this.div({ 25 | class: 'message inline-block', 26 | outlet: 'contents' 27 | }); 28 | _this.pre({ 29 | class: 'preview', 30 | outlet: 'code', 31 | click: 'goToLine', 32 | style: 'cursor: pointer;' 33 | }); 34 | }); 35 | }; 36 | LineMessageView.prototype.init = function () { 37 | var message = 'at line ' + this.options.line; 38 | if (this.options.file !== undefined) { 39 | message += ', file ' + this.options.file; 40 | } 41 | this.position.text(message); 42 | this.contents.text(this.options.message); 43 | if (this.options.preview) { 44 | this.code.text(this.options.preview); 45 | } 46 | else { 47 | this.code.remove(); 48 | } 49 | }; 50 | LineMessageView.prototype.goToLine = function () { 51 | this.options.goToLine(this.options.file, this.options.line, this.options.col); 52 | }; 53 | LineMessageView.prototype.getSummary = function () { 54 | var pos = this.options.line.toString(); 55 | if (this.options.file !== undefined) { 56 | pos += ', ' + this.options.file; 57 | } 58 | return { 59 | summary: pos + ' ' + this.options.message, 60 | rawSummary: true, 61 | handler: function (element) { 62 | $(element) 63 | .css('cursor', 'pointer') 64 | .click(this.goToLine.bind(this)); 65 | }.bind(this) 66 | }; 67 | }; 68 | return LineMessageView; 69 | })(view.View); 70 | exports.LineMessageView = LineMessageView; 71 | -------------------------------------------------------------------------------- /dist/main/lang/fixmyts/quickFixes/addImportStatement.js: -------------------------------------------------------------------------------- 1 | var os_1 = require("os"); 2 | var displayPartsToString = ts.displayPartsToString, typeToDisplayParts = ts.typeToDisplayParts; 3 | var getPathCompletions_1 = require("../../modules/getPathCompletions"); 4 | function getIdentifierAndFileNames(error, project) { 5 | var errorText = error.messageText; 6 | if (typeof errorText !== 'string') { 7 | return undefined; 8 | } 9 | ; 10 | var match = errorText.match(/Cannot find name \'(\w+)\'./); 11 | if (!match) 12 | return; 13 | var identifierName = match[1]; 14 | var files = getPathCompletions_1.getPathCompletions({ 15 | project: project, 16 | filePath: error.file.fileName, 17 | prefix: identifierName, 18 | includeExternalModules: false 19 | }).files; 20 | var file = files.length > 0 ? files[0].relativePath : undefined; 21 | var basename = files.length > 0 ? files[0].name : undefined; 22 | return { identifierName: identifierName, file: file, basename: basename }; 23 | } 24 | var AddImportStatement = (function () { 25 | function AddImportStatement() { 26 | this.key = AddImportStatement.name; 27 | } 28 | AddImportStatement.prototype.canProvideFix = function (info) { 29 | var relevantError = info.positionErrors.filter(function (x) { return x.code == 2304; })[0]; 30 | if (!relevantError) 31 | return; 32 | if (info.positionNode.kind !== ts.SyntaxKind.Identifier) 33 | return; 34 | var matches = getIdentifierAndFileNames(relevantError, info.project); 35 | if (!matches) 36 | return; 37 | var identifierName = matches.identifierName, file = matches.file; 38 | return file ? { display: "import " + identifierName + " = require(\"" + file + "\")" } : undefined; 39 | }; 40 | AddImportStatement.prototype.provideFix = function (info) { 41 | var relevantError = info.positionErrors.filter(function (x) { return x.code == 2304; })[0]; 42 | var identifier = info.positionNode; 43 | var identifierName = identifier.text; 44 | var fileNameforFix = getIdentifierAndFileNames(relevantError, info.project); 45 | var refactorings = [{ 46 | span: { 47 | start: 0, 48 | length: 0 49 | }, 50 | newText: "import " + identifierName + " = require(\"" + fileNameforFix.file + "\");" + os_1.EOL, 51 | filePath: info.sourceFile.fileName 52 | }]; 53 | return refactorings; 54 | }; 55 | return AddImportStatement; 56 | })(); 57 | exports.AddImportStatement = AddImportStatement; 58 | -------------------------------------------------------------------------------- /lib/typings/pathwatcher/pathwatcher.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for pathwatcher 2 | // Project: https://github.com/atom/node-pathwatcher 3 | // Definitions by: vvakame 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | /// 8 | 9 | declare module PathWatcher { 10 | interface IFileStatic { 11 | new (path:string, symlink?:boolean):IFile; 12 | } 13 | 14 | interface IFile { 15 | realPath:string; 16 | path:string; 17 | symlink:boolean; 18 | cachedContents:string; 19 | digest:string; 20 | 21 | handleEventSubscriptions():void; 22 | setPath(path:string):void; 23 | getPath():string; 24 | getRealPathSync():string; 25 | getBaseName():string; 26 | write(text:string):void; 27 | readSync(flushCache:boolean):string; 28 | read(flushCache?:boolean):Q.Promise; 29 | exists():boolean; 30 | setDigest(contents:string):void; 31 | getDigest():string; 32 | writeFileWithPrivilegeEscalationSync (filePath:string, text:string):void; 33 | handleNativeChangeEvent(eventType:string, eventPath:string):void; 34 | detectResurrectionAfterDelay():void; 35 | detectResurrection():void; 36 | subscribeToNativeChangeEvents():void; 37 | unsubscribeFromNativeChangeEvents():void; 38 | } 39 | 40 | interface IDirectoryStatic { 41 | new (path:string, symlink?:boolean):IDirectory; 42 | } 43 | 44 | interface IDirectory { 45 | realPath:string; 46 | path:string; 47 | symlink:boolean; 48 | 49 | getBaseName():string; 50 | getPath():void; 51 | getRealPathSync():string; 52 | contains(pathToCheck:string):boolean; 53 | relativize(fullPath:string):string; 54 | getEntriesSync():any[]; // return type are {File | Directory}[] 55 | getEntries(callback:Function):void; 56 | subscribeToNativeChangeEvents():void; 57 | unsubscribeFromNativeChangeEvents():void; 58 | isPathPrefixOf(prefix:string, fullPath:string):boolean; 59 | } 60 | } 61 | 62 | declare module "pathwatcher" { 63 | 64 | import events = require("events"); 65 | 66 | interface IHandleWatcher extends events.EventEmitter { 67 | onEvent(event:any, filePath:any, oldFilePath:any):any; 68 | start():void; 69 | closeIfNoListener():void; 70 | close():void; 71 | } 72 | 73 | interface IPathWatcher { 74 | isWatchingParent:boolean; 75 | path:any; 76 | handleWatcher:IHandleWatcher; 77 | 78 | close():void; 79 | } 80 | 81 | function watch(path:string, callback:Function):IPathWatcher; 82 | 83 | function closeAllWatchers():void; 84 | 85 | function getWatchedPaths():string[]; 86 | 87 | var File:PathWatcher.IFileStatic; 88 | var Directory:PathWatcher.IDirectoryStatic; 89 | } 90 | -------------------------------------------------------------------------------- /dist/main/lang/fixmyts/quickFixes/implementInterface.js: -------------------------------------------------------------------------------- 1 | var ast = require("../astUtils"); 2 | var os_1 = require("os"); 3 | function getClassAndInterfaceName(error) { 4 | var errorText = ts.flattenDiagnosticMessageText(error.messageText, os_1.EOL); 5 | var match = errorText.match(/Class \'(\w+)\' incorrectly implements interface \'(\w+)\'./); 6 | if (!match || match.length !== 3) 7 | return; 8 | var className = match[1], interfaceName = match[2]; 9 | return { className: className, interfaceName: interfaceName }; 10 | } 11 | var ImplementInterface = (function () { 12 | function ImplementInterface() { 13 | this.key = ImplementInterface.name; 14 | } 15 | ImplementInterface.prototype.canProvideFix = function (info) { 16 | var relevantError = info.positionErrors.filter(function (x) { return x.code == ts.Diagnostics.Class_0_incorrectly_implements_interface_1.code; })[0]; 17 | if (!relevantError) 18 | return; 19 | if (info.positionNode.kind !== ts.SyntaxKind.Identifier) 20 | return; 21 | var match = getClassAndInterfaceName(relevantError); 22 | if (!match) 23 | return; 24 | var className = match.className, interfaceName = match.interfaceName; 25 | return { display: "Implement members of " + interfaceName + " in " + className }; 26 | }; 27 | ImplementInterface.prototype.provideFix = function (info) { 28 | var relevantError = info.positionErrors.filter(function (x) { return x.code == ts.Diagnostics.Class_0_incorrectly_implements_interface_1.code; })[0]; 29 | if (!relevantError) 30 | return; 31 | if (info.positionNode.kind !== ts.SyntaxKind.Identifier) 32 | return; 33 | var match = getClassAndInterfaceName(relevantError); 34 | var className = match.className, interfaceName = match.interfaceName; 35 | var interfaceTarget = ast.getNodeByKindAndName(info.program, ts.SyntaxKind.InterfaceDeclaration, className); 36 | var classTarget = ast.getNodeByKindAndName(info.program, ts.SyntaxKind.ClassDeclaration, className); 37 | var braces = classTarget.getChildren().filter(function (x) { return x.kind == ts.SyntaxKind.CloseBraceToken; }); 38 | var lastBrace = braces[braces.length - 1]; 39 | var indentLength = info.service.getIndentationAtPosition(classTarget.getSourceFile().fileName, lastBrace.getStart(), info.project.projectFile.project.formatCodeOptions); 40 | var indent = Array(indentLength + info.project.projectFile.project.formatCodeOptions.IndentSize + 1).join(' '); 41 | var refactorings = []; 42 | return refactorings; 43 | }; 44 | return ImplementInterface; 45 | })(); 46 | exports.ImplementInterface = ImplementInterface; 47 | -------------------------------------------------------------------------------- /lib/main/lang/modules/getPathCompletions.ts: -------------------------------------------------------------------------------- 1 | import * as path from "path"; 2 | import {Project} from "../core/project"; 3 | import * as tsconfig from "../../tsconfig/tsconfig"; 4 | import * as utils from "../utils"; 5 | var fuzzaldrin: { filter: (list: any[], prefix: string, property?: { key: string }) => any } = require('fuzzaldrin'); 6 | 7 | /** From https://github.com/Microsoft/TypeScript/pull/2173/files */ 8 | function getExternalModuleNames(program: ts.Program): string[] { 9 | var entries: string[] = []; 10 | 11 | program.getSourceFiles().forEach(sourceFile => { 12 | 13 | // Look for ambient external module declarations 14 | ts.forEachChild(sourceFile, child => { 15 | if (child.kind === ts.SyntaxKind.ModuleDeclaration && (child).name.kind === ts.SyntaxKind.StringLiteral) { 16 | entries.push((child).name.text); 17 | } 18 | }); 19 | }); 20 | 21 | return entries; 22 | } 23 | 24 | export interface GetRelativePathsInProjectResponse { 25 | files: { 26 | name: string; 27 | relativePath: string; 28 | fullPath: string; 29 | }[]; 30 | endsInPunctuation: boolean; 31 | } 32 | 33 | export interface GetPathCompletions { 34 | project: Project; 35 | filePath: string; 36 | prefix: string; 37 | includeExternalModules: boolean; 38 | } 39 | 40 | export function getPathCompletions(query: GetPathCompletions): GetRelativePathsInProjectResponse { 41 | var project = query.project; 42 | var sourceDir = path.dirname(query.filePath); 43 | var filePaths = project.projectFile.project.files.filter(p=> p !== query.filePath); 44 | var files: { 45 | name: string; 46 | relativePath: string; 47 | fullPath: string; 48 | }[] = []; 49 | 50 | if (query.includeExternalModules) { 51 | var externalModules = getExternalModuleNames(project.languageService.getProgram()); 52 | externalModules.forEach(e=> files.push({ 53 | name: `${e}`, 54 | relativePath: e, 55 | fullPath: e 56 | })); 57 | } 58 | 59 | filePaths.forEach(p=> { 60 | files.push({ 61 | name: path.basename(p, '.ts'), 62 | relativePath: tsconfig.removeExt(tsconfig.makeRelativePath(sourceDir, p)), 63 | fullPath: p 64 | }); 65 | }); 66 | 67 | var endsInPunctuation: boolean = utils.prefixEndsInPunctuation(query.prefix); 68 | 69 | if (!endsInPunctuation) 70 | files = fuzzaldrin.filter(files, query.prefix, { key: 'name' }); 71 | 72 | var response: GetRelativePathsInProjectResponse = { 73 | files: files, 74 | endsInPunctuation: endsInPunctuation 75 | }; 76 | 77 | return response; 78 | } 79 | -------------------------------------------------------------------------------- /dist/main/atom/atomConfig.js: -------------------------------------------------------------------------------- 1 | var utils_1 = require("../lang/utils"); 2 | var packageName = 'atom-typescript'; 3 | function getConfig(nameLambda) { 4 | return atom.config.get(packageName + '.' + utils_1.getName(nameLambda)); 5 | } 6 | function setConfig(nameLambda, value) { 7 | return atom.config.set(packageName + '.' + utils_1.getName(nameLambda), value); 8 | } 9 | var Config = (function () { 10 | function Config() { 11 | this.schema = { 12 | debugAtomTs: { 13 | title: 'Debug: Atom-TypeScript. Please do not use.', 14 | type: 'boolean', 15 | default: false 16 | }, 17 | preferredQuoteCharacter: { 18 | title: 'Preferred quote character', 19 | type: 'string', 20 | default: 'none' 21 | }, 22 | typescriptServices: { 23 | title: 'Full path (including file name) to a custom `typescriptServices.js`', 24 | type: 'string', 25 | default: '' 26 | }, 27 | showSemanticView: { 28 | title: 'Show semantic view', 29 | type: 'boolean', 30 | default: false 31 | } 32 | }; 33 | } 34 | Object.defineProperty(Config.prototype, "debugAtomTs", { 35 | get: function () { 36 | var _this = this; 37 | return getConfig(function () { return _this.schema.debugAtomTs; }); 38 | }, 39 | enumerable: true, 40 | configurable: true 41 | }); 42 | Object.defineProperty(Config.prototype, "preferredQuoteCharacter", { 43 | get: function () { 44 | var _this = this; 45 | return getConfig(function () { return _this.schema.preferredQuoteCharacter; }); 46 | }, 47 | enumerable: true, 48 | configurable: true 49 | }); 50 | Object.defineProperty(Config.prototype, "typescriptServices", { 51 | get: function () { 52 | var _this = this; 53 | return getConfig(function () { return _this.schema.typescriptServices; }); 54 | }, 55 | enumerable: true, 56 | configurable: true 57 | }); 58 | Object.defineProperty(Config.prototype, "showSemanticView", { 59 | get: function () { 60 | var _this = this; 61 | return getConfig(function () { return _this.schema.showSemanticView; }); 62 | }, 63 | set: function (value) { 64 | var _this = this; 65 | setConfig(function () { return _this.schema.showSemanticView; }, value); 66 | }, 67 | enumerable: true, 68 | configurable: true 69 | }); 70 | return Config; 71 | })(); 72 | var config = new Config(); 73 | module.exports = config; 74 | -------------------------------------------------------------------------------- /lib/main/atom/views/lineMessageView.ts: -------------------------------------------------------------------------------- 1 | import view = require('./view'); 2 | var $ = view.$; 3 | import path = require('path'); 4 | 5 | export interface ViewOptions { 6 | /** This is needed to support good goto next / goto previous logic 7 | * We inform the parent about our navigation 8 | */ 9 | goToLine: (filePath: string, line: number, col: number) => any; 10 | /** your message to the people */ 11 | message: string; 12 | /** what line are we talking about? */ 13 | line: number; 14 | /** which column */ 15 | col: number; 16 | /** so, was that in some other file? */ 17 | file: string; 18 | /** lets you display a code snippet inside a pre tag */ 19 | preview: string; 20 | } 21 | 22 | export class LineMessageView extends view.View { 23 | 24 | public index: number; 25 | private position: JQuery; 26 | private contents: JQuery; 27 | private code: JQuery; 28 | static content() { 29 | return this.div({ 30 | class: 'line-message' 31 | }, () => { 32 | this.div({ 33 | class: 'text-subtle inline-block', 34 | outlet: 'position', 35 | click: 'goToLine', 36 | style: 'cursor: pointer;' 37 | }); 38 | this.div({ 39 | class: 'message inline-block', 40 | outlet: 'contents' 41 | }); 42 | 43 | this.pre({ 44 | class: 'preview', 45 | outlet: 'code', 46 | click: 'goToLine', 47 | style: 'cursor: pointer;' 48 | }); 49 | }); 50 | } 51 | 52 | init() { 53 | var message = 'at line ' + this.options.line; 54 | 55 | if (this.options.file !== undefined) { 56 | message += ', file ' + this.options.file; 57 | } 58 | this.position.text(message); 59 | this.contents.text(this.options.message); 60 | 61 | if (this.options.preview) { 62 | this.code.text(this.options.preview); 63 | } else { 64 | this.code.remove(); 65 | } 66 | } 67 | 68 | goToLine() { 69 | this.options.goToLine(this.options.file, this.options.line, this.options.col); 70 | } 71 | 72 | getSummary() { 73 | var pos = this.options.line.toString(); 74 | if (this.options.file !== undefined) { 75 | pos += ', ' + this.options.file; 76 | } 77 | return { 78 | summary: pos + ' ' + this.options.message, 79 | rawSummary: true, 80 | handler: function(element) { 81 | $(element) 82 | .css('cursor', 'pointer') 83 | .click(this.goToLine.bind(this)); 84 | }.bind(this) 85 | }; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /dist/main/atom/views/projectSymbolsView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var sp = require('atom-space-pen-views'); 7 | var atomUtils = require("../atomUtils"); 8 | var ProjectSymbolsView = (function (_super) { 9 | __extends(ProjectSymbolsView, _super); 10 | function ProjectSymbolsView() { 11 | _super.apply(this, arguments); 12 | this.panel = null; 13 | } 14 | Object.defineProperty(ProjectSymbolsView.prototype, "$", { 15 | get: function () { 16 | return this; 17 | }, 18 | enumerable: true, 19 | configurable: true 20 | }); 21 | Object.defineProperty(ProjectSymbolsView.prototype, "filterView", { 22 | get: function () { 23 | return { 24 | $: this.filterEditorView, 25 | model: this.filterEditorView.model 26 | }; 27 | }, 28 | enumerable: true, 29 | configurable: true 30 | }); 31 | ProjectSymbolsView.prototype.setNavBarItems = function (tsItems) { 32 | _super.prototype.setMaxItems.call(this, 40); 33 | var items = tsItems; 34 | _super.prototype.setItems.call(this, items); 35 | }; 36 | ProjectSymbolsView.prototype.viewForItem = function (item) { 37 | return "\n
  • \n
    " + item.name + "
    \n
    " + item.kind + "
    \n
    " + item.fileName + " : " + (item.position.line + 1) + "
    \n
  • \n "; 38 | }; 39 | ProjectSymbolsView.prototype.confirmed = function (item) { 40 | atom.workspace.open(item.filePath, { 41 | initialLine: item.position.line, 42 | initialColumn: item.position.col 43 | }); 44 | this.hide(); 45 | }; 46 | ProjectSymbolsView.prototype.getFilterKey = function () { return 'name'; }; 47 | ProjectSymbolsView.prototype.show = function () { 48 | this.storeFocusedElement(); 49 | if (!this.panel) 50 | this.panel = atom.workspace.addModalPanel({ item: this }); 51 | this.panel.show(); 52 | this.focusFilterEditor(); 53 | }; 54 | ProjectSymbolsView.prototype.hide = function () { 55 | this.panel.hide(); 56 | this.restoreFocus(); 57 | }; 58 | ProjectSymbolsView.prototype.cancelled = function () { 59 | this.hide(); 60 | }; 61 | return ProjectSymbolsView; 62 | })(sp.SelectListView); 63 | exports.ProjectSymbolsView = ProjectSymbolsView; 64 | -------------------------------------------------------------------------------- /dist/main/atom/views/contextView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var sp = require('atom-space-pen-views'); 7 | var mainPanelView = require('./mainPanelView'); 8 | var semanticView = require("./semanticView"); 9 | var titles = { 10 | togglePanel: 'Toggle TypeScript Panel', 11 | tabErrors: 'Tab: Errors in Open Files', 12 | tabLastBuild: 'Tab: Last Build Output', 13 | tabReferences: 'Tab: Find References', 14 | fileSemantics: 'Toggle: File Semantics', 15 | }; 16 | var items = Object.keys(titles).map(function (item) { return { title: titles[item] }; }); 17 | var ContextView = (function (_super) { 18 | __extends(ContextView, _super); 19 | function ContextView() { 20 | _super.apply(this, arguments); 21 | this.panel = null; 22 | } 23 | Object.defineProperty(ContextView.prototype, "$", { 24 | get: function () { 25 | return this; 26 | }, 27 | enumerable: true, 28 | configurable: true 29 | }); 30 | ContextView.prototype.setItems = function (items) { _super.prototype.setItems.call(this, items); }; 31 | ContextView.prototype.viewForItem = function (item) { 32 | return "
  • " + item.title + "
  • "; 33 | }; 34 | ContextView.prototype.confirmed = function (item) { 35 | if (item.title == titles.togglePanel) { 36 | mainPanelView.panelView.toggle(); 37 | } 38 | if (item.title == titles.tabErrors) { 39 | mainPanelView.panelView.errorPanelSelected(); 40 | } 41 | if (item.title == titles.tabLastBuild) { 42 | mainPanelView.panelView.buildPanelSelected(); 43 | } 44 | if (item.title == titles.tabReferences) { 45 | mainPanelView.panelView.referencesPanelSelected(); 46 | } 47 | if (item.title == titles.fileSemantics) { 48 | semanticView.toggle(); 49 | } 50 | this.hide(); 51 | }; 52 | ContextView.prototype.getFilterKey = function () { return 'title'; }; 53 | ContextView.prototype.show = function () { 54 | this.storeFocusedElement(); 55 | if (!this.panel) 56 | this.panel = atom.workspace.addModalPanel({ item: this }); 57 | this.panel.show(); 58 | this.setItems(items); 59 | this.focusFilterEditor(); 60 | }; 61 | ContextView.prototype.hide = function () { 62 | this.panel.hide(); 63 | this.restoreFocus(); 64 | }; 65 | ContextView.prototype.cancelled = function () { 66 | this.hide(); 67 | }; 68 | return ContextView; 69 | })(sp.SelectListView); 70 | exports.ContextView = ContextView; 71 | -------------------------------------------------------------------------------- /lib/main/atom/views/simpleOverlaySelectionView.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A functional form of the SelectListView 3 | * Only one of these bad boys is allowed on the screen at one time 4 | */ 5 | 6 | export interface SelectListViewOptions { 7 | items: T[]; 8 | /** everything except the `li` which is required and we add for you */ 9 | viewForItem: (item: T) => string; 10 | 11 | /** some property on item */ 12 | filterKey: string; 13 | confirmed: (item: T) => any; 14 | } 15 | 16 | var singleton: SimpleOverlaySelectListView; 17 | 18 | export default function (options: SelectListViewOptions, editor: AtomCore.IEditor): SimpleOverlaySelectListView { 19 | if (!singleton) singleton = new SimpleOverlaySelectListView(options, editor); 20 | else { 21 | singleton.options = options; 22 | singleton.editor = editor; 23 | } 24 | 25 | singleton.setItems(); 26 | singleton.show(); 27 | return singleton; 28 | } 29 | 30 | /** 31 | * Various Utility section 32 | */ 33 | 34 | import sp = require('atom-space-pen-views'); 35 | import * as atomUtils from "../atomUtils"; 36 | 37 | export class SimpleOverlaySelectListView extends sp.SelectListView { 38 | 39 | private _overlayDecoration: AtomCore.Decoration; 40 | 41 | 42 | constructor(public options: SelectListViewOptions, public editor: AtomCore.IEditor) { 43 | super(); 44 | 45 | this.$.addClass('atomts-overlay'); 46 | (this.filterEditorView).model.placeholderText = 'Filter list'; 47 | } 48 | 49 | get $(): JQuery { 50 | return this; 51 | } 52 | 53 | public setItems() { 54 | super.setItems(this.options.items) 55 | } 56 | 57 | /** override */ 58 | viewForItem(item: T) { 59 | return `
  • 60 | ${this.options.viewForItem(item) } 61 |
  • `; 62 | } 63 | 64 | /** override */ 65 | confirmed(item: T) { 66 | this.options.confirmed(item); 67 | this.hide(); 68 | } 69 | 70 | /** override */ 71 | getFilterKey() { 72 | return this.options.filterKey; 73 | } 74 | 75 | show() { 76 | this.storeFocusedElement(); 77 | this._overlayDecoration = this.editor.decorateMarker(this.editor.getLastCursor().getMarker(), 78 | { type: "overlay", position: "tail", item: this }); 79 | 80 | /** I've need to do this timeout otherwise we don't get focus. I suspect its an artifact of creating an overlay decoration */ 81 | // Comment this out if you want to test styles ;) 82 | setTimeout(() => this.focusFilterEditor(), 100); 83 | } 84 | 85 | hide() { 86 | this.restoreFocus(); 87 | 88 | if (this._overlayDecoration) 89 | this._overlayDecoration.destroy(); 90 | } 91 | 92 | cancelled() { 93 | this.hide(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /lib/main/tsconfig/simpleValidator.ts: -------------------------------------------------------------------------------- 1 | /// Not useful for user input validation 2 | // But great for simple config validation 3 | // works only by "n" valid options 4 | 5 | export var types = { 6 | string: 'string', 7 | boolean: 'boolean', 8 | number: 'number' 9 | } 10 | 11 | export interface ValidationInfo { 12 | [name: string]: { 13 | validValues?: string[]; 14 | type?: string; 15 | } 16 | } 17 | 18 | export interface Errors { 19 | invalidValues: string[]; 20 | extraKeys: string[]; 21 | errorMessage: string; 22 | } 23 | 24 | export class SimpleValidator { 25 | 26 | private potentialLowerCaseMatch: { [key: string]: string }; 27 | constructor(public validationInfo: ValidationInfo) { 28 | this.potentialLowerCaseMatch = {}; 29 | Object.keys(validationInfo).forEach(k=> this.potentialLowerCaseMatch[k.toLowerCase()] = k); 30 | } 31 | 32 | validate(config: any): Errors { 33 | var keys = Object.keys(config); 34 | var errors = { invalidValues: [], extraKeys: [], errorMessage: '' }; 35 | keys.forEach(k=> { 36 | // Check extra keys 37 | if (!this.validationInfo[k]) { 38 | if (this.potentialLowerCaseMatch[k]) { 39 | errors.extraKeys.push(`Key: '${k}' is a potential lower case match for '${this.potentialLowerCaseMatch[k]}'. Fix the casing.`); 40 | } 41 | else { 42 | errors.extraKeys.push(`Unknown Option: ${k}`) 43 | } 44 | } 45 | // Do validation 46 | else { 47 | var validationInfo = this.validationInfo[k]; 48 | var value: any = config[k]; 49 | if (validationInfo.validValues && validationInfo.validValues.length) { 50 | var validValues = validationInfo.validValues; 51 | if (!validValues.some(valid => valid.toLowerCase() === value.toLowerCase())) { 52 | errors.invalidValues.push(`Key: '${k}' has an invalid value: ${value}`); 53 | } 54 | } 55 | if (validationInfo.type && typeof value !== validationInfo.type) { 56 | errors.invalidValues.push(`Key: '${k}' has an invalid type: ${typeof value}`) 57 | } 58 | } 59 | }); 60 | 61 | var total = errors.invalidValues.concat(errors.extraKeys); 62 | if (total.length) { 63 | errors.errorMessage = total.join("\n"); 64 | } 65 | 66 | return errors; 67 | } 68 | } 69 | 70 | 71 | export function createMap(arr: string[]): { [key: string]: boolean } { 72 | return arr.reduce((result: { [key: string]: boolean }, key: string) => { 73 | result[key] = true; 74 | return result; 75 | }, <{ [key: string]: boolean }>{}); 76 | } 77 | -------------------------------------------------------------------------------- /dist/main/atom/views/simpleOverlaySelectionView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var singleton; 7 | function default_1(options, editor) { 8 | if (!singleton) 9 | singleton = new SimpleOverlaySelectListView(options, editor); 10 | else { 11 | singleton.options = options; 12 | singleton.editor = editor; 13 | } 14 | singleton.setItems(); 15 | singleton.show(); 16 | return singleton; 17 | } 18 | Object.defineProperty(exports, "__esModule", { value: true }); 19 | exports.default = default_1; 20 | var sp = require('atom-space-pen-views'); 21 | var SimpleOverlaySelectListView = (function (_super) { 22 | __extends(SimpleOverlaySelectListView, _super); 23 | function SimpleOverlaySelectListView(options, editor) { 24 | _super.call(this); 25 | this.options = options; 26 | this.editor = editor; 27 | this.$.addClass('atomts-overlay'); 28 | this.filterEditorView.model.placeholderText = 'Filter list'; 29 | } 30 | Object.defineProperty(SimpleOverlaySelectListView.prototype, "$", { 31 | get: function () { 32 | return this; 33 | }, 34 | enumerable: true, 35 | configurable: true 36 | }); 37 | SimpleOverlaySelectListView.prototype.setItems = function () { 38 | _super.prototype.setItems.call(this, this.options.items); 39 | }; 40 | SimpleOverlaySelectListView.prototype.viewForItem = function (item) { 41 | return "
  • \n " + this.options.viewForItem(item) + "\n
  • "; 42 | }; 43 | SimpleOverlaySelectListView.prototype.confirmed = function (item) { 44 | this.options.confirmed(item); 45 | this.hide(); 46 | }; 47 | SimpleOverlaySelectListView.prototype.getFilterKey = function () { 48 | return this.options.filterKey; 49 | }; 50 | SimpleOverlaySelectListView.prototype.show = function () { 51 | var _this = this; 52 | this.storeFocusedElement(); 53 | this._overlayDecoration = this.editor.decorateMarker(this.editor.getLastCursor().getMarker(), { type: "overlay", position: "tail", item: this }); 54 | setTimeout(function () { return _this.focusFilterEditor(); }, 100); 55 | }; 56 | SimpleOverlaySelectListView.prototype.hide = function () { 57 | this.restoreFocus(); 58 | if (this._overlayDecoration) 59 | this._overlayDecoration.destroy(); 60 | }; 61 | SimpleOverlaySelectListView.prototype.cancelled = function () { 62 | this.hide(); 63 | }; 64 | return SimpleOverlaySelectListView; 65 | })(sp.SelectListView); 66 | exports.SimpleOverlaySelectListView = SimpleOverlaySelectListView; 67 | -------------------------------------------------------------------------------- /dist/main/atom/views/documentationView.js: -------------------------------------------------------------------------------- 1 | var __extends = (this && this.__extends) || function (d, b) { 2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; 3 | function __() { this.constructor = d; } 4 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 5 | }; 6 | var view = require('./view'); 7 | var $ = view.$; 8 | var DocumentationView = (function (_super) { 9 | __extends(DocumentationView, _super); 10 | function DocumentationView() { 11 | _super.apply(this, arguments); 12 | this.shown = false; 13 | } 14 | DocumentationView.content = function () { 15 | var _this = this; 16 | return this.div({ class: 'atom-ts-documentation padded top' }, function () { return _this.div(function () { 17 | _this.h2({ outlet: 'header' }); 18 | _this.p({ outlet: 'documentation' }); 19 | }); }); 20 | }; 21 | DocumentationView.prototype.show = function () { this.$.addClass('active'); this.shown = true; }; 22 | DocumentationView.prototype.hide = function () { this.$.removeClass('active'); this.shown = false; }; 23 | DocumentationView.prototype.toggle = function () { if (this.shown) { 24 | this.hide(); 25 | } 26 | else { 27 | this.show(); 28 | } }; 29 | DocumentationView.prototype.setContent = function (content) { 30 | this.header.html(content.display); 31 | content.documentation = content.documentation.replace(/(?:\r\n|\r|\n)/g, '
    '); 32 | this.documentation.html(content.documentation); 33 | }; 34 | DocumentationView.prototype.autoPosition = function () { 35 | var editor = atom.workspace.getActiveTextEditor(); 36 | var cursor = editor.getCursors()[0]; 37 | var cursorTop = cursor.getPixelRect().top - editor.getScrollTop(); 38 | var editorHeight = editor.getHeight(); 39 | if (editorHeight - cursorTop < 100) { 40 | this.$.removeClass('bottom'); 41 | this.$.addClass('top'); 42 | } 43 | else { 44 | this.$.removeClass('top'); 45 | this.$.addClass('bottom'); 46 | } 47 | }; 48 | return DocumentationView; 49 | })(view.View); 50 | exports.DocumentationView = DocumentationView; 51 | function attach() { 52 | if (exports.docView) 53 | return; 54 | exports.docView = new DocumentationView({}); 55 | $(atom.views.getView(atom.workspace)).append(exports.docView.$); 56 | } 57 | exports.attach = attach; 58 | function testDocumentationView() { 59 | exports.docView.setContent({ 60 | display: "this is awesome", documentation: "\n some docs\n over\n many\n many li\n\n lines\n long\n so\n long\n that\n it\n should\n\n start\n to\n scroll\n ", filePath: "some filepath" 61 | }); 62 | exports.docView.show(); 63 | } 64 | exports.testDocumentationView = testDocumentationView; 65 | -------------------------------------------------------------------------------- /styles/semantic-view.less: -------------------------------------------------------------------------------- 1 | // From https://github.com/xndcn/symbols-tree-view 2 | @import "ui-variables"; 3 | @font-face { 4 | font-family: 'symbol-icons'; 5 | src: url('atom://atom-typescript/images/symbol-icons.woff') format('woff'); 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | @symbol-class: '\e600'; 11 | @symbol-struct: '\e601'; 12 | @symbol-macro: '\e602'; 13 | @symbol-typedef: '\e603'; 14 | @symbol-union: '\e604'; 15 | @symbol-interface: '\e605'; 16 | @symbol-enum: '\e606'; 17 | @symbol-variable: '\e607'; 18 | @symbol-function: '\e608'; 19 | @symbol-namespace: '\e609'; 20 | .symbol-icon(@name) { 21 | font-family: 'symbol-icons'; 22 | content: @@name; 23 | } 24 | .atomts-semantic-view { 25 | max-width: 250px; 26 | // needed otherwise the panel takes up all the space and doesn't scroll 27 | max-height: 100%; 28 | overflow-y: auto; 29 | padding: 10px; 30 | .selected { 31 | background: @background-color-highlight; 32 | } 33 | 34 | .node{ 35 | cursor: pointer; 36 | } 37 | 38 | .icon-class::before { 39 | .symbol-icon(symbol-class); 40 | } 41 | .icon-struct::before { 42 | .symbol-icon(symbol-struct); 43 | } 44 | .icon-variable::before { 45 | .symbol-icon(symbol-variable); 46 | } 47 | 48 | .icon-field::before { 49 | .symbol-icon(symbol-variable); 50 | } 51 | .icon-member::before { 52 | .symbol-icon(symbol-variable); 53 | } 54 | .icon-interface::before { 55 | .symbol-icon(symbol-interface); 56 | } 57 | .icon-enum::before { 58 | .symbol-icon(symbol-enum); 59 | } 60 | .icon-typedef::before { 61 | .symbol-icon(symbol-typedef); 62 | } 63 | .icon-macro::before { 64 | .symbol-icon(symbol-macro); 65 | } 66 | .icon-union::before { 67 | .symbol-icon(symbol-union); 68 | } 69 | 70 | 71 | 72 | .icon-module::before { 73 | .symbol-icon(symbol-macro); 74 | } 75 | 76 | // variable like 77 | .icon-var::before { 78 | .symbol-icon(symbol-variable); 79 | } 80 | .icon-property::before { 81 | .symbol-icon(symbol-variable); 82 | } 83 | .icon-alias::before { 84 | .symbol-icon(symbol-variable); 85 | } 86 | 87 | // function like 88 | .icon-function::before { 89 | .symbol-icon(symbol-function); 90 | } 91 | .icon-constructor::before { 92 | .symbol-icon(symbol-function); 93 | } 94 | .icon-method::before { 95 | .symbol-icon(symbol-function); 96 | } 97 | .icon-setter::before { 98 | .symbol-icon(symbol-function); 99 | } 100 | .icon-getter::before { 101 | .symbol-icon(symbol-function); 102 | } 103 | 104 | // module like 105 | .icon-namespace::before { 106 | .symbol-icon(symbol-namespace); 107 | } 108 | 109 | } 110 | --------------------------------------------------------------------------------