Add a "FIDL: Go To Source" command.

It will jump from FIDL generated bindings to the appropriate FIDL source
file.

Change-Id: I59f62d23dbad9fe8cda8f1c17c3e2cc5ea30ee8e
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..72aae85
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules/
+out/
diff --git a/vscode-language-fidl/CHANGELOG.md b/vscode-language-fidl/CHANGELOG.md
index d68cdd6..e689528 100644
--- a/vscode-language-fidl/CHANGELOG.md
+++ b/vscode-language-fidl/CHANGELOG.md
@@ -1,3 +1,7 @@
 # v0.0.1
 
 - Initial release with basic syntax highlighting support for FIDL.
+
+# v0.0.3
+
+ - Offer a "FIDL: Go To Source" command to jump from generated bindings to FIDL source when working in the Fuchsia tree.
\ No newline at end of file
diff --git a/vscode-language-fidl/README.md b/vscode-language-fidl/README.md
index 364f654..65adeef 100644
--- a/vscode-language-fidl/README.md
+++ b/vscode-language-fidl/README.md
@@ -1,6 +1,8 @@
 # FIDL Language Support for Visual Studio Code
 
-This extension adds syntax highlighting to [FIDL][fidl] files in VS Code.
+This extension adds:
+ - syntax highlighting to [FIDL][fidl] files.
+ - a command to jump from generated bindings to FIDL source.
 
 
 [fidl]: https://fuchsia.googlesource.com/fidl
