mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
call-hierarchy-sample
This commit is contained in:
@ -184,6 +184,13 @@ const samples = [
|
||||
guide: null,
|
||||
apis: [`languages.registerCodeLensProvider`, `CodeLensProvider`, `CodeLens`],
|
||||
contributions: []
|
||||
},
|
||||
{
|
||||
description: 'Call Hierarchy Sample',
|
||||
path: 'call-hierarchy-sample',
|
||||
guide: null,
|
||||
apis: [`languages.registerCallHierarchyProvider`, `CallHierarchyProvider`, `CallHierarchyItem`, `CallHierarchyOutgoingCall`, `CallHierarchyIncomingCall`],
|
||||
contributions: []
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
4
call-hierarchy-sample/.gitignore
vendored
Normal file
4
call-hierarchy-sample/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
out
|
||||
node_modules
|
||||
.vscode-test/
|
||||
*.vsix
|
||||
22
call-hierarchy-sample/.vscode/launch.json
vendored
Normal file
22
call-hierarchy-sample/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// A launch configuration that compiles the extension and then opens it inside a new window
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Run Extension",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "npm: watch"
|
||||
}
|
||||
]
|
||||
}
|
||||
3
call-hierarchy-sample/.vscode/settings.json
vendored
Normal file
3
call-hierarchy-sample/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"editor.insertSpaces": false
|
||||
}
|
||||
20
call-hierarchy-sample/.vscode/tasks.json
vendored
Normal file
20
call-hierarchy-sample/.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch",
|
||||
"problemMatcher": "$tsc-watch",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"reveal": "never"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
9
call-hierarchy-sample/.vscodeignore
Normal file
9
call-hierarchy-sample/.vscodeignore
Normal file
@ -0,0 +1,9 @@
|
||||
.vscode/**
|
||||
.vscode-test/**
|
||||
out/test/**
|
||||
out/**/*.map
|
||||
src/**
|
||||
.gitignore
|
||||
tsconfig.json
|
||||
vsc-extension-quickstart.md
|
||||
tslint.json
|
||||
34
call-hierarchy-sample/README.md
Normal file
34
call-hierarchy-sample/README.md
Normal file
@ -0,0 +1,34 @@
|
||||
# Call Hierarchy Provider Sample
|
||||
|
||||
This sample shows the **Call Hierarchy** in action based on a simple food pyramid model defined using simple subject~verb~object syntax.
|
||||
|
||||

|
||||
|
||||
## VS Code API
|
||||
|
||||
### `vscode` module
|
||||
|
||||
- [`languages.registerCallHierarchyProvider`](https://code.visualstudio.com/api/references/vscode-api#languages.registerCallHierarchyProvider)
|
||||
- [`CallHierarchyProvider`](https://code.visualstudio.com/api/references/vscode-api#CallHierarchyProvider)
|
||||
|
||||
## Running the Sample
|
||||
|
||||
Start the extension in the debugger and it automatically opens a file that is ready for the right-click > Peek Call Hierarchy. Otherwise, it can be testing by creating a file with extension `.txt` and pasting following text:
|
||||
|
||||
```plaintext
|
||||
Coyote eats deer.
|
||||
Deer eats plants.
|
||||
Coyote eats lizard.
|
||||
Lizard eats bird.
|
||||
Lizard eats frog.
|
||||
Lizard eats butterfly.
|
||||
Bird eats seeds.
|
||||
Frog eats insects.
|
||||
Butterfly eats fruit.
|
||||
```
|
||||
|
||||
Right click on a noun or a verb and select _Peek Call Hierarchy_.
|
||||
|
||||
## Contributing to the Sample and Testing the Sample
|
||||
|
||||
Run the _Run Extension Tests_ configuration and verify in the Debug Console that all tests are passing.
|
||||
BIN
call-hierarchy-sample/demo.gif
Normal file
BIN
call-hierarchy-sample/demo.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 273 KiB |
323
call-hierarchy-sample/package-lock.json
generated
Normal file
323
call-hierarchy-sample/package-lock.json
generated
Normal file
@ -0,0 +1,323 @@
|
||||
{
|
||||
"name": "call-hierarchy-sample",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
|
||||
"integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz",
|
||||
"integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "10.14.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.17.tgz",
|
||||
"integrity": "sha512-p/sGgiPaathCfOtqu2fx5Mu1bcjuP8ALFg4xpGgNkcin7LwRyzUKniEHBKdcE1RPsenq5JVPIpMTJSygLboygQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/vscode": {
|
||||
"version": "1.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.40.0.tgz",
|
||||
"integrity": "sha512-5kEIxL3qVRkwhlMerxO7XuMffa+0LBl+iG2TcRa0NsdoeSFLkt/9hJ02jsi/Kvc6y8OVF2N2P2IHP5S4lWf/5w==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"builtin-modules": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
|
||||
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.20.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
|
||||
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
},
|
||||
"diff": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
|
||||
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
|
||||
"dev": true
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"dev": true
|
||||
},
|
||||
"esutils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||
"dev": true
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||
"dev": true
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
|
||||
"integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||
"dev": true
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"dev": true
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
|
||||
"integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
|
||||
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
|
||||
"dev": true
|
||||
},
|
||||
"tslint": {
|
||||
"version": "5.19.0",
|
||||
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.19.0.tgz",
|
||||
"integrity": "sha512-1LwwtBxfRJZnUvoS9c0uj8XQtAnyhWr9KlNvDIdB+oXyT+VpsOAaEhEgKi1HrZ8rq0ki/AAnbGSv4KM6/AfVZw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"builtin-modules": "^1.1.1",
|
||||
"chalk": "^2.3.0",
|
||||
"commander": "^2.12.1",
|
||||
"diff": "^3.2.0",
|
||||
"glob": "^7.1.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
"minimatch": "^3.0.4",
|
||||
"mkdirp": "^0.5.1",
|
||||
"resolve": "^1.3.2",
|
||||
"semver": "^5.3.0",
|
||||
"tslib": "^1.8.0",
|
||||
"tsutils": "^2.29.0"
|
||||
}
|
||||
},
|
||||
"tsutils": {
|
||||
"version": "2.29.0",
|
||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
|
||||
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^1.8.1"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.2.tgz",
|
||||
"integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==",
|
||||
"dev": true
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
30
call-hierarchy-sample/package.json
Normal file
30
call-hierarchy-sample/package.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "call-hierarchy-sample",
|
||||
"displayName": "call-hierarchy-sample",
|
||||
"description": "Call hierarchy provider sample",
|
||||
"version": "0.0.1",
|
||||
"publisher": "vscode-samples",
|
||||
"repository": "https://github.com/Microsoft/vscode-extension-samples/call-hierarchy-sample",
|
||||
"engines": {
|
||||
"vscode": "^1.40.0"
|
||||
},
|
||||
"categories": [
|
||||
"Other"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onLanguage:plaintext"
|
||||
],
|
||||
"main": "./out/extension.js",
|
||||
"scripts": {
|
||||
"vscode:prepublish": "npm run compile",
|
||||
"compile": "tsc -p ./",
|
||||
"lint": "tslint -p ./",
|
||||
"watch": "tsc -watch -p ./"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^10.14.17",
|
||||
"@types/vscode": "^1.40.0",
|
||||
"tslint": "^5.16.0",
|
||||
"typescript": "^3.5.1"
|
||||
}
|
||||
}
|
||||
11
call-hierarchy-sample/sample.txt
Normal file
11
call-hierarchy-sample/sample.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# Right click on a term below and select `Peek Call Hierarchy`.
|
||||
|
||||
Coyote eats deer.
|
||||
Deer eats plants.
|
||||
Coyote eats lizard.
|
||||
Lizard eats bird.
|
||||
Lizard eats frog.
|
||||
Lizard eats butterfly.
|
||||
Bird eats seeds.
|
||||
Frog eats insects.
|
||||
Butterfly eats fruit.
|
||||
155
call-hierarchy-sample/src/FoodPyramidHierarchyProvider.ts
Normal file
155
call-hierarchy-sample/src/FoodPyramidHierarchyProvider.ts
Normal file
@ -0,0 +1,155 @@
|
||||
import {
|
||||
Range, Position, CallHierarchyProvider, TextDocument, CancellationToken, CallHierarchyItem,
|
||||
SymbolKind, ProviderResult, CallHierarchyIncomingCall, CallHierarchyOutgoingCall, workspace, Uri
|
||||
} from 'vscode';
|
||||
import { FoodPyramid, FoodRelation } from './model';
|
||||
|
||||
export class FoodPyramidHierarchyProvider implements CallHierarchyProvider {
|
||||
|
||||
prepareCallHierarchy(document: TextDocument, position: Position, token: CancellationToken): CallHierarchyItem | undefined {
|
||||
let range = document.getWordRangeAtPosition(position);
|
||||
if (range) {
|
||||
let word = document.getText(range);
|
||||
return this.createCallHierarchyItem(word, '', document, range);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async provideCallHierarchyOutgoingCalls(item: CallHierarchyItem, token: CancellationToken): Promise<CallHierarchyOutgoingCall[] | undefined> {
|
||||
let document = await workspace.openTextDocument(item.uri);
|
||||
let parser = new FoodPyramidParser();
|
||||
parser.parse(document);
|
||||
let model = parser.getModel();
|
||||
let originRelation = model.getRelationAt(item.range);
|
||||
|
||||
let outgoingCallItems: CallHierarchyOutgoingCall[] = [];
|
||||
|
||||
if (model.isVerb(item.name)) {
|
||||
let outgoingCalls = model.getVerbRelations(item.name)
|
||||
.filter(relation => relation.subject === originRelation!.subject);
|
||||
|
||||
outgoingCalls.forEach(relation => {
|
||||
let outgoingCallRange = relation.getRangeOf(relation.object);
|
||||
let verbItem = this.createCallHierarchyItem(relation.object, 'noun', document, outgoingCallRange);
|
||||
let outgoingCallItem = new CallHierarchyOutgoingCall(verbItem, [outgoingCallRange]);
|
||||
outgoingCallItems.push(outgoingCallItem);
|
||||
});
|
||||
}
|
||||
else if (model.isNoun(item.name)) {
|
||||
let outgoingCallMap = groupBy(model.getSubjectRelations(item.name), relation => relation.verb);
|
||||
|
||||
outgoingCallMap.forEach((relations, verb) => {
|
||||
let outgoingCallRanges = relations.map(relation => relation.getRangeOf(verb));
|
||||
let verbItem = this.createCallHierarchyItem(verb, 'verb', document, outgoingCallRanges[0]);
|
||||
let outgoingCallItem = new CallHierarchyOutgoingCall(verbItem, outgoingCallRanges);
|
||||
outgoingCallItems.push(outgoingCallItem);
|
||||
});
|
||||
}
|
||||
|
||||
return outgoingCallItems;
|
||||
}
|
||||
|
||||
async provideCallHierarchyIncomingCalls(item: CallHierarchyItem, token: CancellationToken): Promise<CallHierarchyIncomingCall[]> {
|
||||
let document = await workspace.openTextDocument(item.uri);
|
||||
let parser = new FoodPyramidParser();
|
||||
parser.parse(document);
|
||||
let model = parser.getModel();
|
||||
let originRelation = model.getRelationAt(item.range);
|
||||
|
||||
let outgoingCallItems: CallHierarchyIncomingCall[] = [];
|
||||
|
||||
if (model.isVerb(item.name)) {
|
||||
let outgoingCalls = model.getVerbRelations(item.name)
|
||||
.filter(relation => relation.object === originRelation!.object);
|
||||
|
||||
outgoingCalls.forEach(relation => {
|
||||
let outgoingCallRange = relation.getRangeOf(relation.subject);
|
||||
let verbItem = this.createCallHierarchyItem(relation.subject, 'noun', document, outgoingCallRange);
|
||||
let outgoingCallItem = new CallHierarchyIncomingCall(verbItem, [outgoingCallRange]);
|
||||
outgoingCallItems.push(outgoingCallItem);
|
||||
});
|
||||
}
|
||||
else if (model.isNoun(item.name)) {
|
||||
let outgoingCallMap = groupBy(model.getObjectRelations(item.name), relation => relation.verb);
|
||||
|
||||
outgoingCallMap.forEach((relations, verb) => {
|
||||
let outgoingCallRanges = relations.map(relation => relation.getRangeOf(verb));
|
||||
let verbItem = this.createCallHierarchyItem(verb, 'verb-inverted', document, outgoingCallRanges[0]);
|
||||
let outgoingCallItem = new CallHierarchyIncomingCall(verbItem, outgoingCallRanges);
|
||||
outgoingCallItems.push(outgoingCallItem);
|
||||
});
|
||||
}
|
||||
|
||||
return outgoingCallItems;
|
||||
}
|
||||
|
||||
private createCallHierarchyItem(word: string, type: string, document: TextDocument, range: Range): CallHierarchyItem {
|
||||
return new CallHierarchyItem(SymbolKind.Object, word, `(${type})`, document.uri, range, range);
|
||||
}
|
||||
|
||||
deriveCalledItem(item: CallHierarchyItem, called: string, document: TextDocument): CallHierarchyOutgoingCall {
|
||||
const range = this.rangeOf(called, document);
|
||||
let calledItem = new CallHierarchyItem(item.kind, called, called, item.uri, range, range);
|
||||
return new CallHierarchyOutgoingCall(calledItem, this.allRangesOf(called, document));
|
||||
}
|
||||
|
||||
rangeOf(word: string, document: TextDocument): Range {
|
||||
let match = new RegExp("\\b" + word + "\\b").exec(document.getText());
|
||||
let offset = match!.index;
|
||||
return this.toRange(document, offset, word);
|
||||
}
|
||||
|
||||
allRangesOf(word: string, document: TextDocument): Range[] {
|
||||
let pattern = new RegExp("\b" + word + "\b");
|
||||
let ranges: Range[] = [];
|
||||
|
||||
var match: RegExpExecArray | null;
|
||||
while (match = pattern.exec(document.getText())) {
|
||||
ranges.push(this.toRange(document, match.index, word));
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
private toRange(document: TextDocument, offset: number, word: string) {
|
||||
let position = document.positionAt(offset);
|
||||
return new Range(position, position.translate({ characterDelta: word.length }));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample parser of the document text into the [FoodPyramid](#FoodPyramid) model.
|
||||
*/
|
||||
class FoodPyramidParser {
|
||||
private model = new FoodPyramid();
|
||||
|
||||
getModel(): FoodPyramid {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
parse(textDocument: TextDocument): void {
|
||||
let pattern = /^(\w+)\s+(\w+)\s+(\w+).$/gm;
|
||||
let match: RegExpExecArray | null;
|
||||
while (match = pattern.exec(textDocument.getText())) {
|
||||
let startPosition = textDocument.positionAt(match.index);
|
||||
let range = new Range(startPosition, startPosition.translate({ characterDelta: match[0].length }));
|
||||
this.model.addRelation(new FoodRelation(match[1], match[2], match[3], match[0], range));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups array items by a field defined using a key selector.
|
||||
* @param array array to be grouped
|
||||
* @param keyGetter grouping key selector
|
||||
*/
|
||||
function groupBy<K, V>(array: Array<V>, keyGetter: (value: V) => K): Map<K, V[]> {
|
||||
const map = new Map();
|
||||
array.forEach((item) => {
|
||||
const key = keyGetter(item);
|
||||
const groupForKey = map.get(key) || [];
|
||||
groupForKey.push(item);
|
||||
map.set(key, groupForKey);
|
||||
});
|
||||
return map;
|
||||
}
|
||||
29
call-hierarchy-sample/src/extension.ts
Normal file
29
call-hierarchy-sample/src/extension.ts
Normal file
@ -0,0 +1,29 @@
|
||||
// The module 'vscode' contains the VS Code extensibility API
|
||||
// Import the module and reference it with the alias vscode in your code below
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import { FoodPyramidHierarchyProvider } from './FoodPyramidHierarchyProvider';
|
||||
|
||||
// this method is called when your extension is activated
|
||||
// your extension is activated the very first time the command is executed
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
// Use the console to output diagnostic information (console.log) and errors (console.error)
|
||||
// This line of code will only be executed once when your extension is activated
|
||||
console.log('Congratulations, your extension "call-hierarchy-sample" is now active!');
|
||||
|
||||
let disposable = vscode.languages.registerCallHierarchyProvider('plaintext', new FoodPyramidHierarchyProvider());
|
||||
|
||||
context.subscriptions.push(disposable);
|
||||
|
||||
showSampleText(context);
|
||||
}
|
||||
|
||||
async function showSampleText(context: vscode.ExtensionContext): Promise<void> {
|
||||
fs.readFile(context.asAbsolutePath('sample.txt'), async (err, sampleText) => {
|
||||
let doc = await vscode.workspace.openTextDocument({ language: 'plaintext', content: sampleText.toString("utf-8") });
|
||||
vscode.window.showTextDocument(doc);
|
||||
});
|
||||
}
|
||||
|
||||
// this method is called when your extension is deactivated
|
||||
export function deactivate() { }
|
||||
91
call-hierarchy-sample/src/model.ts
Normal file
91
call-hierarchy-sample/src/model.ts
Normal file
@ -0,0 +1,91 @@
|
||||
import {
|
||||
Range, Position, CallHierarchyProvider, TextDocument, CancellationToken, CallHierarchyItem,
|
||||
SymbolKind, ProviderResult, CallHierarchyIncomingCall, CallHierarchyOutgoingCall, workspace, Uri
|
||||
} from 'vscode';
|
||||
|
||||
/**
|
||||
* Sample model of what the text in the document contains.
|
||||
*/
|
||||
export class FoodPyramid {
|
||||
private relations: FoodRelation[] = [];
|
||||
private nouns = new Set<string>();
|
||||
private verbs = new Set<string>();
|
||||
|
||||
getRelationAt(wordRange: Range): FoodRelation | undefined {
|
||||
return this.relations.find(relation => relation.range.contains(wordRange));
|
||||
}
|
||||
|
||||
addRelation(relation: FoodRelation): void {
|
||||
this.relations.push(relation);
|
||||
this.nouns.add(relation.object).add(relation.subject);
|
||||
this.verbs.add(relation.verb);
|
||||
}
|
||||
|
||||
isVerb(name: string): boolean {
|
||||
return this.verbs.has(name.toLowerCase());
|
||||
}
|
||||
|
||||
isNoun(name: string): boolean {
|
||||
return this.nouns.has(name.toLowerCase());
|
||||
}
|
||||
|
||||
getVerbRelations(verb: string): FoodRelation[] {
|
||||
return this.relations
|
||||
.filter(relation => relation.verb === verb.toLowerCase());
|
||||
}
|
||||
|
||||
getNounRelations(noun: string): FoodRelation[] {
|
||||
return this.relations
|
||||
.filter(relation => relation.involves(noun));
|
||||
}
|
||||
|
||||
getSubjectRelations(subject: string): FoodRelation[] {
|
||||
return this.relations
|
||||
.filter(relation => relation.subject === subject.toLowerCase());
|
||||
}
|
||||
|
||||
getObjectRelations(object: string): FoodRelation[] {
|
||||
return this.relations
|
||||
.filter(relation => relation.object === object.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Model element.
|
||||
*/
|
||||
export class FoodRelation {
|
||||
private _subject: string;
|
||||
private _verb: string;
|
||||
private _object: string;
|
||||
|
||||
constructor(subject: string, verb: string, object: string,
|
||||
private readonly originalText: string, public readonly range: Range) {
|
||||
|
||||
this._subject = subject.toLowerCase();
|
||||
this._verb = verb.toLowerCase();
|
||||
this._object = object.toLowerCase();
|
||||
}
|
||||
|
||||
get subject(): string {
|
||||
return this._subject;
|
||||
}
|
||||
|
||||
get object(): string {
|
||||
return this._object;
|
||||
}
|
||||
|
||||
get verb(): string {
|
||||
return this._verb;
|
||||
}
|
||||
|
||||
involves(noun: string): boolean {
|
||||
let needle = noun.toLowerCase();
|
||||
return this._subject === needle || this._object === needle;
|
||||
}
|
||||
|
||||
getRangeOf(word: string): Range {
|
||||
let indexOfWord = new RegExp("\\b" + word + "\\b", "i").exec(this.originalText)!.index;
|
||||
return new Range(this.range.start.translate({ characterDelta: indexOfWord }),
|
||||
this.range.start.translate({ characterDelta: indexOfWord + word.length }));
|
||||
}
|
||||
}
|
||||
11
call-hierarchy-sample/tsconfig.json
Normal file
11
call-hierarchy-sample/tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"outDir": "out",
|
||||
"sourceMap": true,
|
||||
"rootDir": "src",
|
||||
"strict": true
|
||||
},
|
||||
"exclude": ["node_modules", ".vscode-test"]
|
||||
}
|
||||
6
call-hierarchy-sample/tslint.json
Normal file
6
call-hierarchy-sample/tslint.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"rules": {
|
||||
"indent": [true, "tabs"],
|
||||
"semicolon": [true, "always"]
|
||||
}
|
||||
}
|
||||
6
progress-sample/package-lock.json
generated
6
progress-sample/package-lock.json
generated
@ -308,9 +308,9 @@
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.4.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz",
|
||||
"integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==",
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz",
|
||||
"integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==",
|
||||
"dev": true
|
||||
},
|
||||
"wrappy": {
|
||||
|
||||
@ -2,41 +2,82 @@
|
||||
* Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { ExtensionContext, StatusBarAlignment, window, StatusBarItem, Selection, workspace, TextEditor, commands, ProgressLocation } from 'vscode';
|
||||
import { ExtensionContext, window, commands, ProgressLocation, CancellationToken, Progress } from 'vscode';
|
||||
import { spawn, spawnSync } from 'child_process';
|
||||
|
||||
export function activate(context: ExtensionContext) {
|
||||
context.subscriptions.push(commands.registerCommand('extension.startTask', () => {
|
||||
context.subscriptions.push(commands.registerCommand('extension.askMode', () => {
|
||||
return window.showQuickPick(['sync', 'async'], { placeHolder: 'Pick mode...' });
|
||||
}));
|
||||
context.subscriptions.push(commands.registerCommand('extension.startTask', async () => {
|
||||
let mode = await commands.executeCommand('extension.askMode');
|
||||
window.withProgress({
|
||||
location: ProgressLocation.Notification,
|
||||
title: "I am long running!",
|
||||
title: "I am long running",
|
||||
cancellable: true
|
||||
}, (progress, token) => {
|
||||
}, async (progress, token) => {
|
||||
token.onCancellationRequested(() => {
|
||||
console.log("User canceled the long running operation");
|
||||
});
|
||||
|
||||
progress.report({ increment: 0 });
|
||||
|
||||
setTimeout(() => {
|
||||
progress.report({ increment: 10, message: "I am long running! - still going..." });
|
||||
}, 1000);
|
||||
|
||||
setTimeout(() => {
|
||||
progress.report({ increment: 40, message: "I am long running! - still going even more..." });
|
||||
}, 2000);
|
||||
|
||||
setTimeout(() => {
|
||||
progress.report({ increment: 50, message: "I am long running! - almost there..." });
|
||||
}, 3000);
|
||||
|
||||
var p = new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
return p;
|
||||
switch (mode) {
|
||||
case undefined:
|
||||
return; // canceled by the user
|
||||
case 'sync':
|
||||
return spawnSomethingSync(token);
|
||||
case 'async':
|
||||
default:
|
||||
return spawnSomethingAsync(progress, token);
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronous approach
|
||||
* @param _token cancellation token (unused in the sync approach)
|
||||
*/
|
||||
function spawnSomethingSync(_token: CancellationToken): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
console.log('Started...');
|
||||
let child = spawnSync('cmd', ['/c', 'dir', '/S'], { cwd: 'c:\\', encoding: 'utf8' });
|
||||
console.log(`stdout: ${child.stdout.slice(0, 1000)}`); // otherwise it is too big for the console
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous approach
|
||||
* @param token cancellation token (triggered by the cancel button on the UI)
|
||||
*/
|
||||
function spawnSomethingAsync(progress: Progress<{ message?: string; increment?: number }>, token: CancellationToken): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
var progressUpdate = 'Starting up...';
|
||||
const interval = setInterval(() => progress.report({ message: progressUpdate }), 500);
|
||||
|
||||
let childProcess = spawn('cmd', ['/c', 'dir', '/S'], { cwd: 'C:\\Users\\jdolejsi\\AppData\\' })
|
||||
.on("close", (code, signal) => {
|
||||
console.log(`Closed: ${code} ${signal}`);
|
||||
if (childProcess.killed) { console.log('KILLED'); }
|
||||
resolve();
|
||||
clearInterval(interval);
|
||||
})
|
||||
.on("error", err => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
childProcess.stdout
|
||||
.on("data", (chunk: string | Buffer) => {
|
||||
console.log(`stdout: ${chunk}`);
|
||||
progressUpdate = chunk.toString('utf8', 0, 50).replace(/[\r\n]/g, '');
|
||||
});
|
||||
|
||||
token.onCancellationRequested(_ => childProcess.kill());
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user