diff --git a/vscode-language-fidl/package.json b/vscode-language-fidl/package.json
index f1043fd..2dc8d8f 100644
--- a/vscode-language-fidl/package.json
+++ b/vscode-language-fidl/package.json
@@ -1,9 +1,9 @@
 {
     "name": "language-fidl",
     "displayName": "FIDL Language Support",
-    "description": "Syntax highlighting support for FIDL files",
+    "description": "Support for FIDL files",
     "license": "SEE LICENSE IN LICENSE",
-    "version": "0.0.2",
+    "version": "0.0.3",
     "publisher": "fuchsia-authors",
     "engines": {
         "vscode": "^1.10.0"
@@ -11,23 +11,54 @@
     "categories": [
         "Languages"
     ],
+    "activationEvents": [
+        "onCommand:extension.goToFidlSource"
+    ],
+    "main": "./out/extension",
     "contributes": {
-        "languages": [{
-            "id": "fidl",
-            "aliases": ["FIDL", "fidl"],
-            "extensions": [".fidl"],
-            "configuration": "./language-configuration.json"
-        }],
-        "grammars": [{
-            "language": "fidl",
-            "scopeName": "source.fidl",
-            "path": "./syntaxes/fidl.tmLanguage.json"
-        }]
+        "languages": [
+            {
+                "id": "fidl",
+                "aliases": [
+                    "FIDL",
+                    "fidl"
+                ],
+                "extensions": [
+                    ".fidl"
+                ],
+                "configuration": "./language-configuration.json"
+            }
+        ],
+        "grammars": [
+            {
+                "language": "fidl",
+                "scopeName": "source.fidl",
+                "path": "./syntaxes/fidl.tmLanguage.json"
+            }
+        ],
+        "commands": [
+            {
+                "command": "extension.goToFidlSource",
+                "title": "FIDL: Go To Source"
+            }
+        ]
     },
     "homepage": "https://fuchsia.googlesource.com/vscode-language-fidl",
     "repository": {
         "type": "git",
         "url": "https://fuchsia.googlesource.com/vscode-language-fidl"
     },
-    "icon": "images/fuchsia_logo_128x128.png"
+    "icon": "images/fuchsia_logo_128x128.png",
+    "scripts": {
+        "vscode:prepublish": "npm run compile",
+        "compile": "tsc -p ./",
+        "watch": "tsc -watch -p ./",
+        "postinstall": "node ./node_modules/vscode/bin/install"
+    },
+    "devDependencies": {
+        "typescript": "^2.6.1",
+        "vscode": "^1.1.6",
+        "tslint": "^5.8.0",
+        "@types/node": "^7.0.43"
+    }
 }
\ No newline at end of file
diff --git a/vscode-language-fidl/src/extension.ts b/vscode-language-fidl/src/extension.ts
new file mode 100644
index 0000000..fc204cf
--- /dev/null
+++ b/vscode-language-fidl/src/extension.ts
@@ -0,0 +1,41 @@
+'use strict';
+
+import * as vscode from 'vscode';
+import * as fs from 'fs';
+
+function findFidlSource(generatedSourcePath: string): string | void {
+    // TODO: establish a non-regex way of finding the source FIDL path.
+    const cxx_dart_match = generatedSourcePath.match(/(^.*\/)(?:out\/[^/]+\/gen\/)(.*\.fidl)[\._-][^/]*$/);
+    if (cxx_dart_match) {
+        return `${cxx_dart_match[1]}${cxx_dart_match[2]}`;
+    }
+
+    const go_match = generatedSourcePath.match(/(^.*\/)(?:out\/[^/]+\/gen\/go\/src\/)(.*\/)([^/]+)\/\3\.core\.go$/);
+    if (go_match) {
+        return `${go_match[1]}${go_match[2]}${go_match[3]}.fidl`;
+    }
+
+    const rust_match = generatedSourcePath.match(/(^.*\/)(?:out\/[^/]+\/gen\/)(.*).rs$/);
+    if (rust_match) {
+        return `${rust_match[1]}/${rust_match[2]}.fidl`;
+    }
+}
+
+export function activate(context: vscode.ExtensionContext) {
+    let disposable = vscode.commands.registerCommand('extension.goToFidlSource', () => {
+        if (vscode.window.activeTextEditor) {
+            const fileName = vscode.window.activeTextEditor.document.fileName;
+            const fidlFileName = findFidlSource(fileName);
+            if (fidlFileName && fs.existsSync(fidlFileName)) {
+                vscode.workspace.openTextDocument(fidlFileName).then((doc) => vscode.window.showTextDocument(doc));
+            } else {
+                vscode.window.showErrorMessage(`Couldn't find FIDL source for ${fileName}`);
+            }
+        }
+    });
+
+    context.subscriptions.push(disposable);
+}
+
+export function deactivate() {
+}
\ No newline at end of file
diff --git a/vscode-language-fidl/tsconfig.json b/vscode-language-fidl/tsconfig.json
new file mode 100644
index 0000000..8aa5312
--- /dev/null
+++ b/vscode-language-fidl/tsconfig.json
@@ -0,0 +1,23 @@
+{
+    "compilerOptions": {
+        "module": "commonjs",
+        "target": "es6",
+        "outDir": "out",
+        "lib": [
+            "es6"
+        ],
+        "sourceMap": true,
+        "rootDir": "src",
+        /* Strict Type-Checking Option */
+        "strict": true,   /* enable all strict type-checking options */
+        /* Additional Checks */
+        "noUnusedLocals": true /* Report errors on unused locals. */
+        // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
+        // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
+        // "noUnusedParameters": true,  /* Report errors on unused parameters. */
+    },
+    "exclude": [
+        "node_modules",
+        ".vscode-test"
+    ]
+}
\ No newline at end of file
diff --git a/vscode-language-fidl/tslint.json b/vscode-language-fidl/tslint.json
new file mode 100644
index 0000000..c791efd
--- /dev/null
+++ b/vscode-language-fidl/tslint.json
@@ -0,0 +1,15 @@
+{
+    "rules": {
+        "no-string-throw": true,
+        "no-unused-expression": true,
+        "no-duplicate-variable": true,
+        "curly": true,
+        "class-name": true,
+        "semicolon": [
+            true,
+            "always"
+        ],
+        "triple-equals": true
+    },
+    "defaultSeverity": "warning"
+}
\ No newline at end of file