├── .gitattributes
├── .gitignore
├── .vscode
├── launch.json
├── settings.json
└── tasks.json
├── .vscodeignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── basic.language-configuration.json
├── bliss.language-configuration.json
├── cld.language-configuration.json
├── cobol.language-configuration.json
├── fortran.language-configuration.json
├── gulpfile.js
├── i18n
└── ru
│ ├── cld
│ ├── AnalysisListener.i18n.json
│ ├── SourceContext.i18n.json
│ ├── Symbol.i18n.json
│ └── extension.i18n.json
│ ├── config-helper
│ ├── config
│ │ ├── config-api.i18n.json
│ │ └── config-pool.i18n.json
│ └── extension.i18n.json
│ ├── extension.i18n.json
│ ├── msg
│ ├── AnalysisListener.i18n.json
│ ├── SourceContext.i18n.json
│ ├── Symbol.i18n.json
│ └── extension.i18n.json
│ ├── package.i18n.json
│ ├── python
│ ├── debugSession.i18n.json
│ ├── extension.i18n.json
│ ├── provider.i18n.json
│ └── runtime.i18n.json
│ ├── ssh-helper
│ ├── config-resolve
│ │ ├── connect-config-resolver-impl.i18n.json
│ │ ├── password-console-filler.i18n.json
│ │ └── password-vscode-filler.i18n.json
│ ├── extension.i18n.json
│ ├── ssh-helper.i18n.json
│ └── stream
│ │ ├── parse-welcome-vms.i18n.json
│ │ ├── parse-welcome.i18n.json
│ │ ├── pipe.i18n.json
│ │ ├── sftp-client.i18n.json
│ │ ├── shell-parser.i18n.json
│ │ ├── ssh-client.i18n.json
│ │ └── ssh-shell.i18n.json
│ ├── synchronizer
│ ├── build
│ │ └── builder.i18n.json
│ ├── common
│ │ └── find-files.i18n.json
│ ├── dep-tree
│ │ └── project-descr.i18n.json
│ ├── downloadHeaders.i18n.json
│ ├── ensure-settings.i18n.json
│ ├── extension.i18n.json
│ ├── performer.i18n.json
│ ├── scopeWatchers.i18n.json
│ ├── sync
│ │ ├── fs-source.i18n.json
│ │ └── synchronizer.i18n.json
│ └── upload-zip.i18n.json
│ ├── vms_basic
│ └── context
│ │ └── SourceContext.i18n.json
│ ├── vms_cobol
│ ├── context
│ │ ├── CobolAnalisisHelpers.i18n.json
│ │ ├── CobolAnalysisVisitor.i18n.json
│ │ └── CobolSourceContext.i18n.json
│ ├── extension.i18n.json
│ └── stream
│ │ └── cobolInputStream.i18n.json
│ ├── vms_debug
│ ├── debug
│ │ ├── vms_runtime.i18n.json
│ │ └── vms_runtime_run.i18n.json
│ ├── extension.i18n.json
│ ├── net
│ │ └── shell-session.i18n.json
│ └── parsers
│ │ └── debug_module_info.i18n.json
│ ├── vms_fortran
│ └── context
│ │ └── SourceContext.i18n.json
│ ├── vms_jvm_debug
│ ├── extension.i18n.json
│ ├── jvm-debug-session.i18n.json
│ ├── jvm-proj-helper.i18n.json
│ ├── jvm-project.i18n.json
│ └── jvm-shell-runtime.i18n.json
│ └── vms_pascal
│ └── context
│ └── SourceContext.i18n.json
├── images
├── mock-debug-icon.png
├── vms_128x128_v2.png
└── vms_logo.png
├── make_async.txt
├── media
├── dep.png
└── dep.svg
├── mms.language-configuration.json
├── msg.language-configuration.json
├── package.json
├── package.nls.json
├── package.nls.ru.json
├── pascal.language-configuration.json
├── python
├── server.py
└── tracer.py
├── readme.txt
├── resources
├── build_1.png
├── build_28x28.png
├── dark
│ ├── boolean.svg
│ ├── dependency.svg
│ ├── document.svg
│ ├── folder.svg
│ ├── number.svg
│ ├── refresh.svg
│ └── string.svg
├── default.mms
├── light
│ ├── boolean.svg
│ ├── dependency.svg
│ ├── document.svg
│ ├── folder.svg
│ ├── number.svg
│ ├── refresh.svg
│ └── string.svg
├── package-explorer.png
├── ssh_schema.json
├── static.mms
└── synch_schema.json
├── src
├── cld
│ ├── AnalysisListener.ts
│ ├── CompletionProvider.ts
│ ├── ContextErrorListener.ts
│ ├── ContextSymbolTable.ts
│ ├── DefinitionProvider.ts
│ ├── DetailsListener.ts
│ ├── Facade.ts
│ ├── HoverProvider.ts
│ ├── ReferenceProvider.ts
│ ├── RenameProvider.ts
│ ├── SourceContext.ts
│ ├── Symbol.ts
│ ├── cld.g4
│ ├── cld.interp
│ ├── cld.tokens
│ ├── cldLexer.interp
│ ├── cldLexer.tokens
│ ├── cldLexer.ts
│ ├── cldListener.ts
│ ├── cldParser.ts
│ ├── cldVisitor.ts
│ └── extension.ts
├── common
│ ├── async-task-queue.ts
│ ├── barrier.ts
│ ├── bsearch.ts
│ ├── correspondLines.ts
│ ├── cr-lf-trimmed-eq.ts
│ ├── debouncer.ts
│ ├── delay.ts
│ ├── directory.ts
│ ├── iterators.ts
│ ├── lock.ts
│ ├── log-type.ts
│ ├── log.ts
│ ├── main.ts
│ ├── mem-reader.ts
│ ├── mem-writer.ts
│ ├── parser
│ │ ├── CompletionProvider.ts
│ │ ├── DefinitionProvider.ts
│ │ ├── ErrorListeners.ts
│ │ ├── Facade.ts
│ │ ├── HoverProvider.ts
│ │ ├── ReferenceProvider.ts
│ │ ├── RenameProvider.ts
│ │ └── helpers.ts
│ ├── print-like.ts
│ ├── print-syntax-tree.ts
│ ├── quotes.ts
│ ├── read_all_stream.ts
│ ├── resolve.ts
│ ├── rgx-from-str.ts
│ ├── simply-compare.ts
│ ├── subscribe.ts
│ ├── task-count.ts
│ ├── task-divider.ts
│ ├── wait-fire-event-emitter.ts
│ └── waitable-operation.ts
├── config-helper
│ ├── command-context.ts
│ ├── config
│ │ ├── config-api.ts
│ │ ├── config-hepler-section.ts
│ │ ├── config-pool.ts
│ │ ├── config.ts
│ │ ├── dummy-editor.ts
│ │ ├── dummy-storage.ts
│ │ ├── fs-config-helper.ts
│ │ ├── fs-storage.ts
│ │ ├── storage-impl.ts
│ │ ├── uri-editor.ts
│ │ ├── vfs-config-helper.ts
│ │ ├── vfs-storage.ts
│ │ ├── vsc-config-helper.ts
│ │ ├── vsc-editor.ts
│ │ └── vsc-storage.ts
│ ├── extension.ts
│ └── log.ts
├── ext-api
│ └── ext-api.ts
├── extension.ts
├── msg
│ ├── AnalysisListener.ts
│ ├── CompletionProvider.ts
│ ├── ContextErrorListener.ts
│ ├── ContextSymbolTable.ts
│ ├── DefinitionProvider.ts
│ ├── Facade.ts
│ ├── HoverProvider.ts
│ ├── RenameProvider.ts
│ ├── SourceContext.ts
│ ├── Symbol.ts
│ ├── extension.ts
│ ├── msg.g4
│ ├── msg.interp
│ ├── msg.tokens
│ ├── msgLex.g4
│ ├── msgLex.interp
│ ├── msgLex.tokens
│ ├── msgLex.ts
│ ├── msgListener.ts
│ ├── msgParser.ts
│ └── msgVisitor.ts
├── python
│ ├── debugConfig.ts
│ ├── debugSession.ts
│ ├── extension.ts
│ ├── provider.ts
│ └── runtime.ts
├── ssh-helper
│ ├── api.ts
│ ├── config-api.ts
│ ├── config-resolve
│ │ ├── agent-filler.ts
│ │ ├── connect-config-resolver-impl.ts
│ │ ├── context-password-filler.ts
│ │ ├── host-filler.ts
│ │ ├── key-filler.ts
│ │ ├── password-console-filler.ts
│ │ ├── password-filler.ts
│ │ ├── password-vscode-filler.ts
│ │ └── settings-filler.ts
│ ├── config
│ │ └── sections
│ │ │ ├── connection.ts
│ │ │ ├── hosts.ts
│ │ │ ├── labeled-connection.ts
│ │ │ ├── terminal.ts
│ │ │ └── timeouts.ts
│ ├── extension.ts
│ ├── ssh-helper.ts
│ ├── stream
│ │ ├── parse-welcome-vms.ts
│ │ ├── parse-welcome.ts
│ │ ├── pipe.ts
│ │ ├── prompt-catcher-vms.ts
│ │ ├── prompt-catcher.ts
│ │ ├── sftp-client.ts
│ │ ├── shell-parser.ts
│ │ ├── ssh-client.ts
│ │ ├── ssh-shell.ts
│ │ └── stream-creators.ts
│ └── test
│ │ ├── config-resolver.test.ts
│ │ ├── config
│ │ └── config.ts
│ │ ├── lock.test.ts
│ │ ├── sftp-pipe.test.ts
│ │ ├── sftp-shell-transform.test.ts
│ │ └── sftp-shell.test.ts
├── synchronizer
│ ├── build
│ │ └── builder.ts
│ ├── change-crlf.ts
│ ├── command-context.ts
│ ├── common
│ │ ├── TestExecResult.ts
│ │ ├── create-file.ts
│ │ ├── find-files.ts
│ │ ├── parse-output.ts
│ │ └── progress.ts
│ ├── config
│ │ └── sections
│ │ │ ├── builds.ts
│ │ │ ├── project.ts
│ │ │ └── synchronize.ts
│ ├── context.ts
│ ├── dep-tree
│ │ ├── dep-tree.ts
│ │ ├── proj-dep-tree.ts
│ │ ├── proj-state.ts
│ │ ├── project-dep.ts
│ │ └── project-descr.ts
│ ├── downloadHeaders.ts
│ ├── ensure-settings.ts
│ ├── extension.ts
│ ├── on-the-same-vms.ts
│ ├── performer.ts
│ ├── projectDepend.ts
│ ├── scopeWatchers.ts
│ ├── sync
│ │ ├── fs-source.ts
│ │ ├── sftp-source.ts
│ │ ├── source.ts
│ │ ├── sync-api.ts
│ │ ├── synchronizer.ts
│ │ ├── vms-sftp-client.ts
│ │ └── vms-shell-source.ts
│ ├── test
│ │ ├── config
│ │ │ └── vms.ts
│ │ ├── find-files.test.ts
│ │ ├── problem.test.ts
│ │ ├── sftp-readdir.test.ts
│ │ └── source.test.ts
│ ├── upload-zip.ts
│ └── vms
│ │ ├── vms-absolute-date-string.ts
│ │ └── vms-path-converter.ts
├── task2cmd
│ ├── extension.ts
│ └── task2cmd-prov.ts
├── test
│ ├── .gitignore
│ ├── a.a.test.ts
│ ├── a.diff.test.ts
│ ├── cobol-unit.test.ts
│ ├── cobol.test.ts
│ ├── lock.test.ts
│ ├── long.test.ts
│ └── quotes.test.ts
├── vms_basic
│ ├── context
│ │ ├── AnalysisListener.ts
│ │ ├── ContextErrorListener.ts
│ │ ├── ContextSymbolTable.ts
│ │ ├── DetailsListener.ts
│ │ ├── Facade.ts
│ │ ├── SourceContext.ts
│ │ └── Symbol.ts
│ ├── ext_api
│ │ └── config_manager.ts
│ ├── extension.ts
│ ├── parser
│ │ ├── BasicLexer.g4
│ │ ├── BasicLexer.interp
│ │ ├── BasicLexer.tokens
│ │ ├── BasicLexer.ts
│ │ ├── BasicParser.g4
│ │ ├── BasicParser.interp
│ │ ├── BasicParser.tokens
│ │ ├── BasicParser.ts
│ │ ├── BasicParserListener.ts
│ │ └── BasicParserVisitor.ts
│ └── providers
│ │ ├── CompletionProvider.ts
│ │ ├── DefinitionProvider.ts
│ │ ├── HoverProvider.ts
│ │ ├── ReferenceProvider.ts
│ │ └── RenameProvider.ts
├── vms_cobol
│ ├── context
│ │ ├── CobolAnalisisHelpers.ts
│ │ ├── CobolAnalysisVisitor.ts
│ │ ├── CobolBackground.ts
│ │ ├── CobolDetailsListener.ts
│ │ ├── CobolGlobals.ts
│ │ ├── CobolSourceContext.ts
│ │ ├── CobolSymbol.ts
│ │ └── CobolSymbolTable.ts
│ ├── extension.ts
│ ├── parser
│ │ ├── cobol.g4
│ │ ├── cobol.interp
│ │ ├── cobol.tokens
│ │ ├── cobolCopy.g4
│ │ ├── cobolCopy.interp
│ │ ├── cobolCopy.tokens
│ │ ├── cobolCopyLexer.interp
│ │ ├── cobolCopyLexer.tokens
│ │ ├── cobolCopyLexer.ts
│ │ ├── cobolCopyListener.ts
│ │ ├── cobolCopyParser.ts
│ │ ├── cobolCopyVisitor.ts
│ │ ├── cobolLexer.g4
│ │ ├── cobolLexer.interp
│ │ ├── cobolLexer.tokens
│ │ ├── cobolLexer.ts
│ │ ├── cobolListener.ts
│ │ ├── cobolParser.ts
│ │ ├── cobolParserImpl.ts
│ │ └── cobolVisitor.ts
│ ├── stream
│ │ ├── CopyManagerImpl.ts
│ │ ├── CopyManagers.ts
│ │ └── cobolInputStream.ts
│ └── test
│ │ └── test.cob
├── vms_debug
│ ├── command
│ │ ├── debug_commands.ts
│ │ └── os_commands.ts
│ ├── debug
│ │ ├── vms_debug.ts
│ │ ├── vms_debug_run.ts
│ │ ├── vms_runtime.ts
│ │ └── vms_runtime_run.ts
│ ├── ext-api
│ │ └── config_manager.ts
│ ├── extension.ts
│ ├── net
│ │ ├── shell-parser.ts
│ │ └── shell-session.ts
│ ├── parsers
│ │ ├── debug_file_info.ts
│ │ ├── debug_module_info.ts
│ │ ├── debug_parser.ts
│ │ └── debug_variable_info.ts
│ ├── queue
│ │ └── queues.ts
│ └── ui
│ │ ├── status_bar.ts
│ │ └── terminal.ts
├── vms_fortran
│ ├── context
│ │ ├── AnalysisListener.ts
│ │ ├── ContextErrorListener.ts
│ │ ├── ContextSymbolTable.ts
│ │ ├── DetailsListener.ts
│ │ ├── Facade.ts
│ │ ├── SourceContext.ts
│ │ └── Symbol.ts
│ ├── ext_api
│ │ └── config_manager.ts
│ ├── extension.ts
│ ├── parser
│ │ ├── FortranLexer.g4
│ │ ├── FortranLexer.interp
│ │ ├── FortranLexer.tokens
│ │ ├── FortranLexer.ts
│ │ ├── FortranParser.g4
│ │ ├── FortranParser.interp
│ │ ├── FortranParser.tokens
│ │ ├── FortranParser.ts
│ │ ├── FortranParserListener.ts
│ │ └── FortranParserVisitor.ts
│ └── providers
│ │ ├── CompletionProvider.ts
│ │ ├── DefinitionProvider.ts
│ │ ├── HoverProvider.ts
│ │ ├── ReferenceProvider.ts
│ │ └── RenameProvider.ts
├── vms_jvm_debug
│ ├── cmd-queue.ts
│ ├── communication.ts
│ ├── drop.ts
│ ├── extension.ts
│ ├── jvm-config.ts
│ ├── jvm-debug-session.ts
│ ├── jvm-proj-helper.ts
│ ├── jvm-project.ts
│ ├── jvm-shell-runtime.ts
│ ├── jvm-state-machine.ts
│ ├── shell-splitter.ts
│ ├── simple-cmd-client.ts
│ └── ssh-shell-server.ts
├── vms_pascal
│ ├── context
│ │ ├── AnalysisListener.ts
│ │ ├── ContextErrorListener.ts
│ │ ├── ContextSymbolTable.ts
│ │ ├── DetailsListener.ts
│ │ ├── Facade.ts
│ │ ├── SourceContext.ts
│ │ └── Symbol.ts
│ ├── ext_api
│ │ └── config_manager.ts
│ ├── extension.ts
│ ├── parser
│ │ ├── pascal.g4
│ │ ├── pascal.interp
│ │ ├── pascal.tokens
│ │ ├── pascalLexer.interp
│ │ ├── pascalLexer.tokens
│ │ ├── pascalLexer.ts
│ │ ├── pascalListener.ts
│ │ ├── pascalParser.ts
│ │ └── pascalVisitor.ts
│ └── providers
│ │ ├── CompletionProvider.ts
│ │ ├── DefinitionProvider.ts
│ │ ├── HoverProvider.ts
│ │ ├── ReferenceProvider.ts
│ │ └── RenameProvider.ts
└── zip
│ ├── extension.ts
│ └── zip-api.ts
├── syntaxes
├── basic.tmLanguage.json
├── bliss.tmLanguage.json
├── cld.tmLanguage.json
├── fortran.tmLanguage.json
├── mms.tmLanguage.json
├── msg.tmLanguage.json
├── pascal.tmLanguage.json
└── vms-cobol.tmLanguage.json
├── tsconfig.json
├── tslint.json
└── webpack.config.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set default behavior to automatically normalize line endings.
2 | * text=auto
3 |
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | node_modules
3 | .vscode-test/
4 | .ropeproject/
5 | *.vsix
6 | *.zip
7 | package-lock.json
8 | # autogenerated files
9 | **/.antlr/*
10 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "vmssoftware.project-dep.buildName": "DEBUG",
3 | "search.exclude": {
4 | "**/node_modules": false
5 | },
6 | "search.useGlobalIgnoreFiles": true,
7 | "search.useIgnoreFiles": false
8 | }
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/test/**
4 | out/**/*.map
5 | out/**/*.js
6 | out/**/*.ts
7 | src/**
8 | .gitignore
9 | tsconfig.json
10 | vsc-extension-quickstart.md
11 | tslint.json
12 | gulpfile.js
13 | webpack.config.js
14 | i18n
15 | !out/index.js
16 | node_modules
17 | *.zip
18 | package-lock.json
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 VMS Software, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/basic.language-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | "lineComment": "!",
4 | "blockComment": [ "!", "!" ]
5 | },
6 | "wordPattern": "[a-zA-Z][a-zA-Z$_0-9\\.]*[$%]?",
7 | "brackets": [
8 | ["(", ")"],
9 | ["[", "]"],
10 | ],
11 | "autoClosingPairs": [
12 | ["(", ")"],
13 | ["[", "]"],
14 | ["\"", "\""],
15 | ["'", "'"]
16 | ],
17 | "surroundingPairs": [
18 | ["(", ")"],
19 | ["[", "]"],
20 | ["\"", "\""],
21 | ["'", "'"]
22 | ]
23 | }
--------------------------------------------------------------------------------
/bliss.language-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | "lineComment": "!",
4 | "blockComment": [ "%(", ")%" ]
5 | },
6 | "wordPattern": "[a-zA-Z$_][a-zA-Z$_0-9]*",
7 | "brackets": [
8 | ["(", ")"],
9 | ["[", "]"],
10 | ["<", ">"],
11 | ["begin", "end"]
12 | ],
13 | "autoClosingPairs": [
14 | ["(", ")"],
15 | ["\"", "\""],
16 | ["'", "'"]
17 | ],
18 | "surroundingPairs": [
19 | ["(", ")"],
20 | ["\"", "\""],
21 | ["'", "'"]
22 | ]
23 | }
--------------------------------------------------------------------------------
/cld.language-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | "lineComment": "!"
4 | },
5 | "brackets": [
6 | ["(", ")"]
7 | ],
8 | "autoClosingPairs": [
9 | ["(", ")"],
10 | ["\"", "\""],
11 | ["'", "'"]
12 | ],
13 | "surroundingPairs": [
14 | ["(", ")"],
15 | ["\"", "\""],
16 | ["'", "'"]
17 | ]
18 | }
--------------------------------------------------------------------------------
/cobol.language-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | "lineComment": "*>"
4 | },
5 | "brackets": [
6 | [
7 | "[",
8 | "]"
9 | ],
10 | [
11 | "(",
12 | ")"
13 | ],
14 | [
15 | "\"",
16 | "\""
17 | ],
18 | [
19 | "'",
20 | "'"
21 | ]
22 | ],
23 | "autoClosingPairs": [
24 | {
25 | "open": "[",
26 | "close": "]"
27 | },
28 | {
29 | "open": "(",
30 | "close": ")"
31 | },
32 | {
33 | "open": "'",
34 | "close": "'",
35 | "notIn": [
36 | "string",
37 | "comment"
38 | ]
39 | },
40 | {
41 | "open": "\"",
42 | "close": "\"",
43 | "notIn": [
44 | "string",
45 | "comment"
46 | ]
47 | }
48 | ],
49 | "surroundingPairs": [
50 | [
51 | "{",
52 | "}"
53 | ],
54 | [
55 | "[",
56 | "]"
57 | ],
58 | [
59 | "(",
60 | ")"
61 | ],
62 | [
63 | "\"",
64 | "\""
65 | ],
66 | [
67 | "'",
68 | "'"
69 | ]
70 | ],
71 | "folding": {
72 | "markers": {
73 | "start": "^\\s*\\$region\\b",
74 | "end": "^\\s*\\$end-region\\b"
75 | }
76 | },
77 | "wordPattern": "[$a-zA-Z0-9_]([-$a-zA-Z0-9_]*[$a-zA-Z0-9_])?"
78 | }
79 |
--------------------------------------------------------------------------------
/fortran.language-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "wordPattern": "[a-zA-Z][a-zA-Z0-9_$]*",
3 | "comments": {
4 | "lineComment": "!"
5 | },
6 | "brackets": [
7 | [
8 | "[",
9 | "]"
10 | ],
11 | [
12 | "(",
13 | ")"
14 | ],
15 | [
16 | "(/",
17 | "/)"
18 | ]
19 | ],
20 | "autoClosingPairs": [
21 | {
22 | "open": "[",
23 | "close": "]"
24 | },
25 | {
26 | "open": "(",
27 | "close": ")"
28 | },
29 | {
30 | "open": "(/",
31 | "close": "/)"
32 | }
33 | ],
34 | "surroundingPairs": [
35 | [
36 | "[",
37 | "]"
38 | ],
39 | [
40 | "(",
41 | ")"
42 | ],
43 | [
44 | "'",
45 | "'"
46 | ],
47 | [
48 | "\"",
49 | "\""
50 | ]
51 | ],
52 | "indentationRules": {
53 | "unIndentedLinePattern": "^\\s*!.*",
54 | "increaseIndentPattern": {
55 | "pattern": "then(\\s*|\\s*!.*)$|^\\s*(program|subroutine|function|module|do|block|associate|case|select\\s*case)\\b.*$|\\s*(else|else\\s*if|elsewhere)\\b.*$",
56 | "flags": "i"
57 | },
58 | "decreaseIndentPattern": {
59 | "pattern": "^\\s*end\\s*(select|if|do|function|subroutine|module|program)\\b.*$|^\\s*else|case\\b.*$",
60 | "flags": "i"
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/i18n/ru/cld/AnalysisListener.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "cannotFindDefine": "Невозможно найти DEFINE для данного элемента.",
3 | "cannotFindEntity": "Невозможно найти данный элемент или он двусмысленый.",
4 | "circularTypeRef": "Циклическая ссылка на тип.",
5 | "emptyParameterName": "Имя параметра не может быть пустым.",
6 | "entityHasNoChildren": "Элемент не имеет потомков.",
7 | "entityNotUnique": "Имя должно быть уникальным.",
8 | "entityOutside": "Элемент за пределами DEFINE.",
9 | "entityStartNameNotUnique": "Первые четыре символа имени должны быть уникальными.",
10 | "identStringTooLong": "Строка идентификации максимум 31 символ.",
11 | "imageStringTooLong": "Строка образа максимум 63 символа.",
12 | "invalidParameterName": "Имя параметра должно быть в виде Pn, где n - позиция параметра.",
13 | "invalidParameterNumber": "Имя параметра должно быть пронумеровано последовательно от P1 до P8.",
14 | "mutualDefaultOrRequired": "Выражения DEFAULT и REQUIRED взаимоисключающие.",
15 | "mutualImageOrRoutine": "Возможно только одно - или ROUTINE, или IMAGE.",
16 | "mutualQual": "Выражения NOQUALIFIERS и QUALIFIER взаимоисключающие.",
17 | "mutualDisallow": "Выражения NODISALLOWS и DISALLOW взаимоисключающие.",
18 | "mutualParameter": "Выражения NOPARAMETERS и PARAMETER взаимоисключающие.",
19 | "nameTooLong": "Имя максимум 31 символ.",
20 | "parameterPromptTooLong": "Параметр prompt максимум 31 символ.",
21 | "parameterValueDefaultStringTooLong": "Параметр default value максимум 94 символа.",
22 | "syntaxNotExists": "Не найдено SYNTAX для данного имени.",
23 | "tooManyKeywords": "Вы можете указать до 255 ключевых слов в выражении DEFINE TYPE.",
24 | "tooManyLabels": "Слишком много меток.",
25 | "tooManyQualifiers": "Вы можете использовать QUALIFIER до 255 раз в одном DEFINE.",
26 | "tooManyTypes": "Слишком много типов.",
27 | "typeNotExists": "Не найден TYPE для данного имени."
28 | }
--------------------------------------------------------------------------------
/i18n/ru/cld/SourceContext.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/i18n/ru/cld/Symbol.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/i18n/ru/cld/extension.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "config.notfound": "Не найден плагин vmssoftware.config-helper"
3 | }
--------------------------------------------------------------------------------
/i18n/ru/config-helper/config/config-api.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "message.created": "{0} создано"
3 | }
--------------------------------------------------------------------------------
/i18n/ru/config-helper/config/config-pool.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "config.filldata.failed": "чтение данных ('{0}') неудачно",
3 | "config.storedata.failed": "сохранение данных ('{0}') неудачно"
4 | }
--------------------------------------------------------------------------------
/i18n/ru/config-helper/extension.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/i18n/ru/extension.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/i18n/ru/msg/AnalysisListener.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "emptyBaseValue": "Базовый номер не может быть пустым.",
3 | "emptySeverity": "Попытка определить сообщение без указания степени тяжести",
4 | "emptyFacilityName": "Имя службы не может быть пустым.",
5 | "emptyTitleName": "Титульное имя не может быть пустым.",
6 | "emptyFaoCount": "Счётчик FAO не может быть пустым.",
7 | "emptyLiteralName": "Буквенное определение не может быть пустым.",
8 | "emptyMessageIdentification": "Идентификатор сообщения не может быть пустым.",
9 | "emptyMessageName": "Сообщение не может быть пустым.",
10 | "emptyPrefixValue": "Префикс службы не может быть пустым.",
11 | "emptyPrefixToken": "У сообщения должен быть префикс.",
12 | "emptyUserValue": "Пользовательское значение не может быть пустым.",
13 | "messageAlreadyExists": "Сообщение уже существует.",
14 | "messageSymbolAlreadyExists": "Символ сообщения уже существует.",
15 | "oneLine": "Нельзя продолжить текст на следующую строку.",
16 | "tooBigFaoCount": "Число должно быть десятичным от 0 до 255.",
17 | "tooBigMessageNumber": "Количество сообщений не может быть более 4095 и должно быть больше нуля.",
18 | "tooBigUserValue": "Число должно быть десятичным от 0 до 255.",
19 | "tooLongFacilityName": "Имя службы не более 9 символов.",
20 | "tooLongFacilityPrefix": "Маскимальная длина альтернативного префикса, созданного с помощью /PREFIX, составляет 9 символов.",
21 | "tooLongIdentValue": "Максимальная длина идентификатора 31 символ.",
22 | "tooLongIdentification": "Имя может включать до девяти символов.",
23 | "tooLongMessageName": "Общая длина префикса и имени сообщения не должно превышать 31 символ.",
24 | "tooLongMessageText": "Тескт может быть длиной до 255 байт.",
25 | "tooLongTitleDescription": "Титул листинга имеет максимальную длину 28 символов.",
26 | "tooLongTitleName": "Титульное имя имеет максимальную длину 31 символ.",
27 | "undefinedVariable": "Неопределённая переменная.",
28 | "messageFaoCountDiff": "Вероятно, счётчик FAO не верный."
29 | }
--------------------------------------------------------------------------------
/i18n/ru/msg/SourceContext.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "hexnum": "Шестнадцатиричное число",
3 | "octnum": "Восьмиричное число",
4 | "decnum": "Десятичное число"
5 | }
--------------------------------------------------------------------------------
/i18n/ru/msg/Symbol.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "keyword": "Ключевое слово",
3 | "operator": "Оператор",
4 | "literal": "Литера",
5 | "message": "Сообщение",
6 | "variable": "Переменная",
7 | "facility": "Имя службы",
8 | "prefix": "Префикс службы"
9 | }
--------------------------------------------------------------------------------
/i18n/ru/msg/extension.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "config.notfound": "Не найден плагин vmssoftware.config-helper"
3 | }
--------------------------------------------------------------------------------
/i18n/ru/python/debugSession.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "port.busy": "Порт {0} занят."
3 | }
--------------------------------------------------------------------------------
/i18n/ru/python/extension.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/i18n/ru/python/provider.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "msg.config.invalid": "Не верная конфигурация"
3 | }
--------------------------------------------------------------------------------
/i18n/ru/python/runtime.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/config-resolve/connect-config-resolver-impl.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.clearcache": "clearCache: delete {0}",
3 | "debug.killcache": "killCache: delete {0}",
4 | "debug.feedback": "feedBack: элемент {0} принят={1}",
5 | "debug.feedback.lock": "feedback: свободен {0}",
6 | "debug.feedback.already": "feedback: уже принят={0} {1}",
7 | "debug.feedback.no": "feedBack: нет узла {0}",
8 | "debug.resolve.start": "resolveConnectConfig: попытка для {0}",
9 | "debug.resolve.create_node": "resolveConnectConfig: создание узла {0}",
10 | "debug.resolve.lock": "resolveConnectConfig: блокирован {0}",
11 | "debug.resolve.first": "resolveConnectConfig: первый запрос {0}",
12 | "debug.resolve.filled": "resolveConnectConfig: заполнен {0}",
13 | "debug.resolve.didnt": "resolveConnectConfig: не заполнен {0}",
14 | "debug.resolve.unlock.nofeedback": "resolveConnectConfig: lock released (no feedback needed) {0}",
15 | "debug.resolve.timeout": "resolveConnectConfig: разблокирован по таймауту {0}",
16 | "debug.resolve.second": "resolveConnectConfig: второй и следующие запросы {0}",
17 | "debug.resolve.state": "resolveConnectConfig: принят={0} {1}",
18 | "debug.resolve.unlock.already": "resolveConnectConfig: lock released {0}",
19 | "debug.resolve.ret": "resolveConnectConfig: завершён {0}",
20 | "debug.resolve.start.test": "resolveConnectConfig: try {0}"
21 | }
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/config-resolve/password-console-filler.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "query.password": "Пароль для {0}@{1}:{2} "
3 | }
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/config-resolve/password-vscode-filler.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "query.password": "Пароль для {0}@{1}:{2} "
3 | }
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/extension.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | }
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/ssh-helper.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "ssh_helper.case_host": "Cannot find a host in list: {0}, did you mean {1}?",
3 | "ssh_helper.no_host": "Cannot find a host in list: {0}",
4 | "config.logResult.fail": "Settings: load operation failed",
5 | "config.logResult.prepare_failed": "Settings: cannot load data from storage",
6 | "config.logResult.some_data_failed": "Settings: failed to fill some data while loading"
7 | }
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/stream/parse-welcome-vms.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.tt": "vms парсер: найдена команда TTY {0}",
3 | "debug.terminal": "vms parse: setup terminal and wait next prompt",
4 | "debug.prompt": "vms парсер: найден промпт '{0}'"
5 | }
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/stream/parse-welcome.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.prompt": "парсер: найден промпт '{0}'"
3 | }
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/stream/pipe.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.source_fail": "не удалось создать источник {0}",
3 | "debug.source_error": "ошибка источника {0}",
4 | "debug.dest_fail": "не удалось создать приёмник {0}",
5 | "debug.dest_error": "ошибка приёмника {0}",
6 | "debug.dest_finished": "приёмник завершён",
7 | "debug.dest_closed": "приёмник закрыт",
8 | "debug.done": "завершено {0}",
9 | "debug.source_lost": "источник исчез"
10 | }
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/stream/sftp-client.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.read.err": "чтение stream{0} ошибка: {1}",
3 | "debug.write.err": "запись stream{0} ошибка: {1}",
4 | "operation.getstat": "get stat {0} через sftp{1}",
5 | "debug.operation.error": "{0} ошибка: {1}",
6 | "operation.delete": "delete {0} via sftp{1}",
7 | "operation.setstat": "set stat {0} через sftp{1}",
8 | "operation.readdir": "read directory {0} через sftp{1}",
9 | "operation.createdir": "create directory {0} через sftp{1}",
10 | "operation.sftp": "create sftp{0}",
11 | "debug.sftp.ready": "sftp{0} готов",
12 | "debug.sftp.end": "sftp{0} конец",
13 | "debug.sftp.error": "sftp{0} ошибка: {1}",
14 | "debug.sftp.close": "sftp{0} закрыт"
15 | }
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/stream/shell-parser.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.closed": "ShellParser{0}: закрыт",
3 | "debug.error": "ShellParser{1}: ошибка {0}",
4 | "debug.chunk": "ShellParser{0}: получены данные",
5 | "debug.nobuf": "ShellParser{0}: данные не Buffer",
6 | "debug.ready": "ShellParser{0}: готов",
7 | "debug.timeout": "ShellParser{0}: таймаут"
8 | }
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/stream/ssh-client.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.ready": "client{0} готов",
3 | "debug.end": "client{0} завершён",
4 | "debug.error": "client{1} ошибка: {0}",
5 | "connect.exception": "Exception: {0}",
6 | "debug.resolver": "не определена конфигурация {0}"
7 | }
--------------------------------------------------------------------------------
/i18n/ru/ssh-helper/stream/ssh-shell.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.cmd.error": "shell{1} ошибка команды: {0}",
3 | "debug.cmd.raw": "shell{1} сырые дынные команды: {0}",
4 | "debug.cmd.out": "shell{0} вывод команды найден",
5 | "debug.garbage": "shell{0} мусор",
6 | "debug.closed": "shell{0} канал закрыт",
7 | "debug.channel.exit": "shell{0} канал ушёл",
8 | "debug.written": "shell{1} команда записана: {0}",
9 | "debug.unpiped": "shell{0} парсер конца команды отсоединён",
10 | "debug.undef": "shell{0} канал неопределён при попытке отсоединения парсера конца команды",
11 | "debug.welcome": "shell{0} создание парсера приветствия по-умолчанию",
12 | "debug.prompt": "shell{0} создание парсера конца команды по-умолчанию",
13 | "debug.prompt.set": "shell{1} установка промпта '{0}' в парсер конца команды",
14 | "operation.connect": "создание shell{0}",
15 | "debug.operation.error": "{0} ошибка: {1}",
16 | "debug.ready": "shell{0} готов",
17 | "debug.close": "shell{0} закрыт",
18 | "debug.exit": "shell{1} вышел {0}",
19 | "debug.cleaned": "Shell{0} очищен"
20 | }
--------------------------------------------------------------------------------
/i18n/ru/synchronizer/build/builder.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.disposing": "Освобождение источников",
3 | "collect.no_class_for_file": "No class for this file match: {0}",
4 | "collect.no_method_for_line": "No method for this line match: {0}",
5 | "collect.no_class_for_main": "No class for this main function match: {0}",
6 | "collect.no_class_for_method": "No class for method: {0}",
7 | "collect.no_info": "No info for classes: {0}",
8 | "build.cfg": "There is no build configuration named {0}.",
9 | "check.inc.mask": "Please check listing file masks for correct curly brackets",
10 | "create.mms.first": "Сперва (пере)создайте MMS.",
11 | "output.cannot_exec": "Не удалось запустить {0}",
12 | "mms_exist": "Предыдущий MMS файл переименован в {0}",
13 | "opt_exist": "Предыдущий OPT файл переименован в {0}",
14 | "com_exist": "Предыдущий COM файл переименован в {0}",
15 | "cannot.clean": "Have no idea how to clean configuration: {0}",
16 | "cannot.build": "Have no idea how to build configuration: {0}",
17 | "too_many_files": "There are more than one file named {0}",
18 | "no_file": "Cannot find the file named {0}",
19 | "debug.cannot_get_ssh_helper": "Не удалось загрузить ssh-helper API",
20 | "output.install_ssh": "Установите плагин 'vmssoftware.ssh-helper'",
21 | "debug.create_shell": "Создание shell для компиляции"
22 | }
--------------------------------------------------------------------------------
/i18n/ru/synchronizer/common/find-files.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "check.inc.mask": "Проверьте маску include на правильность скобок",
3 | "check.exc.mask": "Проверьте маску include на правильность скобок"
4 | }
--------------------------------------------------------------------------------
/i18n/ru/synchronizer/dep-tree/project-descr.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "SSH": "SSH",
3 | "Project": "Проект",
4 | "Local": "Локально",
5 | "unknown": "Неизвестно",
6 | "modified": "Модифицирован",
7 | "synchronized": "Синхронизирован",
8 | "built": "Посторен",
9 | "not.built": "Не построен",
10 | "select.buildName": "Выберите конфигурацию для построения"
11 | }
--------------------------------------------------------------------------------
/i18n/ru/synchronizer/downloadHeaders.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "cd.failed": "Не удалось установить директорию",
3 | "ssh-helper.failed": "Расширение vmssoftware.ssh-helper не найдено.",
4 | "shell.failed": "Невозможно создать удалённый SHELL.",
5 | "no-result": "Не удалось выполнить команду для получения списка TLB файлов",
6 | "no-tlb": "Не найдены *.TLB файлы в папке SYS$LIBRARY",
7 | "create.failed": "Не удалось создать директорию",
8 | "file.extract.failed": "{0} was failed to unpack",
9 | "file.extracted": "Распакован: {0}",
10 | "del.failed": "Не удалось удалить временные файлы: {0}",
11 | "done": "Успешное завершение."
12 | }
--------------------------------------------------------------------------------
/i18n/ru/synchronizer/ensure-settings.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "config.logResult.fail": "Settings: load operation failed",
3 | "config.logResult.prepare_failed": "Settings: cannot load data from storage",
4 | "config.logResult.some_data_failed": "Settings: failed to fill some data while loading"
5 | }
--------------------------------------------------------------------------------
/i18n/ru/synchronizer/extension.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.activated": "Расширение 'VMS синхронизация' активировано",
3 | "scope.undefined": "Нет выделенного проекта в проводнике проектов",
4 | "debug.deactivated": "Расширение 'VMS синхронизация' выгружено"
5 | }
--------------------------------------------------------------------------------
/i18n/ru/synchronizer/scopeWatchers.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "check.inc.mask": "Проверьте маску include на корректность скобок",
3 | "check.exc.mask": "Проверьте маску exclude на корректность скобок"
4 | }
--------------------------------------------------------------------------------
/i18n/ru/synchronizer/sync/fs-source.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.no_date": "Нет даты файла {0}"
3 | }
--------------------------------------------------------------------------------
/i18n/ru/synchronizer/sync/synchronizer.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug.disposing": "Освобождение ресурсов",
3 | "output.download_manually": "Удалённый файл {0} новее, проверьте и загрузите его самостоятельно",
4 | "output.edit_count": "Отредактируйте и сохраните {0} файл(ов) самостоятельно",
5 | "cannot.find.remote": "Cannot find files on remote source",
6 | "cannot.find.local": "Cannot find files on local source",
7 | "debug.retcode": "Синхронизация вернула: {0}",
8 | "debug.quick.delete": "Delete remote file failed: {0}",
9 | "debug.quick.delete.ok": "Remote file deleted: {0}",
10 | "quick.failed": "Quick uploading failed. Please execute full synchronization or uploading.",
11 | "debug.quick.retcode": "Quick uploading: {0}",
12 | "debug.upload.error": "Ошибка при выгрузке {0}",
13 | "debug.upload.retcode": "Выгрузка исходников retCode: {0}",
14 | "build.cfg": "There is no build configuration named {0}.",
15 | "debug.download_listing.error": "Ошибка при загрузке листинга {0}",
16 | "debug.download.error": "Ошибка при загрузке {0}",
17 | "file-like-bin": "Файл скорее всего бинарный: {0}",
18 | "title.rem_loc": "Удалённый {0} <-> Локальный",
19 | "debug.no_remote": "Нет удалённого файла {0} => выгрузить",
20 | "debug.local_is_newer": "Локальный файл {0} новее => выгрузить",
21 | "debug.remote_is_newer": "Удалённый файл {0} новее на {1} => загрузить",
22 | "debug.the_same": "Файлы {0} одинаковы",
23 | "debug.no_local": "Нет локального файла {0} => загрузить",
24 | "debug.cannot_get_ssh_helper": "Не удалось загрузить ssh-helper API",
25 | "output.install_ssh": "Установите плагин 'vmssoftware.ssh-helper'",
26 | "message.action_success": "{0} удачно: {1}",
27 | "message.action_failed": "{0} ошибка: {1}",
28 | "debug.create_remote": "Создание удалённого источника",
29 | "debug.create_local": "Создание локального источника"
30 | }
--------------------------------------------------------------------------------
/i18n/ru/synchronizer/upload-zip.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "zip.cannot_clean": "Не удалось удалить локальный zip файл.",
3 | "ssh-helper.failed": "Не нашлось расширение vmssoftware.ssh-helper",
4 | "zip.missed": "Расширение vmssoftware.zip-helper не найдено.",
5 | "zip.cannot_start": "Не удалось запустить Zip.",
6 | "zip.nothing": "Нечего паковать.",
7 | "zip.ssh.stopped": "Останов.",
8 | "zip.prepare_to_uploading": "ZIP файл создан. Подготовка к выгрузке.",
9 | "zip.ssh.failed": "Расширение vmssoftware.ssh-helper не найдено.",
10 | "zip.shell.failed": "Не удалось создать shell на удалённой машине.",
11 | "zip.cleaning_folder": "Очистка папки.",
12 | "zip.start_uploading": "Начало выгрузки ZIP файла.",
13 | "zip.prepare_to_unzippping": "ZIP файл выгружен. Подготовка к распаковке.",
14 | "zip.cd.failed": "Не удалось установить текущую директорию.",
15 | "zip.start_unzipping": "Начало распаковки.",
16 | "zip.unzip.failed": "Команда Unzip неуспешна.",
17 | "zip.unzip.not.installed": "Похоже, что 'unzip' не установлен",
18 | "zip.unzip.error_output": "Вывод команды Unzip:\n {0}",
19 | "zip.deleting_zip": "Удаление ZIP файла на стороне VMS.",
20 | "zip.cannot_finish": "Не удалось завершить Zip."
21 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_basic/context/SourceContext.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/i18n/ru/vms_cobol/context/CobolAnalisisHelpers.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "text_length_range": "Должно содержать от {0} до {1} символ(-ов,а)",
3 | "number_in_range": "Должно быть от {0} до {1}",
4 | "not_an_integer": "Должно быть целым",
5 | "undefined_name": "Неопределённое имя",
6 | "ambigous_name": "Двузначное имя",
7 | "illegal_type": "Неверный тип",
8 | "duplicated.clause": "Двойное выражение"
9 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_cobol/context/CobolSourceContext.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/i18n/ru/vms_cobol/extension.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "config.notfound": "Не найден плагин vmssoftware.config-helper"
3 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_cobol/stream/cobolInputStream.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "string.continuation.improperly": "Продолжение должно начинаться с зоны B",
3 | "string.continuation.error": "Ошибка продолжения - строка должна начинаться с {0}",
4 | "string.continuation.error.unpredictable": "Непредсказуемая ошибка продолжения"
5 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_debug/debug/vms_runtime.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "config_error": "Ошибка конфигурации",
3 | "program.end": ": У вас нет прав: log_io, oper, share.",
4 | "runtime.watch_error": "Watch: Ошибка параметра. Пример: (when (x > 3)) или ().",
5 | "runtime.command_ignore": "Команда запрещена!"
6 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_debug/debug/vms_runtime_run.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "runtime.program_end": "Программа завершена!"
3 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_debug/extension.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "setup.connection": "Пожалуйста, определите соединение",
3 | "extention.conecting": "Соединение с сервером ...",
4 | "extention.bar.conecting": "Соединение ...",
5 | "extention.connected": "Соединение с сервером установлено",
6 | "extention.bar.connected": "Подключен",
7 | "extention.closed": "Соединение закрыто",
8 | "extention.bar.disconnected": "Отключен",
9 | "extention.сustomize_configuration": "Настройте конфигурацию",
10 | "extention.not_connected": "Нет соединения с сервером"
11 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_debug/net/shell-session.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "os.not.supported": ": OS is not supported.",
3 | "proram.completed": ": The program is completed.",
4 | "conn.closed": "Connection is closed.",
5 | "ssh.hlp.api.fail": "Could not get ssh-helper API.",
6 | "output.cannot_attach": "Невозможно присоединиться",
7 | "session.interrupted": "(Internal error: the session was interrupted.)"
8 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_debug/parsers/debug_module_info.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/i18n/ru/vms_fortran/context/SourceContext.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/i18n/ru/vms_jvm_debug/extension.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "msg.class_name": "Введите класс для запуска",
3 | "msg.config.invalid": "Неверная конфигурация"
4 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_jvm_debug/jvm-debug-session.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "jvm.port.busy": "Порт {0} занят."
3 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_jvm_debug/jvm-proj-helper.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "breakpoint.no.line": "Невозможно установить точку останова {0}:{1} -> отключена",
3 | "breakpoint.no.line.disable": "Unable to set breakpoint at {0}:{1}. Breakpoint disabled."
4 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_jvm_debug/jvm-project.i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "javainfo.lost": "Информация по классам Java утеряна"
3 | }
--------------------------------------------------------------------------------
/i18n/ru/vms_jvm_debug/jvm-shell-runtime.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/i18n/ru/vms_pascal/context/SourceContext.i18n.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/images/mock-debug-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmssoftware/vms-ide/fb86e12999b0f05b9edfc2e53a8e4b5af58b2e27/images/mock-debug-icon.png
--------------------------------------------------------------------------------
/images/vms_128x128_v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmssoftware/vms-ide/fb86e12999b0f05b9edfc2e53a8e4b5af58b2e27/images/vms_128x128_v2.png
--------------------------------------------------------------------------------
/images/vms_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmssoftware/vms-ide/fb86e12999b0f05b9edfc2e53a8e4b5af58b2e27/images/vms_logo.png
--------------------------------------------------------------------------------
/make_async.txt:
--------------------------------------------------------------------------------
1 | //Make the next replacings, using regexp, and comment some errorneous functions:
2 |
3 | (// @RuleVersion.*\n\tpublic)
4 | $1 async
5 |
6 | (public\s*async.*?\(.*?\)):.*
7 | $1 {
8 |
9 | (this\.[^.]*\(\d*\))
10 | await $1
11 |
12 |
--------------------------------------------------------------------------------
/media/dep.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmssoftware/vms-ide/fb86e12999b0f05b9edfc2e53a8e4b5af58b2e27/media/dep.png
--------------------------------------------------------------------------------
/mms.language-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | // symbol used for single line comment. Remove this entry if your language does not support line comments
4 | "lineComment": "!",
5 | },
6 | // symbols used as brackets
7 | "brackets": [
8 | ["{", "}"],
9 | ["[", "]"],
10 | ["(", ")"]
11 | ],
12 | // symbols that are auto closed when typing
13 | "autoClosingPairs": [
14 | ["{", "}"],
15 | ["[", "]"],
16 | ["(", ")"],
17 | ["\"", "\""],
18 | ["'", "'"]
19 | ],
20 | // symbols that that can be used to surround a selection
21 | "surroundingPairs": [
22 | ["{", "}"],
23 | ["[", "]"],
24 | ["(", ")"],
25 | ["\"", "\""],
26 | ["'", "'"]
27 | ]
28 | }
--------------------------------------------------------------------------------
/msg.language-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | "lineComment": "!"
4 | },
5 | "brackets": [
6 | ["<", ">"]
7 | ],
8 | "autoClosingPairs": [
9 | ["<", ">"],
10 | ["\"", "\""],
11 | ["'", "'"]
12 | ],
13 | "surroundingPairs": [
14 | ["<", ">"],
15 | ["\"", "\""],
16 | ["'", "'"]
17 | ]
18 | }
--------------------------------------------------------------------------------
/pascal.language-configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "comments": {
3 | "lineComment": "!",
4 | "blockComment": [ "{", "}" ]
5 | },
6 | "brackets": [
7 | ["{", "}"],
8 | ["[", "]"],
9 | ["(", ")"]
10 | ],
11 | "autoClosingPairs": [
12 | ["{", "}"],
13 | ["[", "]"],
14 | ["(", ")"],
15 | ["'", "'"]
16 | ],
17 | "surroundingPairs": [
18 | ["{", "}"],
19 | ["[", "]"],
20 | ["(", ")"],
21 | ["'", "'"]
22 | ],
23 | "wordPattern": "[a-zA-Z$_][a-zA-Z$_0-9]*"
24 | }
25 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | Repository containing code for new OpenVMS IDE based on Visual Studio Code.
--------------------------------------------------------------------------------
/resources/build_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmssoftware/vms-ide/fb86e12999b0f05b9edfc2e53a8e4b5af58b2e27/resources/build_1.png
--------------------------------------------------------------------------------
/resources/build_28x28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmssoftware/vms-ide/fb86e12999b0f05b9edfc2e53a8e4b5af58b2e27/resources/build_28x28.png
--------------------------------------------------------------------------------
/resources/dark/boolean.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/dark/dependency.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/dark/document.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/dark/folder.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/dark/refresh.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/default.mms:
--------------------------------------------------------------------------------
1 |
2 | ! MMS - run with /EXTENDED_SYNTAX qualifier
3 | .SILENT
4 |
5 | ! Debug or Release
6 | .IF DEBUG
7 | OUT_DIR = .$(OUTDIR).debug
8 | CXXFLAGS = /DEBUG/NOOP/LIST=$(MMS$TARGET_NAME)/OBJECT=$(MMS$TARGET)
9 | CCFLAGS = /DEBUG/NOOP/LIST=$(MMS$TARGET_NAME)/OBJECT=$(MMS$TARGET)
10 | LINKFLAGS = /DEBUG/MAP=$(MMS$TARGET_NAME)/EXECUTABLE=$(MMS$TARGET)
11 | .ELSE
12 | OUT_DIR = .$(OUTDIR).release
13 | CXXFLAGS = /OBJECT=$(MMS$TARGET)
14 | CCFLAGS = /OBJECT=$(MMS$TARGET)
15 | LINKFLAGS = /EXECUTABLE=$(MMS$TARGET)
16 | .ENDIF
17 |
18 | ! Object directory
19 | OBJ_DIR = $(OUT_DIR).obj
20 |
21 | OBJECTS = $(JOIN $(PATSUBST *,[*],$(PATSUBST *[*],**,$(SUBST [],,$(ADDPREFIX $(OBJ_DIR),$(DIR $(SOURCES)))))),$(ADDSUFFIX .OBJ, $(NOTDIR $(BASENAME $(SOURCES)))))
22 |
23 | .SUFFIXES
24 | .SUFFIXES .EXE .OBJ .CPP .C
25 |
26 | .CPP.OBJ
27 | @- pipe create/dir $(DIR $(MMS$TARGET)) | copy SYS$INPUT nl:
28 | $(CXX) $(CXXFLAGS) $(MMS$SOURCE)
29 |
30 | .C.OBJ
31 | @- pipe create/dir $(DIR $(MMS$TARGET)) | copy SYS$INPUT nl:
32 | $(CC) $(CCFLAGS) $(MMS$SOURCE)
33 |
34 | [$(OUT_DIR)]$(NAME).exe DEPENDS_ON $(OBJECTS)
35 | $(LINK) $(LINKFLAGS) $(MMS$SOURCE_LIST)
36 |
37 |
--------------------------------------------------------------------------------
/resources/light/boolean.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/light/dependency.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/light/document.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/light/folder.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/light/refresh.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/package-explorer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmssoftware/vms-ide/fb86e12999b0f05b9edfc2e53a8e4b5af58b2e27/resources/package-explorer.png
--------------------------------------------------------------------------------
/resources/static.mms:
--------------------------------------------------------------------------------
1 | OUTDIR=out
2 | NAME=static
3 | INCLUDES=inc.h, add.h
4 | SOURCES=inc.cpp, add.cpp
5 |
6 | ! MMS - run with /EXTENDED_SYNTAX qualifier
7 | ! .SILENT
8 |
9 | ! Debug or Release
10 | .IF DEBUG
11 | OUT_DIR = .$(OUTDIR).debug
12 | CXXFLAGS = /DEBUG/NOOP/LIST=$(MMS$TARGET_NAME)/OBJECT=$(MMS$TARGET)
13 | CCFLAGS = /DEBUG/NOOP/LIST=$(MMS$TARGET_NAME)/OBJECT=$(MMS$TARGET)
14 | .ELSE
15 | OUT_DIR = .$(OUTDIR).release
16 | CXXFLAGS = /OBJECT=$(MMS$TARGET)
17 | CCFLAGS = /OBJECT=$(MMS$TARGET)
18 | .ENDIF
19 |
20 | ! Object directory
21 | OBJ_DIR = $(OUT_DIR).obj
22 |
23 | .SUFFIXES
24 | .SUFFIXES .OLB .OBJ .CPP .C
25 |
26 | .CPP.OBJ
27 | pipe create/dir $(DIR $(MMS$TARGET)) | copy SYS$INPUT nl:
28 | $(CXX) $(CXXFLAGS) $(MMS$SOURCE)
29 |
30 | .C.OBJ
31 | pipe create/dir $(DIR $(MMS$TARGET)) | copy SYS$INPUT nl:
32 | $(CC) $(CCFLAGS) $(MMS$SOURCE)
33 |
34 | [$(OUT_DIR)]$(NAME).OLB :: [$(OBJ_DIR)]inc.obj
35 | IF "''F$SEARCH("[$(OUT_DIR)]$(NAME).OLB")'" .EQS. "" THEN -
36 | LIBR/CREATE/OBJ [$(OUT_DIR)]$(NAME).OLB
37 | LIBR [$(OUT_DIR)]$(NAME).OLB [$(OBJ_DIR)]inc.obj
38 |
39 | [$(OUT_DIR)]$(NAME).OLB :: [$(OBJ_DIR)]add.obj
40 | IF "''F$SEARCH("[$(OUT_DIR)]$(NAME).OLB")'" .EQS. "" THEN -
41 | LIBR/CREATE/OBJ [$(OUT_DIR)]$(NAME).OLB
42 | LIBR [$(OUT_DIR)]$(NAME).OLB [$(OBJ_DIR)]add.obj
43 |
44 | [$(OBJ_DIR)]inc.obj : inc.cpp $(INCLUDES)
45 |
46 | [$(OBJ_DIR)]add.obj : add.cpp $(INCLUDES)
--------------------------------------------------------------------------------
/src/cld/CompletionProvider.ts:
--------------------------------------------------------------------------------
1 |
2 | import { TextDocument, Position, CancellationToken, Location, CompletionItem, CompletionItemKind, ProviderResult, CompletionList } from 'vscode';
3 | import { CldFacade, SymbolKind } from './Facade';
4 | import { translateCompletionKind } from './Symbol';
5 |
6 | // Determines the sort order in the completion list. One value for each SymbolKind.
7 | const sortKeys = [
8 | "99", // Other
9 | ];
10 |
11 | // Descriptions for each symbol kind.
12 | const details = [
13 | "Other",
14 | ];
15 |
16 | export class CldCompletionItemProvider {
17 | constructor(private backend: CldFacade) { }
18 |
19 | public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): ProviderResult {
20 |
21 | let candidates = this.backend.getCodeCompletionCandidates(document.fileName, position.character, position.line + 1);
22 | let completionList: CompletionItem[] = [];
23 |
24 | candidates.forEach(info => {
25 | let item = new CompletionItem(info.name, translateCompletionKind(info.kind));
26 | item.sortText = sortKeys[info.kind] + info.name;
27 | item.detail = (info.description !== undefined) ? info.description : details[info.kind];
28 | completionList.push(item);
29 | });
30 |
31 | return new CompletionList(completionList, false);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/cld/ContextErrorListener.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is released under the MIT license.
3 | * Copyright (c) 2016, 2017 Mike Lischke
4 | *
5 | * See LICENSE file for more info.
6 | */
7 |
8 | "use strict";
9 |
10 | import { ANTLRErrorListener, Recognizer, RecognitionException, Token, CommonToken } from 'antlr4ts';
11 |
12 | import { DiagnosticEntry, DiagnosticType } from './Facade';
13 |
14 | export class ContextLexerErrorListener implements ANTLRErrorListener {
15 | constructor(private errorList: DiagnosticEntry[]) {
16 | }
17 |
18 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
19 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void {
20 | let error: DiagnosticEntry = {
21 | type: DiagnosticType.Error,
22 | message: msg,
23 | range: { start: { column: charPositionInLine, row: line }, end: { column: charPositionInLine + 1, row: line }}
24 | };
25 |
26 | this.errorList.push(error);
27 | }
28 | }
29 |
30 | export class ContextErrorListener implements ANTLRErrorListener {
31 | constructor(private errorList: DiagnosticEntry[]) {
32 | }
33 |
34 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
35 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void {
36 | let error: DiagnosticEntry = {
37 | type: DiagnosticType.Error,
38 | message: msg,
39 | range: { start: { column: charPositionInLine, row: line }, end: { column: charPositionInLine + 1, row: line }}
40 | };
41 |
42 | if (offendingSymbol) {
43 | error.range.end.column = charPositionInLine + offendingSymbol.stopIndex - offendingSymbol.startIndex + 1;
44 | }
45 | this.errorList.push(error);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/cld/DefinitionProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Location, Uri, ProviderResult, DefinitionProvider } from 'vscode';
2 | import { CldFacade } from './Facade';
3 |
4 | export class CldDefinitionProvider implements DefinitionProvider {
5 | constructor(private backend: CldFacade) { }
6 |
7 | public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): ProviderResult {
8 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character, position.line + 1);
9 |
10 | if (!info) {
11 | return undefined;
12 | }
13 |
14 | if (info.masterDefinition) {
15 | let range = new Range(
16 | info.masterDefinition.range.start.row - 1, info.masterDefinition.range.start.column,
17 | info.masterDefinition.range.end.row - 1, info.masterDefinition.range.end.column
18 | );
19 | return new Location(Uri.file(info.source), range);
20 | } else {
21 | // Empty for built-in entities or self-define attempts.
22 | // let position = new Position(0, 0);
23 | return new Location(document.uri, position);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/cld/HoverProvider.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 | import { HoverProvider, TextDocument, Position, CancellationToken, ProviderResult, Hover } from "vscode";
3 | import { CldFacade } from "./Facade";
4 | import { symbolDescriptionFromEnum } from './Symbol';
5 |
6 | export class CldHoverProvider implements HoverProvider {
7 | constructor(private backend: CldFacade) { }
8 |
9 | public provideHover(document: TextDocument, position: Position, token: CancellationToken): ProviderResult {
10 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character, position.line + 1);
11 | if (!info) {
12 | return undefined;
13 | }
14 |
15 | return new Hover([
16 | info.description? info.description : symbolDescriptionFromEnum(info.kind)
17 | ]);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/cld/ReferenceProvider.ts:
--------------------------------------------------------------------------------
1 | import {
2 | CancellationToken,
3 | Location,
4 | Position,
5 | ProviderResult,
6 | Range,
7 | ReferenceContext,
8 | ReferenceProvider,
9 | TextDocument,
10 | } from 'vscode';
11 | import { CldFacade } from './Facade';
12 |
13 | export class CldReferenceProvider implements ReferenceProvider {
14 | constructor(private backend: CldFacade) { }
15 |
16 | provideReferences(document: TextDocument, position: Position, context: ReferenceContext, token: CancellationToken): ProviderResult {
17 | const occurences = this.backend.getSymbolOccurences(document.fileName, position.character, position.line + 1);
18 | const result: Location[] = [];
19 | if (occurences.length > 0 ) {
20 | // const master = occurences[0];
21 | // if (master.definition &&
22 | // master.definition.range.start.row === position.line + 1 &&
23 | // master.definition.range.start.column <= position.character &&
24 | // master.definition.range.end.column > position.character) {
25 | // // we point to the master
26 | for (let symbol of occurences) {
27 | if (symbol.definition) {
28 | let range = new Range(
29 | symbol.definition.range.start.row - 1, symbol.definition.range.start.column,
30 | symbol.definition.range.end.row - 1, symbol.definition.range.end.column
31 | );
32 | const loc: Location = {
33 | range,
34 | uri: document.uri,
35 | };
36 | result.push(loc);
37 | }
38 | }
39 | // }
40 | }
41 | return result;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/cld/RenameProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Location, Uri, ProviderResult, WorkspaceEdit, RenameProvider } from 'vscode';
2 | import { CldFacade } from './Facade';
3 |
4 | export class CldRenameProvider implements RenameProvider {
5 | constructor(private backend: CldFacade) { }
6 |
7 | // public prepareRename(document: TextDocument, position: Position, token: CancellationToken): ProviderResult {
8 | // let info = this.backend.symbolInfoAtPosition(document.fileName, position.character, position.line + 1);
9 |
10 | // if (info && info.definition) {
11 | // return new Range(
12 | // info.definition.range.start.row - 1,
13 | // info.definition.range.start.column,
14 | // info.definition.range.end.row - 1,
15 | // info.definition.range.end.column);
16 | // }
17 |
18 | // return undefined;
19 | // }
20 |
21 | public provideRenameEdits(document: TextDocument, position: Position, newName: string,
22 | token: CancellationToken): ProviderResult {
23 | const occurences = this.backend.getSymbolOccurences(document.fileName, position.character, position.line + 1);
24 | if (occurences.length) {
25 | const result = new WorkspaceEdit();
26 | for (let symbol of occurences) {
27 | if (symbol.definition) {
28 | let range = new Range(
29 | symbol.definition.range.start.row - 1, symbol.definition.range.start.column,
30 | symbol.definition.range.end.row - 1, symbol.definition.range.end.column
31 | );
32 | result.replace(Uri.file(symbol.source), range, newName);
33 | }
34 | }
35 | return result;
36 | }
37 | return undefined;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/cld/cld.tokens:
--------------------------------------------------------------------------------
1 | DEFINE=1
2 | IDENT=2
3 | MODULE=3
4 | SYNTAX=4
5 | TYPE=5
6 | VERB=6
7 | NODISALLOWS=7
8 | DISALLOW=8
9 | IMAGE=9
10 | NOPARAMETERS=10
11 | PARAMETER=11
12 | DEFAULT=12
13 | LABEL=13
14 | PROMPT=14
15 | VALUE=15
16 | NOCONCATENATE=16
17 | CONCATENATE=17
18 | LIST=18
19 | REQUIRED=19
20 | NOQUALIFIERS=20
21 | QUALIFIER=21
22 | BATCH=22
23 | NONNEGATABLE=23
24 | NEGATABLE=24
25 | PLACEMENT=25
26 | GLOBAL=26
27 | LOCAL=27
28 | POSITIONAL=28
29 | ROUTINE=29
30 | KEYWORD=30
31 | SYNONYM=31
32 | ANY2=32
33 | NEG=33
34 | NOT=34
35 | AND=35
36 | OR=36
37 | NAME=37
38 | COMMA=38
39 | EQUAL=39
40 | P_OPEN=40
41 | P_CLOSE=41
42 | A_OPEN=42
43 | A_CLOSE=43
44 | DOT=44
45 | STRING=45
46 | WHITESPACE=46
47 | NEWLINE=47
48 | COMMENT=48
49 | ','=38
50 | '='=39
51 | '('=40
52 | ')'=41
53 | '<'=42
54 | '>'=43
55 | '.'=44
56 |
--------------------------------------------------------------------------------
/src/cld/cldLexer.tokens:
--------------------------------------------------------------------------------
1 | DEFINE=1
2 | IDENT=2
3 | MODULE=3
4 | SYNTAX=4
5 | TYPE=5
6 | VERB=6
7 | NODISALLOWS=7
8 | DISALLOW=8
9 | IMAGE=9
10 | NOPARAMETERS=10
11 | PARAMETER=11
12 | DEFAULT=12
13 | LABEL=13
14 | PROMPT=14
15 | VALUE=15
16 | NOCONCATENATE=16
17 | CONCATENATE=17
18 | LIST=18
19 | REQUIRED=19
20 | NOQUALIFIERS=20
21 | QUALIFIER=21
22 | BATCH=22
23 | NONNEGATABLE=23
24 | NEGATABLE=24
25 | PLACEMENT=25
26 | GLOBAL=26
27 | LOCAL=27
28 | POSITIONAL=28
29 | ROUTINE=29
30 | KEYWORD=30
31 | SYNONYM=31
32 | ANY2=32
33 | NEG=33
34 | NOT=34
35 | AND=35
36 | OR=36
37 | NAME=37
38 | COMMA=38
39 | EQUAL=39
40 | P_OPEN=40
41 | P_CLOSE=41
42 | A_OPEN=42
43 | A_CLOSE=43
44 | DOT=44
45 | STRING=45
46 | WHITESPACE=46
47 | NEWLINE=47
48 | COMMENT=48
49 | ','=38
50 | '='=39
51 | '('=40
52 | ')'=41
53 | '<'=42
54 | '>'=43
55 | '.'=44
56 |
--------------------------------------------------------------------------------
/src/common/async-task-queue.ts:
--------------------------------------------------------------------------------
1 | type SimplyFn = () => void;
2 |
3 | export class AsyncTaskQueue {
4 |
5 | protected tasks: SimplyFn[] = [];
6 | protected isRunning: boolean = false;
7 | protected isStopped: boolean = false;
8 |
9 | public get numTasks(): number {
10 | return this.tasks.length;
11 | }
12 |
13 | /**
14 | * Enqueue task to execute
15 | * @param task
16 | * @param asap to set task in first position
17 | */
18 | public enqueue(task: SimplyFn, asap: boolean = false): void {
19 | if (asap) {
20 | this.tasks.unshift(task);
21 | } else {
22 | this.tasks.push(task);
23 | }
24 | this.start();
25 | }
26 |
27 | public start(): void {
28 | this.isStopped = false;
29 | if (!this.isRunning) {
30 | this.execute();
31 | }
32 | }
33 |
34 | public stop(): void {
35 | this.isStopped = true;
36 | }
37 |
38 | private execute(): void {
39 |
40 | // If there is more than one task in the queue and this is not stopped.
41 | if (!this.isStopped && this.tasks.length > 0) {
42 |
43 | // Set status to running
44 | this.isRunning = true;
45 |
46 | // Get the first task
47 | const task: SimplyFn = this.tasks.shift()!;
48 |
49 | // Run the task decoupled and start the next
50 | Promise.resolve().then(async () => {
51 | await task();
52 | this.execute();
53 | });
54 |
55 | } else {
56 | // If there is no more tasks or if this is no longer running
57 | // Set status to not running
58 | this.isRunning = false;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/common/bsearch.ts:
--------------------------------------------------------------------------------
1 | export function binarySearch(array: T[], predicate: (el: T) => number) {
2 | var m = 0;
3 | var n = array.length - 1;
4 | while (m <= n) {
5 | var k = (n + m) >> 1;
6 | var cmp = predicate(array[k]);
7 | if (cmp > 0) {
8 | m = k + 1;
9 | } else if(cmp < 0) {
10 | n = k - 1;
11 | } else {
12 | return k;
13 | }
14 | }
15 | return -m - 1;
16 | }
--------------------------------------------------------------------------------
/src/common/cr-lf-trimmed-eq.ts:
--------------------------------------------------------------------------------
1 | const regexpt = /[\x13\x10]/g;
2 |
3 | export function CrLfTrimmedEqIgnoreCase(one: string, two: string): boolean {
4 | if (one === two) {
5 | return true;
6 | }
7 | return one.replace(regexpt, "").trim().toUpperCase() === two.replace(regexpt, "").trim().toUpperCase();
8 | }
9 |
--------------------------------------------------------------------------------
/src/common/debouncer.ts:
--------------------------------------------------------------------------------
1 | import { LogFunction, LogType } from "./log-type";
2 |
3 | /**
4 | * Collects all calls and fire only one if during _msec were no more calls
5 | * Only the last then() or await will continue to work!!!
6 | */
7 |
8 | export class Debouncer {
9 |
10 | protected timer: NodeJS.Timeout | undefined = undefined;
11 |
12 | constructor(protected msec: number, public debugLog?: LogFunction) {
13 |
14 | }
15 |
16 | public async debounce() {
17 | if (this.debugLog) {
18 | this.debugLog(LogType.debug, () => "debounce: start");
19 | }
20 | if (this.timer) {
21 | if (this.debugLog) {
22 | this.debugLog(LogType.debug, () => "debounce: timer exists - clear timer");
23 | }
24 | clearTimeout(this.timer);
25 | }
26 | if (this.debugLog) {
27 | this.debugLog(LogType.debug, () => "debounce: creating promise");
28 | }
29 | return new Promise((resolve) => {
30 | if (this.debugLog) {
31 | this.debugLog(LogType.debug, () => "debounce: creating timer");
32 | }
33 | this.timer = setTimeout(() => {
34 | if (this.debugLog) {
35 | this.debugLog(LogType.debug, () => "debounce: timer fired");
36 | }
37 | this.timer = undefined;
38 | resolve();
39 | }, this.msec);
40 | });
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/common/delay.ts:
--------------------------------------------------------------------------------
1 |
2 | export async function Delay(msec: number) {
3 | return new Promise((resolve) => {
4 | setTimeout(() => {
5 | resolve();
6 | }, msec);
7 | });
8 | }
9 |
--------------------------------------------------------------------------------
/src/common/directory.ts:
--------------------------------------------------------------------------------
1 |
2 | export interface IFileEntry {
3 | filename: string;
4 | isFile: boolean;
5 | isDirectory: boolean;
6 | date: Date; // modification date
7 | vers: number; // version
8 | }
9 |
10 | export const ftpPathSeparator = "/";
11 |
12 | export interface IReadDirectory {
13 | readDirectory(directory: string): Promise;
14 | }
15 |
--------------------------------------------------------------------------------
/src/common/iterators.ts:
--------------------------------------------------------------------------------
1 |
2 | export function minOf(iter: IterableIterator) {
3 | let min = Number.MAX_SAFE_INTEGER;
4 | for (const i of iter) {
5 | if (min > i) {
6 | min = i;
7 | }
8 | }
9 | return min;
10 | }
--------------------------------------------------------------------------------
/src/common/log-type.ts:
--------------------------------------------------------------------------------
1 |
2 | export enum LogType {
3 | error,
4 | warning,
5 | information,
6 | debug,
7 | }
8 |
9 | export type LogResult= () => string;
10 |
11 | export type LogFunction = (type: LogType, message: LogResult, show?: boolean, addStackLevel?: number) => void;
12 |
--------------------------------------------------------------------------------
/src/common/log.ts:
--------------------------------------------------------------------------------
1 | import { LogResult, LogType } from "./log-type";
2 |
3 | export function logConsoleFn(type: LogType, message: LogResult) {
4 | switch (type) {
5 | case LogType.error:
6 | // tslint:disable-next-line:no-console
7 | console.error(message());
8 | break;
9 | case LogType.warning:
10 | // tslint:disable-next-line:no-console
11 | console.warn(message());
12 | break;
13 | case LogType.information:
14 | // tslint:disable-next-line:no-console
15 | console.info(message());
16 | break;
17 | case LogType.debug:
18 | // tslint:disable-next-line:no-console
19 | console.log(message());
20 | break;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/common/main.ts:
--------------------------------------------------------------------------------
1 | export * from "./async-task-queue";
2 | export * from "./barrier";
3 | export * from "./cr-lf-trimmed-eq";
4 | export * from "./debouncer";
5 | export * from "./delay";
6 | export * from "./directory";
7 | export * from "./lock";
8 | export * from "./log";
9 | export * from "./log-type";
10 | export * from "./mem-reader";
11 | export * from "./mem-writer";
12 | export * from "./print-like";
13 | export * from "./resolve";
14 | export * from "./simply-compare";
15 | export * from "./subscribe";
16 | export * from "./wait-fire-event-emitter";
17 | export * from "./waitable-operation";
18 |
--------------------------------------------------------------------------------
/src/common/mem-reader.ts:
--------------------------------------------------------------------------------
1 | import { Readable } from "stream";
2 | import { LogFunction, LogType } from "./log-type";
3 |
4 | export class MemoryReadStream extends Readable {
5 |
6 | public pos = 0;
7 |
8 | constructor(public chunks?: Array, public debugLog?: LogFunction) {
9 | super();
10 | this.on("error", (err) => {
11 | if (this.debugLog) {
12 | this.debugLog(LogType.error, () => `memstream error: ${err}`);
13 | }
14 | });
15 | }
16 |
17 | public _read(size: number) {
18 | if (this.chunks) {
19 | if (this.pos < this.chunks.length) {
20 | if (this.chunks[this.pos] === null) {
21 | process.nextTick(() => this.emit("error", new Error("Null Chunk")));
22 | } else {
23 | this.push(this.chunks[this.pos++]);
24 | }
25 | } else {
26 | this.push(null);
27 | }
28 | } else {
29 | this.push(null);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/common/mem-writer.ts:
--------------------------------------------------------------------------------
1 | import { Writable } from "stream";
2 | import { LogFunction, LogType } from "./log-type";
3 |
4 | export class MemoryWriteStream extends Writable {
5 |
6 | public static badChunk: Buffer = Buffer.from([0, 0, 0, 0, 0]);
7 |
8 | public chunks: Buffer[] = [];
9 |
10 | constructor(public debugLog?: LogFunction, public emulateError?: boolean) {
11 | super();
12 | this.on("error", (err) => {
13 | if (this.debugLog) {
14 | this.debugLog(LogType.error, () => `memstream error: ${err}`);
15 | }
16 | });
17 | }
18 |
19 | public _write(chunk: any, encoding: string, callback: (err?: Error) => any) {
20 | if (this.emulateError) {
21 | callback(new Error("Writing prohibited"));
22 | }
23 | if (Buffer.isBuffer(chunk)) {
24 | if (chunk.equals(MemoryWriteStream.badChunk)) {
25 | callback(new Error("Bad chunk encountered"));
26 | } else {
27 | this.chunks.push(chunk);
28 | callback();
29 | }
30 | } else {
31 | callback(new Error("Chunk isn't Buffer"));
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/common/parser/CompletionProvider.ts:
--------------------------------------------------------------------------------
1 | import { FacadeImpl } from "./Facade";
2 | import { TextDocument, Position, CancellationToken, ProviderResult, CompletionList, CompletionItem } from "vscode";
3 |
4 | export class CompletionItemProviderImpl
5 | {
6 | constructor(private backend: FacadeImpl) { }
7 |
8 | public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): ProviderResult
9 | {
10 | let candidates = this.backend.getCodeCompletionCandidates(document.fileName, position.character, position.line);
11 | let completionList: CompletionItem[] = [];
12 |
13 | candidates.forEach(candidate => {
14 | let item = new CompletionItem(candidate.candidate);
15 | item.detail = candidate.description;
16 | completionList.push(item);
17 | });
18 |
19 | return new CompletionList(completionList, false);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/common/parser/DefinitionProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Location, Uri, ProviderResult, DefinitionProvider } from 'vscode';
2 | import { FacadeImpl } from './Facade';
3 |
4 | export class DefinitionProviderImpl implements DefinitionProvider {
5 | constructor(private backend: FacadeImpl) {
6 | }
7 | public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): ProviderResult {
8 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character, position.line);
9 | if (info && info.definition) {
10 | let range = new Range(0,0,0,0);
11 | if (info.definition.range) {
12 | range = new Range(
13 | info.definition.range.start.row, info.definition.range.start.col,
14 | info.definition.range.end.row, info.definition.range.end.col
15 | );
16 | }
17 | return new Location(Uri.file(info.definition.source), range);
18 | }
19 | return undefined;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/common/parser/ErrorListeners.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { ANTLRErrorListener, Recognizer, RecognitionException, Token, CommonToken } from 'antlr4ts';
4 | import { IDiagnosticEntry, EDiagnosticType } from './Facade';
5 |
6 |
7 | export class LexerErrorListener implements ANTLRErrorListener
8 | {
9 | constructor(private errorList: IDiagnosticEntry[])
10 | { }
11 |
12 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
13 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void
14 | {
15 | let error: IDiagnosticEntry = {
16 | type: EDiagnosticType.Error,
17 | message: msg,
18 | range: { start: { col: charPositionInLine, row: line }, end: { col: charPositionInLine + 1, row: line }}
19 | };
20 |
21 | this.errorList.push(error);
22 | }
23 | }
24 |
25 | export class ParserErrorListener implements ANTLRErrorListener
26 | {
27 | constructor(private errorList: IDiagnosticEntry[]) {
28 | }
29 |
30 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
31 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void
32 | {
33 | let error: IDiagnosticEntry = {
34 | type: EDiagnosticType.Error,
35 | message: msg,
36 | range: { start: { col: charPositionInLine, row: line }, end: { col: charPositionInLine + 1, row: line }}
37 | };
38 |
39 | if (offendingSymbol) {
40 | error.range.end.col = charPositionInLine + offendingSymbol.stopIndex - offendingSymbol.startIndex + 1;
41 | }
42 |
43 | this.errorList.push(error);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/common/parser/HoverProvider.ts:
--------------------------------------------------------------------------------
1 | import { HoverProvider, TextDocument, Position, CancellationToken, Hover, workspace } from "vscode";
2 | import { FacadeImpl } from "./Facade";
3 | import * as path from 'path';
4 |
5 | export class HoverProviderImpl implements HoverProvider {
6 | constructor(private backend: FacadeImpl) {
7 | }
8 | public async provideHover(document: TextDocument, position: Position, token: CancellationToken) {
9 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character, position.line);
10 | if (info) {
11 | let defStr = "";
12 | if (info.definition) {
13 | if (info.definition.source) {
14 | defStr = workspace.asRelativePath(info.definition.source, true);
15 | }
16 | if (info.definition.text) {
17 | defStr = `defined in ${defStr}`;
18 | if (info.definition.range) {
19 | defStr += ` at ${info.definition.range.start.row + 1}:${info.definition.range.start.col + 1}`;
20 | }
21 | } else {
22 | defStr = `from ${defStr}`;
23 | }
24 | }
25 | return new Hover([
26 | `**${info.kindString}** ${defStr}`,
27 | info.description
28 | ]);
29 | }
30 | return undefined;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/common/parser/ReferenceProvider.ts:
--------------------------------------------------------------------------------
1 | import {
2 | CancellationToken,
3 | Location,
4 | Position,
5 | ProviderResult,
6 | Range,
7 | ReferenceContext,
8 | ReferenceProvider,
9 | TextDocument,
10 | Uri,
11 | } from 'vscode';
12 | import { FacadeImpl } from './Facade';
13 |
14 | export class ReferenceProviderImpl implements ReferenceProvider {
15 |
16 | constructor(private backend: FacadeImpl) {
17 | }
18 |
19 | public provideReferences(document: TextDocument, position: Position, context: ReferenceContext, token: CancellationToken): ProviderResult {
20 | const occurences = this.backend.getOccurencesUnderCursor(document.fileName, position.character, position.line);
21 | const result: Location[] = [];
22 |
23 | if (occurences.length > 0 ) {
24 | for (let ocuurance of occurences) {
25 | if (ocuurance.range) {
26 | let range = new Range(
27 | ocuurance.range.start.row, ocuurance.range.start.col,
28 | ocuurance.range.end.row, ocuurance.range.end.col
29 | );
30 | const loc: Location = {
31 | range,
32 | uri: Uri.file(ocuurance.source),
33 | };
34 | result.push(loc);
35 | }
36 | }
37 | }
38 |
39 | return result;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/common/parser/RenameProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Uri, ProviderResult, WorkspaceEdit, RenameProvider } from 'vscode';
2 | import { FacadeImpl } from './Facade';
3 |
4 | export class RenameProviderImpl implements RenameProvider {
5 | constructor(private backend: FacadeImpl) {
6 | }
7 | public provideRenameEdits(document: TextDocument, position: Position, newName: string, token: CancellationToken): ProviderResult {
8 | const occurences = this.backend.getOccurencesUnderCursor(document.fileName, position.character, position.line);
9 | if (occurences.length) {
10 | const result = new WorkspaceEdit();
11 | for (let occurance of occurences) {
12 | if (occurance.text && occurance.range) {
13 | let range = new Range(
14 | occurance.range.start.row, occurance.range.start.col,
15 | occurance.range.end.row, occurance.range.end.col
16 | );
17 | let replaceName = newName;
18 | if (occurance.quotas) {
19 | replaceName = occurance.quotas + newName + occurance.quotas[occurance.quotas.length - 1];
20 | }
21 | result.replace(Uri.file(occurance.source), range, replaceName);
22 | }
23 | }
24 | return result;
25 | }
26 | return undefined;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/common/print-like.ts:
--------------------------------------------------------------------------------
1 |
2 | export function printLike(strings: TemplateStringsArray, ...values: T) {
3 | return (...p: T) => {
4 | let str = "";
5 | for (let i = 0; i < p.length; i++) {
6 | str += strings[i];
7 | str += p[i];
8 | }
9 | str += strings[strings.length - 1];
10 | return str;
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/src/common/print-syntax-tree.ts:
--------------------------------------------------------------------------------
1 | import { Parser, ParserRuleContext } from "antlr4ts";
2 | import { ParseTree, Trees } from "antlr4ts/tree";
3 |
4 | export function getSyntaxTreeStrings(parser: Parser, root: ParseTree) : string[] {
5 | return recursive(root, 0, parser);
6 | }
7 |
8 | function recursive(root: ParseTree, offset: number, parser: Parser): string[] {
9 | let buf = [" ".repeat(offset) + Trees.getNodeText(root, parser.ruleNames)];
10 | if (root instanceof ParserRuleContext) {
11 | if (root.children != null) {
12 | for (let child of root.children) {
13 | buf.push(...recursive(child, offset + 1, parser));
14 | }
15 | }
16 | }
17 | // else if (root instanceof TerminalNode) {
18 | // let symbName = parser.vocabulary.getSymbolicName(root.symbol.type);
19 | // if (symbName) {
20 | // buf[buf.length-1] += ' <' + symbName + '>';
21 | // }
22 | // }
23 | return buf;
24 | }
--------------------------------------------------------------------------------
/src/common/quotes.ts:
--------------------------------------------------------------------------------
1 | export function test_enclosing_quotes(str: string) {
2 | let first_char = str[0];
3 | if (first_char === '"' || first_char === "'") {
4 | for(let i = 1; i < str.length; ++i) {
5 | if (str[i] == '\\') {
6 | ++i;
7 | } else if (str[i] == first_char) {
8 | return { enclosed: true, quote_pos: i } ;
9 | }
10 | }
11 | }
12 | return { enclosed: false, quote_pos: -1 } ;
13 | }
--------------------------------------------------------------------------------
/src/common/read_all_stream.ts:
--------------------------------------------------------------------------------
1 | import { Readable, Writable } from "stream";
2 |
3 | export async function readWholeStream(stream: Readable | undefined) {
4 | return new Promise((resolve) => {
5 | if (stream) {
6 | const chunks: Buffer[] = [];
7 | stream.on('data', chunk => Buffer.isBuffer(chunk) ? chunks.push(chunk) : undefined);
8 | stream.on('error', () => resolve(""));
9 | stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
10 | } else {
11 | resolve("");
12 | }
13 | });
14 | }
15 |
16 | export async function writeWholeStream(stream: Writable | undefined, data: Buffer | string) {
17 | if (typeof data === "string") {
18 | data = Buffer.from(data, "utf-8");
19 | }
20 | return new Promise(async (resolve) => {
21 | if (stream) {
22 | stream.write(data);
23 | stream.end();
24 | } else {
25 | resolve(false);
26 | }
27 | });
28 | }
29 |
--------------------------------------------------------------------------------
/src/common/resolve.ts:
--------------------------------------------------------------------------------
1 | export type Resolve = ((value?: T | PromiseLike | undefined) => void);
2 | export type Reject = ((reason?: any) => void);
--------------------------------------------------------------------------------
/src/common/rgx-from-str.ts:
--------------------------------------------------------------------------------
1 |
2 | export function RgxFromStr(str: string, mode = "g") {
3 | return new RegExp(RgxStrFromStr(str), mode);
4 | }
5 |
6 | export function RgxStrFromStr(str: string) {
7 | return str.replace(/[.*+?^${}()|[\]\\\/]/g, "\\$&");
8 | }
9 |
10 | export function maskSpacesInTemplate(str: string, mask?: string) {
11 | mask = mask || "*";
12 | let depth = 0;
13 | let result = "";
14 | for(let i = 0; i < str.length; ++i) {
15 | switch (str[i] ) {
16 | case '<':
17 | ++depth;
18 | result += str[i];
19 | break;
20 | case '>':
21 | if (depth) {
22 | --depth;
23 | }
24 | result += str[i];
25 | break;
26 | default:
27 | if (depth && str[i] === ' ') {
28 | result += mask;
29 | } else {
30 | result += str[i];
31 | }
32 | }
33 | }
34 | return result;
35 | }
36 |
37 | export function removeTemplate(str: string) {
38 | let depth = 0;
39 | let result = "";
40 | for(let i = 0; i < str.length; ++i) {
41 | switch (str[i] ) {
42 | case '<':
43 | ++depth;
44 | break;
45 | case '>':
46 | if (depth) {
47 | --depth;
48 | }
49 | break;
50 | default:
51 | if (!depth) {
52 | result += str[i];
53 | }
54 | }
55 | }
56 | return result;
57 | }
58 |
--------------------------------------------------------------------------------
/src/common/simply-compare.ts:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * True if equal
4 | * @param a
5 | * @param b
6 | */
7 | export function isSimplyEq(a: any, b: any): boolean {
8 | if (a === b) {
9 | return true;
10 | }
11 | if (a === undefined || b === undefined) {
12 | return false;
13 | }
14 | let count = 0;
15 | for (const key in a) {
16 | if (a.hasOwnProperty(key)) {
17 | if ( b.hasOwnProperty(key) && a[key] === b[key] ) {
18 | ++ count;
19 | continue;
20 | }
21 | return false;
22 | }
23 | }
24 | for (const key in b) {
25 | if (b.hasOwnProperty(key)) {
26 | -- count;
27 | }
28 | }
29 | return count === 0;
30 | }
31 |
--------------------------------------------------------------------------------
/src/common/subscribe.ts:
--------------------------------------------------------------------------------
1 | import { EventEmitter } from "events";
2 |
3 | export interface IUnSubscribe {
4 | unsubscribe: () => void;
5 | }
6 |
7 | export function Subscribe(emitter: EventEmitter, event: string | symbol, listener: (...args: any[]) => void)
8 | : IUnSubscribe {
9 | emitter.on(event, listener);
10 | return { unsubscribe: () => {
11 | emitter.removeListener(event, listener);
12 | }};
13 | }
14 |
--------------------------------------------------------------------------------
/src/common/task-count.ts:
--------------------------------------------------------------------------------
1 | import { EventEmitter } from "events";
2 |
3 | export class TaskCount {
4 |
5 | private emitter = new EventEmitter();
6 | private counter = 0;
7 |
8 | public getCount() {
9 | return this.counter;
10 | }
11 |
12 | public taskStarted() {
13 | ++this.counter;
14 | }
15 |
16 | public waitAllTask(): Promise {
17 | return new Promise((resolve) => {
18 | if (this.counter === 0) {
19 | resolve(true);
20 | } else {
21 | // Otherwise, wait until somebody releases the lock and try again
22 | const testTask = () => {
23 | if (this.counter === 0) {
24 | this.emitter.removeListener("taskEnded", testTask);
25 | this.emitter.setMaxListeners(Math.max(0, this.emitter.getMaxListeners() - 1));
26 | return resolve(true);
27 | }
28 | };
29 | this.emitter.setMaxListeners(this.emitter.getMaxListeners() + 1);
30 | this.emitter.on("taskEnded", testTask);
31 | }
32 | });
33 | }
34 |
35 | public taskEnded() {
36 | --this.counter;
37 | setImmediate(() => this.emitter.emit("taskEnded"));
38 | }
39 | }
--------------------------------------------------------------------------------
/src/common/task-divider.ts:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Allow task to break its execution and other task can change asyncValue.
4 | * For example - to cancel current async task
5 | */
6 | export class TaskDivider {
7 | constructor(public asyncValue: T) {
8 | }
9 |
10 | public async testValue() {
11 | return new Promise(resolve => {
12 | setImmediate(() => {
13 | resolve(this.asyncValue);
14 | });
15 | });
16 | }
17 | }
--------------------------------------------------------------------------------
/src/common/wait-fire-event-emitter.ts:
--------------------------------------------------------------------------------
1 | import { EventEmitter } from "events";
2 | import { LogFunction } from "./log-type";
3 | import { Subscribe } from "./subscribe";
4 |
5 | /**
6 | * Waiting _wait_msec before firing the event. If a new fire() was called while waiting, the timeout starts again.
7 | * Only last event will be fired, all previous data will be discarded.
8 | */
9 | export class WaitFireEventEmitter {
10 |
11 | private fireSoonHandle?: NodeJS.Timeout;
12 | private emitter = new EventEmitter();
13 | private event = Symbol();
14 |
15 | constructor(private waitMsec: number, public debugLog?: LogFunction) {
16 | }
17 |
18 | public fire(data?: T) {
19 | this.fireSoon(data);
20 | }
21 |
22 | public dispose(): void {
23 | if (this.fireSoonHandle) {
24 | clearTimeout(this.fireSoonHandle);
25 | this.fireSoonHandle = undefined;
26 | }
27 | }
28 |
29 | public Subscribe(listener: (...args: any[]) => void) {
30 | return Subscribe(this.emitter, this.event, listener);
31 | }
32 |
33 | private fireSoon(data?: T ): void {
34 | if (this.fireSoonHandle) {
35 | clearTimeout(this.fireSoonHandle);
36 | }
37 | this.fireSoonHandle = setTimeout(() => {
38 | this.emitter.emit(this.event, data);
39 | }, this.waitMsec);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/config-helper/command-context.ts:
--------------------------------------------------------------------------------
1 | import { commands } from "vscode";
2 |
3 | export enum CommandContext {
4 | isSingleRoot = "vmssoftware.isSingleRoot",
5 | isTestEnabled = "vmssoftware.config-helper.test:enabled",
6 | }
7 |
8 | export function setContext(context: CommandContext, state: boolean) {
9 | commands.executeCommand("setContext", context, state);
10 | }
11 |
--------------------------------------------------------------------------------
/src/config-helper/config/config-hepler-section.ts:
--------------------------------------------------------------------------------
1 | import { IConfigData, IConfigSection } from "./config";
2 |
3 | export class ConfigHelperSection implements IConfigSection {
4 |
5 | public static readonly section = "settings";
6 |
7 | public static is(candidate: any): candidate is ConfigHelperSection {
8 | return !!candidate &&
9 | typeof candidate.addCalleeInfo === "boolean" &&
10 | typeof candidate.debug === "string" &&
11 | typeof candidate.test === "string" &&
12 | typeof candidate.using === "string";
13 | }
14 |
15 | public addCalleeInfo: boolean = false;
16 | public debug: string = "";
17 | public test: string = "test";
18 | public using: "FS" | "VSC" | "VFS" = "FS";
19 |
20 | public name(): string {
21 | return ConfigHelperSection.section;
22 | }
23 |
24 | public store(): IConfigData {
25 | return {
26 | addCalleeInfo: this.addCalleeInfo,
27 | debug: this.debug,
28 | test: this.test,
29 | using: this.using,
30 | };
31 | }
32 |
33 | public templateToFillFrom(): IConfigData {
34 | return this.store();
35 | }
36 |
37 | public fillFrom(data: IConfigData): boolean {
38 | if (ConfigHelperSection.is(data)) {
39 | this.addCalleeInfo = data.addCalleeInfo;
40 | this.debug = data.debug;
41 | this.test = data.test;
42 | switch (data.using) {
43 | case "FS":
44 | case "VSC":
45 | case "VFS":
46 | this.using = data.using;
47 | break;
48 | default:
49 | this.using = "FS";
50 | break;
51 | }
52 | return true;
53 | }
54 | return false;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/config-helper/config/dummy-editor.ts:
--------------------------------------------------------------------------------
1 | import { IConfigEditor } from "./config";
2 |
3 | /**
4 | * Dummy Editor implementation
5 | */
6 | export class DummyEditor implements IConfigEditor {
7 | public invoke(): Promise {
8 | return Promise.resolve(false);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/config-helper/config/dummy-storage.ts:
--------------------------------------------------------------------------------
1 | import { CSAResult, IConfigStorage } from "./config";
2 |
3 | /**
4 | * Dummy Storage implementations
5 | */
6 |
7 | export class DummyStorage implements IConfigStorage {
8 |
9 | public fillStart(): Promise {
10 | return Promise.resolve(CSAResult.prepare_failed);
11 | }
12 |
13 | public fillData(): Promise {
14 | return Promise.resolve(CSAResult.some_data_failed);
15 | }
16 |
17 | public fillEnd(): Promise {
18 | return Promise.resolve(CSAResult.end_failed);
19 | }
20 |
21 | public storeStart(): Promise {
22 | return Promise.resolve(CSAResult.prepare_failed);
23 | }
24 |
25 | public storeData(): Promise {
26 | return Promise.resolve(CSAResult.some_data_failed);
27 | }
28 |
29 | public storeEnd(): Promise {
30 | return Promise.resolve(CSAResult.end_failed);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/config-helper/config/fs-storage.ts:
--------------------------------------------------------------------------------
1 | import fs, { exists } from "fs";
2 | import path from "path";
3 | import util from "util";
4 |
5 | import { LogFunction, LogType } from "../../common/main";
6 | import { CSAResult, IConfigData, IConfigStorage } from "./config";
7 | import { ConfigStorageImpl } from "./storage-impl";
8 |
9 | const fsExist = util.promisify(fs.exists);
10 | const fsReadFile = util.promisify(fs.readFile);
11 | const fsWriteFile = util.promisify(fs.writeFile);
12 | const fsMkDir = util.promisify(fs.mkdir);
13 |
14 | /**
15 | * FSConfigStorage
16 | */
17 | export class FSConfigStorage extends ConfigStorageImpl {
18 |
19 | constructor(protected fileName: string, logFn?: LogFunction) {
20 | super(logFn);
21 | }
22 |
23 | public fillStart(): Promise {
24 | return fsReadFile(this.fileName)
25 | .then((data) => {
26 | this.content = data.toString("utf8");
27 | return super.fillStart();
28 | }).catch((err) => {
29 | this.logFn(LogType.debug, () => `${err}`);
30 | return CSAResult.prepare_failed;
31 | });
32 | }
33 |
34 | public storeEnd(): Promise {
35 | return super.storeEnd()
36 | .then((result) => {
37 | if (result === CSAResult.ok) {
38 | const dir = path.dirname(this.fileName);
39 | return fsExist(dir).then((ok) => {
40 | if (!ok) {
41 | return fsMkDir(dir);
42 | }
43 | }).then(() => {
44 | return fsWriteFile(this.fileName, this.content ? this.content : "")
45 | .then(() => {
46 | this.logFn(LogType.debug, () => "fsWriteFile => ok");
47 | return CSAResult.ok;
48 | });
49 | }).catch((err) => {
50 | this.logFn(LogType.debug, () => `fsWriteFile => fail ${err}`);
51 | return CSAResult.end_failed;
52 | });
53 | }
54 | return result;
55 | });
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/src/config-helper/config/uri-editor.ts:
--------------------------------------------------------------------------------
1 |
2 | import { Uri, window, workspace, Range, WorkspaceEdit, Position } from "vscode";
3 |
4 | import { LogFunction, LogType } from "../../common/main";
5 | import { IConfig, IConfigEditor, CSAResult } from "./config";
6 | import { ConfigStorageImpl } from "./storage-impl";
7 |
8 | // import * as nls from "vscode-nls";
9 | // nls.config({messageFormat: nls.MessageFormat.both});
10 | // const localize = nls.loadMessageBundle();
11 |
12 | export class UriEditor implements IConfigEditor {
13 |
14 | constructor(protected uri: Uri, protected cfg: IConfig, public logFn?: LogFunction) {
15 |
16 | }
17 |
18 | public invoke(): Promise {
19 | return new Promise((resolve) => {
20 | const buffer = new ConfigStorageImpl();
21 | this.cfg.save(buffer).then(async (result) => {
22 | if (result === CSAResult.ok && buffer.GetContent()) {
23 | try {
24 | let range: Range | undefined;
25 | try {
26 | const textDoc = await workspace.openTextDocument(this.uri);
27 | range = textDoc.validateRange(new Range(0, 0, 32767, 32767));
28 | } catch (err) {
29 | range = undefined;
30 | }
31 | const we = new WorkspaceEdit();
32 | const str = buffer.GetContent();
33 | let uri = this.uri;
34 | if (!range) {
35 | uri = this.uri.with({ scheme: "untitled"});
36 | we.insert(uri, new Position(0, 0), str!);
37 | } else {
38 | we.replace(uri, range, str!);
39 | }
40 | const doc = await workspace.openTextDocument(uri);
41 | const applied = await workspace.applyEdit(we);
42 | await window.showTextDocument(doc, { preview: false });
43 | resolve(true);
44 | } catch (err) {
45 | resolve(false);
46 | }
47 | } else {
48 | resolve(false);
49 | }
50 | });
51 | });
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/config-helper/config/vfs-config-helper.ts:
--------------------------------------------------------------------------------
1 | import { Uri } from "vscode";
2 |
3 | import { LogFunction, LogType } from "../../common/main";
4 | import { FSConfigHelper } from "./fs-config-helper";
5 | import { VFSConfigStorage } from "./vfs-storage";
6 |
7 | // import * as nls from "vscode-nls";
8 | // nls.config({messageFormat: nls.MessageFormat.both});
9 | // const localize = nls.loadMessageBundle();
10 |
11 | /**
12 | * ConfigHelper implementation
13 | */
14 | export class VFSConfigHelper extends FSConfigHelper {
15 |
16 | protected createConcreteFS_Storage(uri: Uri, logFn?: LogFunction) {
17 | // TODO: test URI and return appropriate FS
18 | return new VFSConfigStorage(uri, logFn);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/config-helper/config/vsc-config-helper.ts:
--------------------------------------------------------------------------------
1 | import { Disposable, Uri, workspace, WorkspaceFolder } from "vscode";
2 |
3 | import { Debouncer, LogFunction, LogType } from "../../common/main";
4 |
5 | import { CSAResult, IConfig, IConfigEditor, IConfigHelper, IConfigStorage } from "./config";
6 | import { ConfigPool } from "./config-pool";
7 | import { VSCWorkspaceConfigEditor } from "./vsc-editor";
8 | import { VSCConfigStorage } from "./vsc-storage";
9 |
10 | // import * as nls from "vscode-nls";
11 | // nls.config({messageFormat: nls.MessageFormat.both});
12 | // const localize = nls.loadMessageBundle();
13 |
14 | /**
15 | * ConfigHelper implementation
16 | */
17 | export class VSCConfigHelper implements IConfigHelper {
18 |
19 | protected logFn: LogFunction;
20 |
21 | protected config: ConfigPool;
22 | protected storage: IConfigStorage;
23 | protected editor: IConfigEditor;
24 | protected debouncer = new Debouncer(3000);
25 | protected disposables: Disposable[] = [];
26 |
27 | constructor(public workspaceFolder: WorkspaceFolder | undefined, protected extension: string, logFn?: LogFunction) {
28 | // tslint:disable-next-line:no-empty
29 | this.logFn = logFn || (() => {});
30 | this.storage = new VSCConfigStorage(this.workspaceFolder, this.extension, logFn);
31 | this.config = new ConfigPool(this.storage, logFn);
32 | this.editor = new VSCWorkspaceConfigEditor(this.config, logFn);
33 | this.disposables.push( workspace.onDidChangeConfiguration((e) => {
34 | if (e.affectsConfiguration(this.extension)) {
35 | this.config.freeze();
36 | this.logFn(LogType.debug, () => "onDidChangeConfiguration");
37 | this.debouncer.debounce().then(async () => {
38 | await this.config.load().then(result => this.config.lastResult |= result);
39 | this.config.unfreeze();
40 | });
41 | }
42 | }));
43 | }
44 |
45 | public dispose() {
46 | for (const disp of this.disposables) {
47 | disp.dispose();
48 | }
49 | this.disposables = [];
50 | }
51 |
52 | public getConfig(): IConfig {
53 | return this.config;
54 | }
55 |
56 | public getEditor(): IConfigEditor {
57 | return this.editor;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/config-helper/config/vsc-editor.ts:
--------------------------------------------------------------------------------
1 | import { commands } from "vscode";
2 |
3 | import { LogFunction, LogType } from "../../common/main";
4 | import { IConfig, IConfigEditor } from "./config";
5 |
6 | // import * as nls from "vscode-nls";
7 | // nls.config({messageFormat: nls.MessageFormat.both});
8 | // const localize = nls.loadMessageBundle();
9 |
10 | export class VSCWorkspaceConfigEditor implements IConfigEditor {
11 |
12 | protected readonly command = "workbench.action.openWorkspaceSettings";
13 |
14 | constructor(protected cfg: IConfig, protected logFn?: LogFunction) {
15 |
16 | }
17 |
18 | public invoke(): Promise {
19 | return new Promise((resolve) => {
20 | this.cfg.save().then(() => {
21 | // execute edit command in any case
22 | commands.executeCommand(this.command).then(() => {
23 | resolve(true);
24 | }, () => {
25 | resolve(false);
26 | });
27 | });
28 | });
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/config-helper/extension.ts:
--------------------------------------------------------------------------------
1 | import { commands, env, ExtensionContext, workspace } from "vscode";
2 | import { CommandContext, setContext } from "./command-context";
3 |
4 | import { ConfigApi } from "./config/config-api";
5 | import { ConfigHelperSection } from "./config/config-hepler-section";
6 | import { createLogFunction } from "./log";
7 |
8 | const locale = env.language ;
9 | import * as nls from "vscode-nls";
10 | const localize = nls.config({ locale, messageFormat: nls.MessageFormat.both })();
11 |
12 | const logFn = createLogFunction("VMS-IDE");
13 |
14 | export function activate(context: ExtensionContext) {
15 |
16 | const configApi = new ConfigApi(logFn);
17 |
18 | // setContext(CommandContext.isTestEnabled, true); // to test command, also required "*" in "activationEvents" in package.json
19 |
20 | setContext(CommandContext.isSingleRoot, (workspace.workspaceFolders !== undefined && workspace.workspaceFolders.length === 1));
21 | context.subscriptions.push( workspace.onDidChangeWorkspaceFolders(() => {
22 | setContext(CommandContext.isSingleRoot, (workspace.workspaceFolders !== undefined && workspace.workspaceFolders.length === 1));
23 | }));
24 |
25 | // context.subscriptions.push( commands.registerCommand("vmssoftware.config-helper.test", async () => {
26 | // //
27 | // const configHelper = configApi.getConfigHelper("vmssoftware.config-helper");
28 | // if (configHelper) {
29 | // let test = await configHelper.getConfig().get(ConfigHelperSection.section);
30 | // if (!ConfigHelperSection.is(test)) {
31 | // configHelper.getConfig().add(new ConfigHelperSection());
32 | // test = await configHelper.getConfig().get(ConfigHelperSection.section);
33 | // }
34 | // if (ConfigHelperSection.is(test)) {
35 | // test.test = "passed";
36 | // configHelper.getConfig().save();
37 | // }
38 | // }
39 | // }));
40 |
41 | return configApi;
42 | }
43 |
44 | export function deactivate() {
45 | //
46 | }
47 |
--------------------------------------------------------------------------------
/src/ext-api/ext-api.ts:
--------------------------------------------------------------------------------
1 |
2 | import { IConfigApi } from "../config-helper/config/config";
3 | import { SshHelper } from "../ssh-helper/ssh-helper";
4 | import { SyncApi } from "../synchronizer/sync/sync-api";
5 | import { ZipApi } from "../zip/zip-api";
6 |
7 | let configApi: IConfigApi | undefined;
8 | let sshHelperType: typeof SshHelper | undefined;
9 | let syncApi: SyncApi | undefined;
10 | let zipApi: typeof ZipApi | undefined;
11 |
12 | export function SetConfigHelperApi(newConfigApi: IConfigApi| undefined) {
13 | configApi = newConfigApi;
14 | }
15 |
16 | export function GetConfigHelperFromApi() {
17 | return configApi;
18 | }
19 |
20 | export function SetSshHelper(newSshHelper: typeof SshHelper | undefined) {
21 | sshHelperType = newSshHelper;
22 | }
23 |
24 | export function GetSshHelperType() {
25 | return sshHelperType;
26 | }
27 |
28 | export function GetSyncApi() {
29 | return syncApi;
30 | }
31 |
32 | export function SetSyncApi(newSyncApi: SyncApi | undefined) {
33 | syncApi = newSyncApi;
34 | }
35 |
36 | export function GetZipApi() {
37 | return zipApi;
38 | }
39 |
40 | export function SetZipApi(newZipApi: typeof ZipApi | undefined) {
41 | zipApi = newZipApi;
42 | }
43 |
--------------------------------------------------------------------------------
/src/msg/ContextErrorListener.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is released under the MIT license.
3 | * Copyright (c) 2016, 2017 Mike Lischke
4 | *
5 | * See LICENSE file for more info.
6 | */
7 |
8 | "use strict";
9 |
10 | import { ANTLRErrorListener, Recognizer, RecognitionException, Token, CommonToken } from 'antlr4ts';
11 |
12 | import { DiagnosticEntry, DiagnosticType } from './Facade';
13 |
14 | export class ContextLexerErrorListener implements ANTLRErrorListener {
15 | constructor(private errorList: DiagnosticEntry[]) {
16 | }
17 |
18 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
19 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void {
20 | let error: DiagnosticEntry = {
21 | type: DiagnosticType.Error,
22 | message: msg,
23 | range: { start: { column: charPositionInLine, row: line }, end: { column: charPositionInLine + 1, row: line }}
24 | };
25 |
26 | this.errorList.push(error);
27 | }
28 | }
29 |
30 | export class ContextErrorListener implements ANTLRErrorListener {
31 | constructor(private errorList: DiagnosticEntry[]) {
32 | }
33 |
34 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
35 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void {
36 | let error: DiagnosticEntry = {
37 | type: DiagnosticType.Error,
38 | message: msg,
39 | range: { start: { column: charPositionInLine, row: line }, end: { column: charPositionInLine + 1, row: line }}
40 | };
41 |
42 | if (offendingSymbol) {
43 | error.range.end.column = charPositionInLine + offendingSymbol.stopIndex - offendingSymbol.startIndex + 1;
44 | }
45 | this.errorList.push(error);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/msg/DefinitionProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Location, Uri, ProviderResult, DefinitionProvider } from 'vscode';
2 | import { MsgFacade } from './Facade';
3 |
4 | export class MsgDefinitionProvider implements DefinitionProvider {
5 | constructor(private backend: MsgFacade) { }
6 |
7 | public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): ProviderResult {
8 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character, position.line + 1);
9 |
10 | if (!info) {
11 | return undefined;
12 | }
13 |
14 | if (info.definition) {
15 | let range = new Range(
16 | info.definition.range.start.row - 1, info.definition.range.start.column,
17 | info.definition.range.end.row - 1, info.definition.range.end.column
18 | );
19 | return new Location(Uri.file(info.source), range);
20 | } else {
21 | // Empty for built-in entities.
22 | let position = new Position(0, 0);
23 | return new Location(Uri.parse(""), position);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/msg/HoverProvider.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 | import { HoverProvider, TextDocument, Position, CancellationToken, ProviderResult, Hover } from "vscode";
3 | import { MsgFacade } from "./Facade";
4 | import { symbolDescriptionFromEnum } from './Symbol';
5 |
6 | export class MsgHoverProvider implements HoverProvider {
7 | constructor(private backend: MsgFacade) { }
8 |
9 | public provideHover(document: TextDocument, position: Position, token: CancellationToken): ProviderResult {
10 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character, position.line + 1);
11 | if (!info) {
12 | return undefined;
13 | }
14 |
15 | return new Hover([
16 | info.description? info.description : symbolDescriptionFromEnum(info.kind)
17 | ]);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/msg/RenameProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Location, Uri, ProviderResult, WorkspaceEdit, RenameProvider } from 'vscode';
2 | import { MsgFacade, SymbolKind, SymbolInfo } from './Facade';
3 |
4 | export class MsgRenameProvider implements RenameProvider {
5 | constructor(private backend: MsgFacade) { }
6 |
7 | public prepareRename(document: TextDocument, position: Position, token: CancellationToken): ProviderResult {
8 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character, position.line + 1);
9 |
10 | if (info && info.definition) {
11 | return new Range(
12 | info.definition.range.start.row - 1,
13 | info.definition.range.start.column,
14 | info.definition.range.end.row - 1,
15 | info.definition.range.end.column);
16 | }
17 |
18 | return undefined;
19 | }
20 |
21 | public provideRenameEdits(document: TextDocument, position: Position, newName: string,
22 | token: CancellationToken): ProviderResult {
23 | const occurences = this.backend.getSymbolOccurences(document.fileName, position.character, position.line + 1);
24 | if (occurences.length) {
25 | const result = new WorkspaceEdit();
26 | for (let symbol of occurences) {
27 | if (symbol.definition) {
28 | let range = new Range(
29 | symbol.definition.range.start.row - 1, symbol.definition.range.start.column,
30 | symbol.definition.range.end.row - 1, symbol.definition.range.end.column
31 | );
32 | result.replace(Uri.file(symbol.source), range, newName);
33 | }
34 | }
35 | return result;
36 | }
37 | return undefined;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/msg/Symbol.ts:
--------------------------------------------------------------------------------
1 | import * as nls from "vscode-nls";
2 | import * as vscode from 'vscode';
3 | import { SymbolKind } from './Facade';
4 |
5 | nls.config({messageFormat: nls.MessageFormat.both});
6 | const localize = nls.loadMessageBundle();
7 |
8 | /**
9 | * Provides a textual expression for a native symbol kind.
10 | */
11 | export function symbolDescriptionFromEnum(kind: SymbolKind): string {
12 | // Could be localized.
13 | switch (kind) {
14 | case SymbolKind.Keyword:
15 | return localize("keyword", "Keyword");
16 | case SymbolKind.Operator:
17 | return localize("operator", "Operator");
18 | case SymbolKind.Literal:
19 | return localize("literal", "Literal");
20 | case SymbolKind.Message:
21 | return localize("message", "Message");
22 | case SymbolKind.Variable:
23 | return localize("variable", "Variable");
24 | case SymbolKind.FacilityName:
25 | return localize("facility", "Facility name");
26 | case SymbolKind.FacilityPrefix:
27 | return localize("prefix", "Facility prefix");
28 | default:
29 | return "Unknown type";
30 | }
31 | }
32 |
33 | /**
34 | * Converts the native symbol kind to a vscode symbol kind.
35 | */
36 | export function translateSymbolKind(kind: SymbolKind): vscode.SymbolKind {
37 | switch (kind) {
38 |
39 | default:
40 | return vscode.SymbolKind.Null;
41 | }
42 | }
43 |
44 | /**
45 | * Converts the native symbol kind to a vscode symbol kind.
46 | */
47 | export function translateCompletionKind(kind: SymbolKind): vscode.CompletionItemKind {
48 | switch (kind) {
49 | case SymbolKind.Keyword:
50 | return vscode.CompletionItemKind.Keyword;
51 |
52 | default:
53 | return vscode.CompletionItemKind.Text;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/msg/msg.tokens:
--------------------------------------------------------------------------------
1 | TITLE=1
2 | IDENT=2
3 | PAGE=3
4 | LITERAL=4
5 | FACILITY=5
6 | SEVERITY=6
7 | BASE=7
8 | END=8
9 | PREFIX=9
10 | SHARED=10
11 | SYSTEM=11
12 | FAOCOUNT=12
13 | IDENTIFICATION=13
14 | USERVALUE=14
15 | SUCCESS=15
16 | INFORMATIONAL=16
17 | WARNING=17
18 | ERROR=18
19 | SEVERE=19
20 | FATAL=20
21 | WHITESPACE=21
22 | NEWLINE=22
23 | NAME=23
24 | NUMBER=24
25 | ASSIGN=25
26 | ADD=26
27 | SUB=27
28 | MUL=28
29 | DIV=29
30 | SHIFT=30
31 | SHARP=31
32 | PERC=32
33 | POW=33
34 | UNDER=34
35 | P_OPEN=35
36 | P_CLOS=36
37 | HEXNUM=37
38 | OCTNUM=38
39 | DECNUM=39
40 | DOT=40
41 | COMMA=41
42 | EXCL=42
43 | ASTRING_OPEN=43
44 | QSTRING_OPEN=44
45 | BSTRING_OPEN=45
46 | ANY=46
47 | IDENTSEP=47
48 | IDENTNAME=48
49 | IDENTSTRING=49
50 | IDENTCOMMENT=50
51 | IDENT_CLOSE=51
52 | BSTRING_CLOSE=52
53 | BFAO=53
54 | BTEXT=54
55 | QSTRING_CLOSE=55
56 | QFAO=56
57 | QTEXT=57
58 | ASTRING_CLOSE=58
59 | AFAO=59
60 | ATEXT=60
61 | '='=25
62 | '+'=26
63 | '-'=27
64 | '*'=28
65 | '/'=29
66 | '@'=30
67 | '#'=31
68 | '%'=32
69 | '^'=33
70 | '_'=34
71 | '('=35
72 | ')'=36
73 | '.'=40
74 | ','=41
75 | '!'=42
76 | '<'=45
77 | '>'=52
78 |
--------------------------------------------------------------------------------
/src/msg/msgLex.tokens:
--------------------------------------------------------------------------------
1 | TITLE=1
2 | IDENT=2
3 | PAGE=3
4 | LITERAL=4
5 | FACILITY=5
6 | SEVERITY=6
7 | BASE=7
8 | END=8
9 | PREFIX=9
10 | SHARED=10
11 | SYSTEM=11
12 | FAOCOUNT=12
13 | IDENTIFICATION=13
14 | USERVALUE=14
15 | SUCCESS=15
16 | INFORMATIONAL=16
17 | WARNING=17
18 | ERROR=18
19 | SEVERE=19
20 | FATAL=20
21 | WHITESPACE=21
22 | NEWLINE=22
23 | NAME=23
24 | NUMBER=24
25 | ASSIGN=25
26 | ADD=26
27 | SUB=27
28 | MUL=28
29 | DIV=29
30 | SHIFT=30
31 | SHARP=31
32 | PERC=32
33 | POW=33
34 | UNDER=34
35 | P_OPEN=35
36 | P_CLOS=36
37 | HEXNUM=37
38 | OCTNUM=38
39 | DECNUM=39
40 | DOT=40
41 | COMMA=41
42 | EXCL=42
43 | ASTRING_OPEN=43
44 | QSTRING_OPEN=44
45 | BSTRING_OPEN=45
46 | ANY=46
47 | IDENTSEP=47
48 | IDENTNAME=48
49 | IDENTSTRING=49
50 | IDENTCOMMENT=50
51 | IDENT_CLOSE=51
52 | BSTRING_CLOSE=52
53 | BFAO=53
54 | BTEXT=54
55 | QSTRING_CLOSE=55
56 | QFAO=56
57 | QTEXT=57
58 | ASTRING_CLOSE=58
59 | AFAO=59
60 | ATEXT=60
61 | '='=25
62 | '+'=26
63 | '-'=27
64 | '*'=28
65 | '/'=29
66 | '@'=30
67 | '#'=31
68 | '%'=32
69 | '^'=33
70 | '_'=34
71 | '('=35
72 | ')'=36
73 | '.'=40
74 | ','=41
75 | '!'=42
76 | '<'=45
77 | '>'=52
78 |
--------------------------------------------------------------------------------
/src/python/debugConfig.ts:
--------------------------------------------------------------------------------
1 |
2 | import { DebugProtocol } from "@vscode/debugprotocol";
3 | import { DebugConfiguration, WorkspaceFolder } from "vscode";
4 |
5 | /**
6 | * This interface describes the vms_jvm_debugger specific launch attributes
7 | * (which are not part of the Debug Adapter Protocol).
8 | * The schema for these attributes lives in the package.json of the mock-debug extension.
9 | * The interface should always match this schema.
10 | */
11 | export interface IPythonLaunchRequestArguments extends DebugProtocol.LaunchRequestArguments {
12 | /** a script to execute. */
13 | script: string;
14 | /** a VMS command to execute before. */
15 | pre_launch?: string;
16 | /** a port to debug. */
17 | port?: string;
18 | /** command line arguments */
19 | arguments?: string;
20 | /** python arguments */
21 | python_args?: string;
22 | /** current workspace folder */
23 | workspace: WorkspaceFolder;
24 | }
25 |
26 | export interface IPythonDebugConfiguration extends DebugConfiguration {
27 | /** a script to execute. */
28 | script: string;
29 | /** a VMS command to execute before. */
30 | pre_launch?: string;
31 | /** a port to debug. */
32 | port?: string;
33 | /** command line arguments */
34 | arguments?: string;
35 | /** python arguments */
36 | python_args?: string;
37 | /** current workspace folder */
38 | workspace: WorkspaceFolder;
39 | }
40 |
41 | export function isPythonDebugConfiguration(candidate: any): candidate is IPythonDebugConfiguration {
42 | return !!candidate &&
43 | typeof candidate.type === "string" &&
44 | typeof candidate.name === "string" &&
45 | typeof candidate.request === "string" &&
46 | (typeof candidate.python_args === undefined || typeof candidate.python_args === "string") &&
47 | (typeof candidate.arguments === undefined || typeof candidate.arguments === "string") &&
48 | (typeof candidate.pre_launch === undefined || typeof candidate.pre_launch === "string") &&
49 | (typeof candidate.port === undefined || typeof candidate.port === "number") &&
50 | typeof candidate.script === "string";
51 | }
--------------------------------------------------------------------------------
/src/python/extension.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------
2 | * Copyright (C) VMS Corporation. All rights reserved.
3 | *--------------------------------------------------------*/
4 |
5 | import { LogFunction, LogType } from "../common/main";
6 | import * as vscode from "vscode";
7 | import * as nls from "vscode-nls";
8 | import { createLogFunction } from "../config-helper/log";
9 | import { PythonConfigurationProvider, PythonDebugAdapterDescriptorFactory } from "./provider";
10 |
11 | nls.config({messageFormat: nls.MessageFormat.both});
12 | const localize = nls.loadMessageBundle();
13 |
14 | let logFn: LogFunction;
15 |
16 | export function activate(context: vscode.ExtensionContext)
17 | {
18 | logFn = createLogFunction("VMS-IDE");
19 |
20 | // register a configuration provider for 'vms jvm debugger' debug type
21 | const provider = new PythonConfigurationProvider();
22 | context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider(PythonConfigurationProvider.debuggerType, provider));
23 |
24 | const factory = new PythonDebugAdapterDescriptorFactory(logFn);
25 | context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory(PythonConfigurationProvider.debuggerType, factory));
26 | context.subscriptions.push(factory);
27 | }
28 |
29 | export function deactivate()
30 | {
31 | // nothing to do
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/src/ssh-helper/config-api.ts:
--------------------------------------------------------------------------------
1 | import { IConfigApi } from "../config-helper/config/config";
2 | import { GetConfigHelperFromApi } from "../ext-api/ext-api";
3 |
4 | export let configApi: IConfigApi | undefined;
5 |
6 | export async function ensureConfigHelperApi(): Promise {
7 | if (!configApi) {
8 | configApi = GetConfigHelperFromApi();
9 | }
10 | return configApi !== undefined;
11 | }
12 |
--------------------------------------------------------------------------------
/src/ssh-helper/config-resolve/agent-filler.ts:
--------------------------------------------------------------------------------
1 |
2 | import { LogFunction, LogType } from "../../common/main";
3 | import { IConnectConfig } from "../api";
4 | import { ISettingsFiller } from "./settings-filler";
5 |
6 | export class AgentFiller implements ISettingsFiller {
7 |
8 | public logFn: LogFunction;
9 |
10 | constructor(logFunc?: LogFunction) {
11 | // tslint:disable-next-line:no-empty
12 | this.logFn = logFunc || (() => {});
13 | }
14 |
15 | /**
16 | * True it settings has unempty host and username
17 | * @param settings
18 | */
19 | public testSettings(settings: IConnectConfig): boolean {
20 | const ret = typeof settings.host === "string" && !!settings.host &&
21 | typeof settings.username === "string" && !!settings.username &&
22 | ((typeof settings.addConnectConfig?.agent === "string" && !!settings.addConnectConfig?.agent));
23 | return ret;
24 | }
25 |
26 | public async fillSetting(settings: IConnectConfig): Promise {
27 |
28 | if (typeof settings.addConnectConfig?.agent === "string" && !!settings.addConnectConfig?.agent) {
29 | // ok, already has
30 | return true;
31 | }
32 | return false;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/ssh-helper/config-resolve/context-password-filler.ts:
--------------------------------------------------------------------------------
1 | import { Lock } from "../../common/main";
2 |
3 | import { IConnectConfig } from "../api";
4 | import { ISettingsFiller } from "./settings-filler";
5 |
6 | export interface IContextPassword {
7 | host?: string;
8 | password?: string;
9 | }
10 |
11 | export class ContextPasswordFiller implements ISettingsFiller {
12 |
13 | private lock = new Lock();
14 |
15 | constructor(public contexts: IContextPassword[] = [], public emulateUserDelay = 0) {
16 | }
17 |
18 | public testSettings(settings: IConnectConfig): boolean {
19 | const ret = typeof settings.host === "string" &&
20 | !!settings.host &&
21 | typeof settings.username === "string" &&
22 | !!settings.username;
23 | return ret;
24 | }
25 |
26 | public async fillSetting(settings: IConnectConfig): Promise {
27 |
28 | if (typeof settings.password === "string" &&
29 | settings.password) {
30 | // ok, already has
31 | return true;
32 | }
33 |
34 | for (const context of this.contexts) {
35 | if (context.host === settings.host) {
36 | if (this.emulateUserDelay !== 0) {
37 | await this.lock.acquire(); // to prevent concurrent use of console
38 | const waitUser = new Lock(true); // simulate user
39 | setTimeout(() => {
40 | settings.password = context.password;
41 | waitUser.release();
42 | }, this.emulateUserDelay);
43 | await waitUser.acquire(); // do not pass until password entered
44 | this.lock.release();
45 | } else {
46 | settings.password = context.password;
47 | }
48 | }
49 | }
50 |
51 | return !!settings.password;
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/ssh-helper/config-resolve/host-filler.ts:
--------------------------------------------------------------------------------
1 |
2 | import { LogFunction } from "../../common/main";
3 | import { IConnectConfig, IHostsSection } from "../api";
4 | import { ISettingsFiller } from "./settings-filler";
5 |
6 | export class HostFiller implements ISettingsFiller {
7 |
8 | public static rg = /^<(.*)>$/;
9 |
10 | public logFn: LogFunction;
11 |
12 | constructor(public hostSection: IHostsSection, logFunc?: LogFunction) {
13 | // tslint:disable-next-line:no-empty
14 | this.logFn = logFunc || (() => {});
15 | }
16 |
17 | /**
18 | * If settings has then resolve it from hosts and pass to the next fillers
19 | * @param settings
20 | */
21 | public testSettings(settings: IConnectConfig): boolean {
22 | if (typeof settings.host === "string" && !!settings.host) {
23 | const matched = settings.host.match(HostFiller.rg);
24 | if (matched) {
25 | for (const host of this.hostSection.hosts) {
26 | if (host.label === matched[1]) {
27 | settings.host = host.host;
28 | settings.port = host.port;
29 | settings.username = host.username;
30 | settings.keyFile = host.keyFile;
31 | settings.password = host.password;
32 | settings.debug = host.debug;
33 | settings.skipSignatureVerification = host.skipSignatureVerification?true:false;
34 | settings.algorithms = Object.assign({}, host.algorithms);
35 | settings.supportSetFileTime = host.supportSetFileTime;
36 | settings.unzipCmd = host.unzipCmd;
37 | settings.zipCmd = host.zipCmd;
38 | settings.addConnectConfig = host.addConnectConfig;
39 | break;
40 | }
41 | }
42 | }
43 | }
44 | return false;
45 | }
46 |
47 | public async fillSetting(settings: IConnectConfig): Promise {
48 | return false;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/ssh-helper/config-resolve/key-filler.ts:
--------------------------------------------------------------------------------
1 | import * as fs from "fs-extra";
2 |
3 | import { LogFunction, LogType } from "../../common/main";
4 | import { IConnectConfig } from "../api";
5 | import { ISettingsFiller } from "./settings-filler";
6 |
7 | export class KeyFiller implements ISettingsFiller {
8 |
9 | public logFn: LogFunction;
10 |
11 | constructor(logFunc?: LogFunction) {
12 | // tslint:disable-next-line:no-empty
13 | this.logFn = logFunc || (() => {});
14 | }
15 |
16 | /**
17 | * True it settings has unempty host and username
18 | * @param settings
19 | */
20 | public testSettings(settings: IConnectConfig): boolean {
21 | const ret = typeof settings.host === "string" && !!settings.host &&
22 | typeof settings.username === "string" && !!settings.username &&
23 | ( (typeof settings.privateKey === "string" && !!settings.privateKey) ||
24 | Buffer.isBuffer(settings.privateKey) ||
25 | (typeof settings.keyFile === "string" && !!settings.keyFile)
26 | );
27 | return ret;
28 | }
29 |
30 | public async fillSetting(settings: IConnectConfig): Promise {
31 |
32 | if (typeof settings.privateKey === "string" ||
33 | Buffer.isBuffer(settings.privateKey)) {
34 | // ok, already has
35 | return true;
36 | }
37 | if (!settings.keyFile) {
38 | return false;
39 | }
40 | try {
41 | settings.privateKey = await fs.readFile(settings.keyFile);
42 | // if (settings.keyFile !== undefined) {
43 | // delete settings.keyFile;
44 | // }
45 | if (settings.password !== undefined) {
46 | delete settings.password;
47 | }
48 | return true;
49 | } catch (err) {
50 | this.logFn(LogType.error, () => String(err));
51 | return false;
52 | }
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/ssh-helper/config-resolve/password-console-filler.ts:
--------------------------------------------------------------------------------
1 | import * as readline from "readline";
2 |
3 | import { Lock } from "../../common/main";
4 |
5 | import { IConnectConfig } from "../api";
6 | import { ISettingsFiller } from "./settings-filler";
7 |
8 | import * as nls from "vscode-nls";
9 | nls.config({messageFormat: nls.MessageFormat.both});
10 | const localize = nls.loadMessageBundle();
11 |
12 | const lock = new Lock();
13 |
14 | export class PasswordConsoleFiller implements ISettingsFiller {
15 |
16 | /**
17 | * True it settings has unempty host and username
18 | * @param settings
19 | */
20 | public testSettings(settings: IConnectConfig): boolean {
21 | const ret = typeof settings.host === "string" &&
22 | !!settings.host &&
23 | typeof settings.username === "string" &&
24 | !!settings.username;
25 | return ret;
26 | }
27 |
28 | public async fillSetting(settings: IConnectConfig): Promise {
29 |
30 | if (typeof settings.password === "string" &&
31 | settings.password) {
32 | // ok, already has
33 | return true;
34 | }
35 |
36 | await lock.acquire(); // to prevent concurrent use of console
37 |
38 | let retCode = false;
39 | const waitUser = new Lock(true); // to wait user input
40 |
41 | settings.port = settings.port || 22;
42 | const readLineInterface = readline.createInterface(process.stdin, process.stdout);
43 | const prompt = localize("query.password", "Password for {0}@{1}:{2} ", settings.username, settings.host, settings.port);
44 | // TODO: how to use * instead of symbols?
45 | readLineInterface.question(prompt, (answer) => {
46 | readLineInterface.close();
47 | if (answer) {
48 | settings.password = answer;
49 | retCode = true;
50 | }
51 | waitUser.release(); // ok, may proceed
52 | });
53 |
54 | await waitUser.acquire(); // do not pass until password entered
55 |
56 | lock.release();
57 | return retCode;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/ssh-helper/config-resolve/password-filler.ts:
--------------------------------------------------------------------------------
1 | import { Lock } from "../../common/main";
2 |
3 | import { IConnectConfig } from "../api";
4 | import { ISettingsFiller } from "./settings-filler";
5 |
6 | export class ConstPasswordFiller implements ISettingsFiller {
7 |
8 | private lock = new Lock();
9 |
10 | constructor(public password: string, public timeout?: number) {
11 |
12 | }
13 |
14 | /**
15 | * True it settings has unempty host and username
16 | * @param settings
17 | */
18 | public testSettings(settings: IConnectConfig): boolean {
19 | const ret = typeof settings.host === "string" &&
20 | !!settings.host &&
21 | typeof settings.username === "string" &&
22 | !!settings.username;
23 | return ret;
24 | }
25 |
26 | public async fillSetting(settings: IConnectConfig): Promise {
27 |
28 | if (typeof settings.password === "string" &&
29 | settings.password) {
30 | // ok, already has
31 | return true;
32 | }
33 |
34 | await this.lock.acquire(); // to prevent concurrent use of console
35 |
36 | if (this.timeout) {
37 | const waitUser = new Lock(true); // simulate user
38 | setTimeout(() => {
39 | settings.password = this.password;
40 | if (settings.keyFile !== undefined) {
41 | delete settings.keyFile;
42 | }
43 | waitUser.release();
44 | }, this.timeout);
45 | await waitUser.acquire(); // do not pass until password entered
46 | } else {
47 | settings.password = this.password;
48 | }
49 |
50 | this.lock.release();
51 |
52 | return !!settings.password;
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/ssh-helper/config-resolve/password-vscode-filler.ts:
--------------------------------------------------------------------------------
1 |
2 | import { window } from "vscode";
3 |
4 | import { Lock } from "../../common/main";
5 |
6 | import { IConnectConfig } from "../api";
7 | import { ISettingsFiller } from "./settings-filler";
8 |
9 | import * as nls from "vscode-nls";
10 | nls.config({messageFormat: nls.MessageFormat.both});
11 | const localize = nls.loadMessageBundle();
12 |
13 | const lock = new Lock();
14 |
15 | export class PasswordVscodeFiller implements ISettingsFiller {
16 |
17 | /**
18 | * True it settings has unempty host and username
19 | * @param settings
20 | */
21 | public testSettings(settings: IConnectConfig): boolean {
22 | const ret = typeof settings.host === "string" &&
23 | !!settings.host &&
24 | typeof settings.username === "string" &&
25 | !!settings.username;
26 | return ret;
27 | }
28 |
29 | public async fillSetting(settings: IConnectConfig): Promise {
30 | if (typeof settings.password === "string" &&
31 | settings.password) {
32 | // ok, already has
33 | return true;
34 | }
35 | await lock.acquire(); // to prevent concurrent using
36 | settings.port = settings.port || 22;
37 | const prompt = localize("query.password", "Password for {0}@{1}:{2} ", settings.username, settings.host, settings.port);
38 | settings.password = await window.showInputBox( { password: true, prompt, ignoreFocusOut: true });
39 | if (settings.keyFile !== undefined) {
40 | delete settings.keyFile;
41 | }
42 | lock.release();
43 | return settings.password !== undefined;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/ssh-helper/config-resolve/settings-filler.ts:
--------------------------------------------------------------------------------
1 |
2 | import { IConnectConfig } from "../api";
3 |
4 | export interface ISettingsFiller {
5 | /**
6 | * Test if that kind of settings can be filled by this implementation, may change settings object
7 | * @param settings settings to test
8 | * @returns true if can be filled (or already filled)
9 | */
10 | testSettings(settings: IConnectConfig): boolean;
11 |
12 | /**
13 | * Fill settings, should change settings object
14 | * @param settings settings to fill out
15 | * @returns true if settings filled and can be used
16 | */
17 | fillSetting(settings: IConnectConfig): Promise;
18 | }
19 |
--------------------------------------------------------------------------------
/src/ssh-helper/config/sections/hosts.ts:
--------------------------------------------------------------------------------
1 | import { IConfigData, IConfigSection, ValueData } from "../../../config-helper/config/config";
2 | import { IHostsSection } from "../../api";
3 | import { LabeledConnection } from "./labeled-connection";
4 |
5 | export class HostsSection implements IConfigSection {
6 |
7 | public static readonly section = "host-collection";
8 |
9 | public static is(candidate: any): candidate is IHostsSection {
10 | return !!candidate &&
11 | candidate.hosts instanceof Array;
12 | }
13 | public hosts: LabeledConnection[] = [];
14 |
15 | public name(): string {
16 | return HostsSection.section;
17 | }
18 |
19 | public store(): IConfigData {
20 | const ret: IConfigData = {};
21 | ret.hosts = [] as IConfigData[];
22 | for (const tmp of this.hosts) {
23 | ret.hosts.push(tmp.store());
24 | }
25 | return ret;
26 | }
27 |
28 | public templateToFillFrom(): IConfigData {
29 | const ret: IConfigData = {
30 | hosts: [ new LabeledConnection().templateToFillFrom() ],
31 | };
32 | return ret;
33 | }
34 |
35 | public fillFrom(data: IConfigData): boolean {
36 | let retcode = true;
37 | this.hosts = [];
38 | if (data.hosts instanceof Array) {
39 | for (const host of data.hosts) {
40 | const tmp = new LabeledConnection();
41 | if (tmp.fillFrom(host as IConfigData)) {
42 | this.hosts.push(tmp);
43 | } else {
44 | retcode = false;
45 | }
46 | }
47 | }
48 | return retcode;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/ssh-helper/config/sections/labeled-connection.ts:
--------------------------------------------------------------------------------
1 | import { ConnectionSection } from "./connection";
2 |
3 | import { IConfigData } from "../../../config-helper/config/config";
4 |
5 | export class LabeledConnection extends ConnectionSection {
6 |
7 | public static is(candidate: any): candidate is LabeledConnection {
8 | return typeof candidate.label === "string" && ConnectionSection.is(candidate);
9 | }
10 |
11 | public label: string = "";
12 |
13 | public name(): string {
14 | return this.label;
15 | }
16 |
17 | public store(): IConfigData {
18 | const ret = super.store();
19 | ret.label = this.label;
20 | return ret;
21 | }
22 |
23 | public templateToFillFrom(): IConfigData {
24 | const ret = super.templateToFillFrom();
25 | ret.label = "";
26 | return ret;
27 | }
28 |
29 | public fillFrom(data: IConfigData): boolean {
30 | if (typeof data.label === "string") {
31 | this.label = data.label;
32 | }
33 | return super.fillFrom(data);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/ssh-helper/config/sections/terminal.ts:
--------------------------------------------------------------------------------
1 | import { IConfigData, IConfigSection } from "../../../config-helper/config/config";
2 | import { ITerminalSection } from "../../api";
3 |
4 | export class TerminalSection implements ITerminalSection, IConfigSection {
5 |
6 | public static readonly section = "terminal";
7 |
8 | public static is(candidate: any): candidate is ITerminalSection {
9 | return !!candidate &&
10 | typeof candidate.command === "string";
11 | }
12 |
13 | public command = "";
14 |
15 | public name(): string {
16 | return TerminalSection.section;
17 | }
18 |
19 | public store(): IConfigData {
20 | return this.templateToFillFrom();
21 | }
22 |
23 | public templateToFillFrom(): IConfigData {
24 | return {
25 | command: this.command,
26 | };
27 | }
28 |
29 | public fillFrom(data: IConfigData): boolean {
30 | if (TerminalSection.is(data)) {
31 | this.command = data.command;
32 | return true;
33 | }
34 | return false;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/ssh-helper/config/sections/timeouts.ts:
--------------------------------------------------------------------------------
1 | import { IConfigData, IConfigSection } from "../../../config-helper/config/config";
2 | import { ITimeoutsSection } from "../../api";
3 |
4 | export class TimeoutSection implements ITimeoutsSection, IConfigSection {
5 |
6 | public static readonly section = "timeouts";
7 |
8 | public static is(candidate: any): candidate is ITimeoutsSection {
9 | return !!candidate &&
10 | typeof candidate.cmdTimeout === "number" &&
11 | typeof candidate.feedbackTimeout === "number" &&
12 | typeof candidate.welcomeTimeout === "number";
13 | }
14 |
15 | public cmdTimeout: number = 0; // in msec
16 | public feedbackTimeout: number = 0; // in msec
17 | public welcomeTimeout: number = 0; // in msec
18 |
19 | public name(): string {
20 | return TimeoutSection.section;
21 | }
22 |
23 | public store(): IConfigData {
24 | return this.templateToFillFrom();
25 | }
26 |
27 | public templateToFillFrom(): IConfigData {
28 | return {
29 | cmdTimeout: this.cmdTimeout,
30 | feedbackTimeout: this.feedbackTimeout,
31 | welcomeTimeout: this.welcomeTimeout,
32 | };
33 | }
34 |
35 | public fillFrom(data: IConfigData): boolean {
36 | if (TimeoutSection.is(data)) {
37 | this.cmdTimeout = data.cmdTimeout;
38 | this.feedbackTimeout = data.feedbackTimeout;
39 | this.welcomeTimeout = data.welcomeTimeout;
40 | return true;
41 | }
42 | return false;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/ssh-helper/extension.ts:
--------------------------------------------------------------------------------
1 |
2 | import * as vscode from "vscode";
3 |
4 | import { configApi, ensureConfigHelperApi } from "./config-api";
5 | import { SshHelper } from "./ssh-helper";
6 |
7 | const locale = vscode.env.language ;
8 | import * as nls from "vscode-nls";
9 | const localize = nls.config({ locale, messageFormat: nls.MessageFormat.both })();
10 |
11 | export async function activate(context: vscode.ExtensionContext) {
12 |
13 | if (!await ensureConfigHelperApi() || !configApi) {
14 | return undefined;
15 | }
16 |
17 | const sshHelper = new SshHelper(configApi.createLogFunction("VMS-IDE"));
18 |
19 | setupWatchers(sshHelper);
20 |
21 | vscode.workspace.onDidChangeWorkspaceFolders(() => {
22 | setupWatchers(sshHelper);
23 | });
24 |
25 | context.subscriptions.push(sshHelper);
26 |
27 | return SshHelper; // class, not object
28 | }
29 |
30 | let watchers: vscode.Disposable[] = [];
31 |
32 | function setupWatchers(sshHelper: SshHelper) {
33 | watchers.forEach((watcher) => watcher.dispose());
34 | watchers = [];
35 | if (vscode.workspace.workspaceFolders) {
36 | for (const wf of vscode.workspace.workspaceFolders) {
37 | watchers.push(sshHelper.setConfigWatcher(wf.name, () => {
38 | sshHelper.killPasswordCache();
39 | sshHelper.testSettings(wf.name);
40 | }));
41 | }
42 | }
43 | }
44 |
45 | export function deactivate() {
46 | // do nothing
47 | }
48 |
--------------------------------------------------------------------------------
/src/ssh-helper/stream/parse-welcome.ts:
--------------------------------------------------------------------------------
1 | import { LogFunction, LogType } from "../../common/main";
2 | import { IParseWelcome } from "../api";
3 | import { ShellParser } from "./shell-parser";
4 | import { SshShell } from "./ssh-shell";
5 |
6 | import * as nls from "vscode-nls";
7 | nls.config({messageFormat: nls.MessageFormat.both});
8 | const localize = nls.loadMessageBundle();
9 |
10 | export class ParseWelcome extends ShellParser implements IParseWelcome {
11 |
12 | public prompt?: string;
13 |
14 | /**
15 | * Parses stream until the last line isn't the same as previous line. Writes EOL on each data received.
16 | * Caveat: may be the reason of garbage in output already after prompt is caught, so wait your command
17 | * before utilizing output.
18 | * @param timeout timeout prompt catching
19 | * @param logFn like console.log
20 | */
21 | constructor(timeout?: number, logFn?: LogFunction, tag?: string) {
22 | super(timeout, logFn, tag);
23 | }
24 |
25 | /**
26 | * Just write some if esc-code found, else welcome!
27 | */
28 | public _transform(chunk: any, encoding: string, callback: () => any) {
29 | super._transform(chunk, encoding, callback);
30 | if (Buffer.isBuffer(chunk)) {
31 | if (chunk.includes(27)) {
32 | this.push(SshShell.eol);
33 | } else {
34 | if (this.lines.length > 1) {
35 | if (this.lines[this.lines.length - 1].trim() === this.lastLine.trim()) {
36 | this.prompt = this.lastLine.trim();
37 | this.logFn(LogType.debug, () => localize("debug.prompt", "parse: found prompt '{0}'", this.prompt));
38 | this.setReady();
39 | }
40 | }
41 | if (this.prompt === undefined) {
42 | this.push(SshShell.eol);
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/ssh-helper/stream/prompt-catcher-vms.ts:
--------------------------------------------------------------------------------
1 | import { LogFunction, LogType } from "../../common/main";
2 |
3 | import { IPromptCatcher } from "../api";
4 | import { ShellParser } from "./shell-parser";
5 |
6 | export class PromptCatcherVms extends ShellParser implements IPromptCatcher {
7 |
8 | /**
9 | * Note: only the last prompt will be caught properly.
10 | * If do write several commands without catching each prompt some of these prompts may not be caught.
11 | */
12 | constructor(public prompt: string, timeout?: number, logFn?: LogFunction, tag?: string) {
13 | super(timeout, logFn, tag);
14 | }
15 |
16 | public _transform(chunk: any, encoding: string, callback: () => any) {
17 | super._transform(chunk, encoding, callback);
18 | if (Buffer.isBuffer(chunk)) {
19 | if (chunk.includes(0)) {
20 | const promptIdx = this.lastLine.lastIndexOf(String.fromCharCode(0));
21 | if (promptIdx >= 0) {
22 | this.lastLine = this.lastLine.slice(0, promptIdx);
23 | }
24 | this.setReady();
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/ssh-helper/stream/prompt-catcher.ts:
--------------------------------------------------------------------------------
1 | import { LogFunction, LogType } from "../../common/main";
2 |
3 | import { IPromptCatcher } from "../api";
4 | import { ShellParser } from "./shell-parser";
5 |
6 | export class PromptCatcher extends ShellParser implements IPromptCatcher {
7 |
8 | /**
9 | * Note: only the last prompt will be caught properly.
10 | * If do write several commands without catching each prompt some of these prompts may not be caught.
11 | */
12 | constructor(public prompt: string, timeout?: number, logFn?: LogFunction, tag?: string) {
13 | super(timeout, logFn, tag);
14 | }
15 |
16 | public _transform(chunk: any, encoding: string, callback: () => any) {
17 | super._transform(chunk, encoding, callback);
18 | if (this.lastLine.endsWith(this.prompt)) {
19 | // remove prompt
20 | this.lastLine = this.lastLine.slice(0, this.lastLine.length - this.prompt.length);
21 | // emit event and clear lastString
22 | this.setReady();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ssh-helper/stream/stream-creators.ts:
--------------------------------------------------------------------------------
1 | import { Readable, Writable } from "stream";
2 |
3 | import { ICanCreateReadStream, ICanCreateWriteStream, IMemoryStreamCreator } from "./../api";
4 |
5 | import { LogFunction, LogType, MemoryReadStream, MemoryWriteStream } from "../../common/main";
6 |
7 | export class MemoryStreamCreator implements IMemoryStreamCreator, ICanCreateReadStream, ICanCreateWriteStream {
8 |
9 | public readStream?: MemoryReadStream;
10 | public writeStream?: MemoryWriteStream;
11 |
12 | constructor(public chunks?: Array, public emulateError?: boolean, public logFn?: LogFunction) {
13 | }
14 |
15 | public async createReadStream(file: string): Promise {
16 | return this.readStream = new MemoryReadStream(this.chunks, this.logFn);
17 | }
18 |
19 | public async createWriteStream(file: string): Promise {
20 | return this.writeStream = new MemoryWriteStream(this.logFn, this.emulateError);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/ssh-helper/test/config/config.ts:
--------------------------------------------------------------------------------
1 | export async function TestConfiguration(local: boolean) {
2 | if (local) {
3 | return {
4 | host: "localhost",
5 | port: 22,
6 | username: "user",
7 | password: "pass",
8 | };
9 | } else {
10 | return {
11 | host: "104.207.199.181",
12 | port: 22,
13 | username: "vorfolomeev",
14 | keyFile: "H:/.ssh/sv01",
15 | };
16 | }
17 | }
--------------------------------------------------------------------------------
/src/synchronizer/command-context.ts:
--------------------------------------------------------------------------------
1 | import { commands } from "vscode";
2 |
3 | export enum CommandContext {
4 | isInAction = "vmssoftware.synchronizer.isInAction",
5 | // isSyncronizing = "vmssoftware.synchronizer.isSync",
6 | // isBuilding = "vmssoftware.synchronizer.isBuild",
7 | // isSaving = "vmssoftware.synchronizer.isSaving",
8 | // isCrLf = "vmssoftware.synchronizer.isCrLf",
9 | // isEdit = "vmssoftware.synchronizer.isEdit",
10 | // isHeaders = "vmssoftware.synchronizer.isHeaders",
11 | }
12 |
13 | const contextMap = new Map();
14 |
15 | export function setContext(context: CommandContext, state: boolean) {
16 | contextMap.set(context, state);
17 | commands.executeCommand("setContext", context, state);
18 | }
19 |
20 | export function getContext(context: CommandContext): boolean {
21 | return !!contextMap.get(context);
22 | }
23 |
--------------------------------------------------------------------------------
/src/synchronizer/common/TestExecResult.ts:
--------------------------------------------------------------------------------
1 |
2 | const rgx = /(?:%|-)(?:\w+)-(?:W|E|F)-(?:\w+), (.*)/;
3 | /**
4 | *
5 | * @param result
6 | * @returns error string or indefined
7 | */
8 | export function ParseExecResult(result: string[] | undefined): string[] {
9 | if (!result) {
10 | return ["No result"];
11 | }
12 | let errors: string[] = [];
13 | for (let line of result) {
14 | let match = line.match(rgx);
15 | if (match && match[1]) {
16 | errors.push(match[1]);
17 | }
18 | }
19 | return errors;
20 | }
--------------------------------------------------------------------------------
/src/synchronizer/common/create-file.ts:
--------------------------------------------------------------------------------
1 | import vscode from "vscode";
2 |
3 | export async function createFile(fileUri: vscode.Uri, content: string) {
4 | try {
5 | let range: vscode.Range | undefined;
6 | try {
7 | const textDoc = await vscode.workspace.openTextDocument(fileUri);
8 | range = textDoc.validateRange(new vscode.Range(0, 0, 32767, 32767));
9 | } catch (err) {
10 | range = undefined;
11 | }
12 | const we = new vscode.WorkspaceEdit();
13 | if (!range) {
14 | we.createFile(fileUri);
15 | we.insert(fileUri, new vscode.Position(0, 0), content);
16 | } else {
17 | we.replace(fileUri, range, content);
18 | }
19 | const status = await vscode.workspace.applyEdit(we);
20 | if (status) {
21 | const textDoc = await vscode.workspace.openTextDocument(fileUri);
22 | const saved = await textDoc.save();
23 | return saved;
24 | } else {
25 | return false;
26 | }
27 | } catch (err) {
28 | return false;
29 | }
30 | }
31 |
32 | export async function loadFile(fileUri: vscode.Uri) {
33 | try {
34 | const textDoc = await vscode.workspace.openTextDocument(fileUri);
35 | return textDoc.getText();
36 | } catch (err) {
37 | return "";
38 | }
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/src/synchronizer/common/progress.ts:
--------------------------------------------------------------------------------
1 | import { Disposable, window } from "vscode";
2 | import { IProgress } from "../sync/source";
3 |
4 | export interface IValueOfMax {
5 | value: number;
6 | maxValue?: number;
7 | }
8 |
9 | export class Progress implements IProgress, Disposable {
10 |
11 | private map: Map = new Map();
12 |
13 | private prevMessage: Disposable | undefined;
14 |
15 | public getToken(token: string) {
16 | return this.map.get(token);
17 | }
18 |
19 | public dispose() {
20 | if (this.prevMessage) {
21 | this.prevMessage.dispose();
22 | }
23 | this.prevMessage = undefined;
24 | }
25 |
26 | public addProgress(token: string, addValue: number): boolean {
27 | let prev = this.map.get(token);
28 | if (!prev) {
29 | prev = { value: 0, maxValue: 0};
30 | }
31 | prev.value += addValue;
32 | this.map.set(token, prev);
33 | this.update();
34 | return false; // no canceling at all
35 | }
36 |
37 | public setProgress(token: string, value: number, maxValue?: number): boolean {
38 | maxValue = maxValue || 0;
39 | this.map.set(token, {value, maxValue});
40 | this.update();
41 | return false; // no canceling at all
42 | }
43 |
44 | private update() {
45 | // setImmediate(() => {
46 | const strArr: string[] = [];
47 | for ( const [key, valueOf] of this.map) {
48 | if (strArr.length > 0) {
49 | strArr.push(", ");
50 | }
51 | strArr.push(key);
52 | strArr.push(": ");
53 | strArr.push(String(valueOf.value));
54 | if (valueOf.maxValue) {
55 | strArr.push(" of ");
56 | strArr.push(String(valueOf.maxValue));
57 | }
58 | }
59 | if (this.prevMessage) {
60 | this.prevMessage.dispose();
61 | }
62 | this.prevMessage = window.setStatusBarMessage(strArr.join(""));
63 | // });
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/synchronizer/context.ts:
--------------------------------------------------------------------------------
1 | import { ExtensionContext } from "vscode";
2 |
3 | export let contextSaved: ExtensionContext | undefined;
4 |
5 | export function setExtensionContext(context: ExtensionContext) {
6 | contextSaved = context;
7 | }
8 |
--------------------------------------------------------------------------------
/src/synchronizer/on-the-same-vms.ts:
--------------------------------------------------------------------------------
1 | import { LogFunction } from "../common/main";
2 |
3 | import { GetSshHelperType } from "../ext-api/ext-api";
4 | import { IConnectConfig } from "../ssh-helper/api";
5 | import { ProjDepTree } from "./dep-tree/proj-dep-tree";
6 |
7 | export async function onTheSameVms(scope: string, logFn: LogFunction) {
8 | if (!scope) {
9 | return true;
10 | }
11 | const sshHelperType = await GetSshHelperType();
12 | if (!sshHelperType) {
13 | return true;
14 | }
15 | const sshHelper = new sshHelperType(logFn);
16 | const deps = new ProjDepTree().getDepList(scope);
17 | let testConnectionSettings: IConnectConfig | undefined;
18 | for (const dep of deps) {
19 | const cfg = await sshHelper.getSettings(dep);
20 | if (cfg) {
21 | const res = cfg.connectConfigResolver.testConnectConfig(cfg.connectionSection);
22 | if (res.settings) {
23 | if (!testConnectionSettings) {
24 | testConnectionSettings = res.settings;
25 | } else if (testConnectionSettings.host !== res.settings.host ||
26 | testConnectionSettings.username !== res.settings.username) {
27 | return false;
28 | }
29 | }
30 | }
31 | }
32 | return true;
33 | }
34 |
--------------------------------------------------------------------------------
/src/synchronizer/projectDepend.ts:
--------------------------------------------------------------------------------
1 | import { Event } from "vscode";
2 |
3 | let _projectDependenciesChanged: Event | undefined;
4 |
5 | export function projectDependenciesChanged(): Event | undefined {
6 | return _projectDependenciesChanged;
7 | }
8 |
9 | export function setProjectDependenciesChanged(value: Event | undefined) {
10 | _projectDependenciesChanged = value;
11 | }
--------------------------------------------------------------------------------
/src/synchronizer/sync/source.ts:
--------------------------------------------------------------------------------
1 | import { IFileEntry } from "../../common/main";
2 |
3 | import { Readable, Writable } from "stream";
4 |
5 | export interface IProgress {
6 | /**
7 | * Show progress
8 | * @param token name
9 | * @param addvalue amount of progress
10 | * @returns true on cancel
11 | */
12 | addProgress(token: string, addvalue: number): boolean;
13 |
14 | /**
15 | * Set progress
16 | * @param token name
17 | * @param value current value
18 | * @param maxvalue max value
19 | */
20 | setProgress(token: string, value: number, maxvalue?: number): boolean;
21 | }
22 |
23 | export type sourceType = "local" | "remote";
24 |
25 | export interface ISource {
26 | root?: string;
27 | attempts?: number;
28 | enabled: boolean;
29 | createReadStream(filename: string): Promise;
30 | createWriteStream(filename: string): Promise;
31 | dispose(): void;
32 | ensureDirectory(directory: string): Promise;
33 | findFiles(include: string, exclude?: string, progress?: IProgress): Promise;
34 | getDate(filename: string): Promise;
35 | setDate(filename: string, date: Date): Promise;
36 | accessFile(filename: string): Promise;
37 | deleteFile(filename: string): Promise;
38 | }
39 |
--------------------------------------------------------------------------------
/src/synchronizer/test/config/vms.ts:
--------------------------------------------------------------------------------
1 | export const Vms = {
2 | host: "10.11.108.21",
3 | keyFile: "h:/.ssh/sv01",
4 | port: 22,
5 | username: "vorfolomeev",
6 | };
7 |
--------------------------------------------------------------------------------
/src/synchronizer/test/problem.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from "assert";
2 |
3 | import { logConsoleFn, LogFunction, LogType } from "../../common/main";
4 |
5 | import { inspect } from "util";
6 | import { parseVmsOutput } from "../common/parse-output";
7 | import { VmsPathConverter } from "../vms/vms-path-converter";
8 |
9 | suite("Source tests", function(this: Mocha.Suite) {
10 |
11 | return;
12 |
13 | this.timeout(0);
14 |
15 | let debugLogFn: LogFunction | undefined;
16 | debugLogFn = logConsoleFn;
17 |
18 | const output =
19 | `
20 | for (int i = 0; i < 10; ++j) {
21 | ..............................^
22 | %CXX-E-UNDECLARED, identifier "j" is undefined
23 | at line number 9 in file WORK:[VORFOLOMEEV.WORK]main.cpp;6
24 |
25 | %CXX-I-MESSAGE, 1 error detected in the compilation of "WORK:[VORFOLOMEEV.WORK]main.cpp;6".
26 | %MMS-F-ABORT, For target [.OUT.DEBUG.OBJ]MAIN.OBJ, CLI returned abort status: %X15F61262.
27 |
28 | `;
29 | test("Test p1", async () => {
30 | const c1 = VmsPathConverter.fromVms("[.a.b]c.d");
31 | const c2 = VmsPathConverter.fromVms("[a.b]c.d");
32 | const result = parseVmsOutput(output.split(/[\r?|\r\n]/));
33 | if (debugLogFn) {
34 | debugLogFn(LogType.debug, () => inspect(result));
35 | }
36 | assert.ok(true, "ok");
37 | });
38 |
39 | });
40 |
--------------------------------------------------------------------------------
/src/synchronizer/test/sftp-readdir.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from "assert";
2 |
3 | import { SshHelper } from "../../ssh-helper/ssh-helper";
4 |
5 | import { logConsoleFn, LogFunction, LogType } from "../../common/main";
6 | import { GetSshHelperType } from "../../ext-api/ext-api";
7 |
8 | suite("Directory tests", function(this: Mocha.Suite) {
9 |
10 | return;
11 |
12 | this.timeout(0);
13 |
14 | let debugLogFn: LogFunction | undefined;
15 | debugLogFn = logConsoleFn;
16 |
17 | let sshHelper: SshHelper;
18 |
19 | this.beforeAll(async () => {
20 | const sshHelperType = await GetSshHelperType();
21 | assert.notEqual(sshHelperType, undefined, `Cannot get ssh-helper api`);
22 | sshHelper = new sshHelperType!(debugLogFn);
23 | });
24 |
25 | test(`Read local "" dirname`, async () => {
26 | const sftp = await sshHelper.getTestSftp({host: "localhost", port: 22, username: "user", password: "pass"});
27 | assert.notEqual(sftp, undefined, "sftp must be defined");
28 | const files = await sftp!.readDirectory("");
29 | sftp!.dispose();
30 | assert.notEqual(files, undefined, "files must be defined");
31 | if (files) {
32 | assert.notEqual(files.length, 0, "files must not be empty");
33 | }
34 | });
35 |
36 | test(`Read local "WRK" dirname`, async () => {
37 | const sftp = await sshHelper.getTestSftp({host: "localhost", port: 22, username: "user", password: "pass"});
38 | assert.notEqual(sftp, undefined, "sftp must be defined");
39 | const files = await sftp!.readDirectory("WRK");
40 | sftp!.dispose();
41 | assert.notEqual(files, undefined, "files must be defined");
42 | if (files) {
43 | assert.notEqual(files.length, 0, "files must not be empty");
44 | }
45 | });
46 |
47 | test(`Read local "unexist" dirname`, async () => {
48 | const sftp = await sshHelper.getTestSftp({host: "localhost", port: 22, username: "user", password: "pass"});
49 | assert.notEqual(sftp, undefined, "sftp must be defined");
50 | const files = await sftp!.readDirectory("unexist");
51 | sftp!.dispose();
52 | assert.equal(files, undefined, "files must be defined");
53 | });
54 |
55 | });
56 |
--------------------------------------------------------------------------------
/src/synchronizer/vms/vms-absolute-date-string.ts:
--------------------------------------------------------------------------------
1 |
2 | export function VmsAbsoluteDateString(date: Date, locale: string = "en-US"): string {
3 | const day = date.getDate().toString(10).padStart(2, "0");
4 | const year = date.getFullYear().toString(10);
5 | const hour = date.getHours().toString(10).padStart(2, "0");
6 | const minute = date.getMinutes().toString(10).padStart(2, "0");
7 | const sec = date.getSeconds().toString(10).padStart(2, "0");
8 |
9 | const f = new Intl.DateTimeFormat(locale, {month: "short"});
10 | const month = f.format(date);
11 |
12 | const dateString = `${day}-${month}-${year} ${hour}:${minute}:${sec}`;
13 | return dateString;
14 | }
15 |
--------------------------------------------------------------------------------
/src/task2cmd/extension.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import { tasks } from 'vscode';
3 | import { Task2CmdProvider } from './task2cmd-prov';
4 | import { GetConfigHelperFromApi } from '../ext-api/ext-api';
5 |
6 | export async function activate(context: vscode.ExtensionContext) {
7 |
8 | const configApi = await GetConfigHelperFromApi();
9 | if (!configApi) {
10 | return;
11 | }
12 | const logFn = configApi.createLogFunction("VMS-IDE");
13 |
14 | const taskProvider = new Task2CmdProvider(logFn);
15 | let disposable = tasks.registerTaskProvider(Task2CmdProvider.taskType, taskProvider);
16 |
17 | context.subscriptions.push(disposable);
18 | context.subscriptions.push(taskProvider);
19 | }
20 |
21 | export function deactivate() {
22 | }
--------------------------------------------------------------------------------
/src/test/.gitignore:
--------------------------------------------------------------------------------
1 | list/*.*
--------------------------------------------------------------------------------
/src/test/a.a.test.ts:
--------------------------------------------------------------------------------
1 |
2 | import micromatch from 'micromatch'
3 |
4 | // mm(list, patterns[, options]);
5 |
6 | suite("MM tests", function(this: Mocha.Suite) {
7 |
8 | this.timeout(0);
9 |
10 | this.beforeAll(async () => {
11 | });
12 |
13 | return;
14 |
15 | /***************************************************************************************/
16 | /***************************************************************************************/
17 | /***************************************************************************************/
18 |
19 | test("MM 1", async() => {
20 | let options: micromatch.Options = {
21 | basename: false,
22 | dot: true,
23 | nocase: true,
24 | };
25 |
26 | let list = [
27 | '.vscode/a.js',
28 | '.vscode/test/null/b.js',
29 | 'any/.vscode/test/null/c.js',
30 | '.vscode/.test/null/d.js',
31 | '.vscode/test/.null/d.js',
32 | '.any/null/.vscode/test/d.js',
33 | 'any/.null/.vscode/test/d.js'
34 | ];
35 |
36 | let pattern = [
37 | '**/.vscode/**'
38 | ];
39 |
40 | while(pattern.length > 0) {
41 | const testOne = micromatch(list, pattern, options);
42 | options.dot = true;
43 | const testTwo = micromatch(list, pattern, options);
44 | options.dot = false;
45 | const testThree = micromatch(list, pattern, options);
46 |
47 | pattern = [];
48 |
49 | console.log(testOne);
50 | console.log(testTwo);
51 | console.log(testThree);
52 | }
53 | })
54 | });
--------------------------------------------------------------------------------
/src/test/cobol-unit.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from "assert";
2 | import * as vscode from "vscode";
3 | import { CobolAnalisisHelper } from "../vms_cobol/context/CobolAnalisisHelpers";
4 |
5 | suite("COBOL UNIT tests", function(this: Mocha.Suite) {
6 |
7 | this.timeout(0);
8 |
9 | this.beforeAll(async () => {
10 | });
11 |
12 | return;
13 |
14 | /***************************************************************************************/
15 | /***************************************************************************************/
16 | /***************************************************************************************/
17 |
18 | test("literal", async() => {
19 |
20 | assert.equal("", CobolAnalisisHelper.stringLiteralContent(""));
21 | assert.equal("abc", CobolAnalisisHelper.stringLiteralContent("abc"));
22 | assert.equal("nabc", CobolAnalisisHelper.stringLiteralContent("nabc"));
23 | assert.equal("Nabc", CobolAnalisisHelper.stringLiteralContent("Nabc"));
24 | assert.equal("abc", CobolAnalisisHelper.stringLiteralContent("\"abc\""));
25 | assert.equal("abc", CobolAnalisisHelper.stringLiteralContent("'abc'"));
26 | assert.equal("abc", CobolAnalisisHelper.stringLiteralContent("n'abc'"));
27 | assert.equal("abc", CobolAnalisisHelper.stringLiteralContent("N'abc'"));
28 | assert.equal("abc", CobolAnalisisHelper.stringLiteralContent("N\"abc\""));
29 | assert.equal("abc", CobolAnalisisHelper.stringLiteralContent("\"abc"));
30 | assert.equal("abc'", CobolAnalisisHelper.stringLiteralContent("\"abc'"));
31 | assert.equal("abc", CobolAnalisisHelper.stringLiteralContent("'abc"));
32 | assert.equal("abc\"", CobolAnalisisHelper.stringLiteralContent("N'abc\""));
33 | assert.equal("abc", CobolAnalisisHelper.stringLiteralContent("N\"abc"));
34 | assert.equal("abc'", CobolAnalisisHelper.stringLiteralContent("\"abc'"));
35 | assert.equal("abc", CobolAnalisisHelper.stringLiteralContent("n'abc"));
36 | assert.equal("abc\"", CobolAnalisisHelper.stringLiteralContent("n'abc\""));
37 | });
38 |
39 | });
40 |
--------------------------------------------------------------------------------
/src/test/long.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from "assert";
2 |
3 | suite("LONG tests", function(this: Mocha.Suite) {
4 |
5 | this.timeout(0);
6 |
7 | this.beforeAll(async () => {
8 |
9 | });
10 |
11 | return;
12 |
13 | /***************************************************************************************/
14 | /***************************************************************************************/
15 | /***************************************************************************************/
16 |
17 | test("long", async() => {
18 |
19 | console.log("start");
20 |
21 | let stop = false;
22 | let max = 1000000;
23 |
24 | let lognAsyncFnWithAwait = async () => {
25 | let count: number = 0;
26 | for(let i = 0; i < max && !stop; ++i) {
27 | await new Promise(resolve => {
28 | setImmediate(() => {
29 | resolve();
30 | })
31 | })
32 | ++count;
33 | }
34 | return count;
35 | }
36 |
37 | let result = lognAsyncFnWithAwait();
38 |
39 | //stop = true;
40 |
41 | let counter = await result;
42 |
43 | console.log('stop');
44 |
45 | });
46 |
47 | });
48 |
--------------------------------------------------------------------------------
/src/test/quotes.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from "assert";
2 | import { test_enclosing_quotes } from "../common/quotes";
3 |
4 | suite("Quotes tests", function(this: Mocha.Suite) {
5 |
6 | this.timeout(0);
7 |
8 | this.beforeAll(async () => {
9 | // prepare
10 | });
11 |
12 | test("Quotes test", async () => {
13 | let test_strs = [
14 | { str: '"abcd"', enclosed: true },
15 | { str: '"abcd', enclosed: false },
16 | { str: '"ab\\"cd', enclosed: false },
17 | { str: '"ab\\"cd"', enclosed: true },
18 | { str: '"ab\\"', enclosed: false },
19 | { str: '"ab\\\\"', enclosed: true },
20 | ];
21 | for(let test_str of test_strs) {
22 | assert.equal(test_enclosing_quotes(test_str.str).enclosed, test_str.enclosed, test_str.str);
23 | }
24 | });
25 |
26 | });
27 |
--------------------------------------------------------------------------------
/src/vms_basic/context/AnalysisListener.ts:
--------------------------------------------------------------------------------
1 | import * as nls from "vscode-nls";
2 |
3 | import { BasicParserListener } from '../parser/BasicParserListener';
4 | import { DiagnosticEntry, DiagnosticType } from './Facade';
5 | import { Token } from "antlr4ts";
6 | //import { TerminalNode } from "antlr4ts/tree";
7 | import {
8 | ProgramContext
9 | } from "../parser/BasicParser";
10 | import { ContextSymbolTable } from "./ContextSymbolTable";
11 | //import { BaseSymbol, ScopedSymbol } from "antlr4-c3";
12 |
13 | nls.config({messageFormat: nls.MessageFormat.both});
14 | //const localize = nls.loadMessageBundle();
15 |
16 | export class AnalysisListener implements BasicParserListener
17 | {
18 | constructor(public diagnostics: DiagnosticEntry[], public symbolTable: ContextSymbolTable)
19 | { }
20 |
21 | enterProgram(ctx: ProgramContext)
22 | {
23 | }
24 |
25 | /**
26 | * @returns true if doesn't exeed
27 | */
28 | public testLength(value: string, maxlength: number, message: string, token: Token, type = DiagnosticType.Error )
29 | {
30 | if (value.length > maxlength)
31 | {
32 | this.markToken(token, message, type);
33 | return false;
34 | }
35 |
36 | return true;
37 | }
38 |
39 | /**
40 | * @returns true if value is in range
41 | */
42 | public testRange(value: number, minvalue: number, maxvalue: number, message: string, token: Token, type = DiagnosticType.Error )
43 | {
44 | if (minvalue <= value && value <= maxvalue)
45 | {
46 | return true;
47 | }
48 |
49 | this.markToken(token, message, type);
50 | return false;
51 | }
52 |
53 | public markToken(token: Token, message: string, type = DiagnosticType.Error )
54 | {
55 | this.markText(message, token.charPositionInLine, token.line, (token.text? token.text.length : 0), type);
56 | }
57 |
58 | public markText(message: string, column: number, row: number, length: number, type = DiagnosticType.Error )
59 | {
60 | const error: DiagnosticEntry = {
61 | type,
62 | message,
63 | range:
64 | {
65 | start: { column, row },
66 | end: { column: column + length, row }
67 | }
68 | };
69 |
70 | this.diagnostics.push(error);
71 | }
72 | }
--------------------------------------------------------------------------------
/src/vms_basic/context/ContextErrorListener.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { ANTLRErrorListener, Recognizer, RecognitionException, Token, CommonToken } from 'antlr4ts';
4 | import { DiagnosticEntry, DiagnosticType } from './Facade';
5 |
6 |
7 | export class ContextLexerErrorListener implements ANTLRErrorListener
8 | {
9 | constructor(private errorList: DiagnosticEntry[])
10 | { }
11 |
12 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
13 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void
14 | {
15 | let error: DiagnosticEntry = {
16 | type: DiagnosticType.Error,
17 | message: msg,
18 | range: { start: { column: charPositionInLine, row: line }, end: { column: charPositionInLine + 1, row: line }}
19 | };
20 |
21 | this.errorList.push(error);
22 | }
23 | }
24 |
25 | export class ContextErrorListener implements ANTLRErrorListener
26 | {
27 | constructor(private errorList: DiagnosticEntry[])
28 | { }
29 |
30 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
31 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void
32 | {
33 | let error: DiagnosticEntry = {
34 | type: DiagnosticType.Error,
35 | message: msg,
36 | range: { start: { column: charPositionInLine, row: line }, end: { column: charPositionInLine + 1, row: line }}
37 | };
38 |
39 | if (offendingSymbol)
40 | {
41 | error.range.end.column = charPositionInLine + offendingSymbol.stopIndex - offendingSymbol.startIndex + 1;
42 | }
43 |
44 | this.errorList.push(error);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/vms_basic/providers/CompletionProvider.ts:
--------------------------------------------------------------------------------
1 |
2 | import { TextDocument, Position, CancellationToken, CompletionItem, ProviderResult, CompletionList } from 'vscode';
3 | import { Facade } from '../context/Facade';
4 | import { translateCompletionKind } from '../context/Symbol';
5 |
6 | // Determines the sort order in the completion list. One value for each SymbolKind.
7 | const sortKeys = [
8 | "99", // Other
9 | ];
10 |
11 | // Descriptions for each symbol kind.
12 | const details = [
13 | "Other",
14 | ];
15 |
16 | export class BasicCompletionItemProvider
17 | {
18 | constructor(private backend: Facade) { }
19 |
20 | public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): ProviderResult
21 | {
22 | let candidates = this.backend.getCodeCompletionCandidates(document.fileName, position.character, position.line + 1);
23 | let completionList: CompletionItem[] = [];
24 |
25 | candidates.forEach(info => {
26 | let item = new CompletionItem(info.name.toLowerCase(), translateCompletionKind(info.kind));
27 | item.sortText = sortKeys[info.kind] + info.name;
28 | item.detail = (info.description !== undefined) ? info.description : details[info.kind];
29 | completionList.push(item);
30 | });
31 |
32 | return new CompletionList(completionList, false);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/vms_basic/providers/DefinitionProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Location, Uri, ProviderResult, DefinitionProvider } from 'vscode';
2 | import { Facade } from '../context/Facade';
3 |
4 | export class BasicDefinitionProvider implements DefinitionProvider
5 | {
6 | constructor(private backend: Facade) { }
7 |
8 | public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): ProviderResult
9 | {
10 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character + 1, position.line + 1);
11 |
12 | if (!info)
13 | {
14 | return undefined;
15 | }
16 |
17 | if (info.definition)
18 | {
19 | let range = new Range(
20 | info.definition.range.start.row - 1, info.definition.range.start.column,
21 | info.definition.range.end.row - 1, info.definition.range.end.column
22 | );
23 | return new Location(Uri.file(info.source), range);
24 | }
25 | else
26 | {
27 | // Empty for built-in entities or self-define attempts.
28 | return new Location(document.uri, position);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/vms_basic/providers/HoverProvider.ts:
--------------------------------------------------------------------------------
1 | import { HoverProvider, TextDocument, Position, CancellationToken, Hover } from "vscode";
2 | import { Facade } from "../context/Facade";
3 | import { symbolDescriptionFromEnum } from '../context/Symbol';
4 | import { Basic } from '../extension';
5 | import * as path from 'path';
6 |
7 |
8 | export class BasicHoverProvider implements HoverProvider
9 | {
10 | constructor(private backend: Facade) { }
11 |
12 | public async provideHover(document: TextDocument, position: Position, token: CancellationToken)//: ProviderResult
13 | {
14 | let positionInfo = "";
15 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character + 1, position.line + 1);
16 |
17 | if (!info)
18 | {
19 | return undefined;
20 | }
21 |
22 | if(info.definition)
23 | {
24 | if (info.definition.range)
25 | {
26 | positionInfo += ` at ${info.definition.range.start.row}:${info.definition.range.start.column}`;
27 | }
28 | }
29 |
30 | const description = symbolDescriptionFromEnum(info.kind);
31 | return new Hover([
32 | "**" + description + "**\ndefined in: " + path.basename(info.source) + positionInfo,
33 | { language: Basic.language, value: (info.dataInfo? info.dataInfo : "") }
34 | ]);
35 | }
36 | }
--------------------------------------------------------------------------------
/src/vms_basic/providers/ReferenceProvider.ts:
--------------------------------------------------------------------------------
1 | import {
2 | CancellationToken,
3 | Location,
4 | Position,
5 | ProviderResult,
6 | Range,
7 | ReferenceContext,
8 | ReferenceProvider,
9 | TextDocument,
10 | Uri,
11 | } from 'vscode';
12 | import { Facade } from '../context/Facade';
13 |
14 | export class BasicReferenceProvider implements ReferenceProvider
15 | {
16 | constructor(private backend: Facade) { }
17 |
18 | public provideReferences(document: TextDocument, position: Position, context: ReferenceContext, token: CancellationToken): ProviderResult
19 | {
20 | const occurences = this.backend.getSymbolOccurences(document.fileName, position.character, position.line + 1);
21 | const result: Location[] = [];
22 |
23 | if (occurences.length > 0 )
24 | {
25 | for (let symbol of occurences)
26 | {
27 | if (symbol.definition)
28 | {
29 | let range = new Range(
30 | symbol.definition.range.start.row - 1, symbol.definition.range.start.column,
31 | symbol.definition.range.end.row - 1, symbol.definition.range.end.column
32 | );
33 |
34 | const loc: Location = {
35 | range,
36 | uri: Uri.file(symbol.source),
37 | };
38 |
39 | result.push(loc);
40 | }
41 | }
42 | }
43 |
44 | return result;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/vms_basic/providers/RenameProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Uri, ProviderResult, WorkspaceEdit, RenameProvider } from 'vscode';
2 | import { Facade } from '../context/Facade';
3 |
4 | export class BasicRenameProvider implements RenameProvider
5 | {
6 | constructor(private backend: Facade) { }
7 |
8 | public provideRenameEdits(document: TextDocument, position: Position, newName: string,
9 | token: CancellationToken): ProviderResult
10 | {
11 | const occurences = this.backend.getSymbolOccurences(document.fileName, position.character+1, position.line + 1);
12 |
13 | if (occurences.length)
14 | {
15 | const result = new WorkspaceEdit();
16 |
17 | for (let symbol of occurences)
18 | {
19 | if (symbol.definition)
20 | {
21 | let range = new Range(
22 | symbol.definition.range.start.row - 1, symbol.definition.range.start.column,
23 | symbol.definition.range.end.row - 1, symbol.definition.range.end.column
24 | );
25 |
26 | result.replace(Uri.file(symbol.source), range, newName);
27 | }
28 | }
29 |
30 | return result;
31 | }
32 |
33 | return undefined;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/vms_cobol/parser/cobolCopy.interp:
--------------------------------------------------------------------------------
1 | token literal names:
2 | null
3 | null
4 | null
5 | null
6 | null
7 | null
8 | null
9 | null
10 | null
11 | null
12 | null
13 | null
14 | null
15 | null
16 | ','
17 | ';'
18 | null
19 | null
20 | null
21 |
22 | token symbolic names:
23 | null
24 | PSEUDO_TEXT_
25 | STRING_LITERAL_
26 | COPY
27 | IN
28 | OF
29 | FROM
30 | DICTIONARY
31 | REPLACING
32 | BY
33 | DOT_
34 | NUMERIC_LITERAL_
35 | HEX_LITERAL_
36 | USER_DEFINED_WORD_
37 | COMMA_
38 | SEMI_
39 | WHITESPACE_
40 | NEWLINE_
41 | ANY_CHAR_
42 |
43 | rule names:
44 | copyStatement
45 | lastCopyStatement
46 | text_name
47 | library_name
48 | record_name
49 | repl_from
50 | repl_to
51 |
52 |
53 | atn:
54 | [3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 20, 61, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 3, 2, 7, 2, 18, 10, 2, 12, 2, 14, 2, 21, 11, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 30, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 36, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 3, 43, 10, 3, 13, 3, 14, 3, 44, 5, 3, 47, 10, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 19, 2, 2, 9, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 2, 5, 3, 2, 6, 7, 4, 2, 4, 4, 15, 15, 5, 2, 3, 4, 13, 13, 15, 15, 2, 58, 2, 19, 3, 2, 2, 2, 4, 25, 3, 2, 2, 2, 6, 50, 3, 2, 2, 2, 8, 52, 3, 2, 2, 2, 10, 54, 3, 2, 2, 2, 12, 56, 3, 2, 2, 2, 14, 58, 3, 2, 2, 2, 16, 18, 11, 2, 2, 2, 17, 16, 3, 2, 2, 2, 18, 21, 3, 2, 2, 2, 19, 20, 3, 2, 2, 2, 19, 17, 3, 2, 2, 2, 20, 22, 3, 2, 2, 2, 21, 19, 3, 2, 2, 2, 22, 23, 5, 4, 3, 2, 23, 24, 7, 2, 2, 3, 24, 3, 3, 2, 2, 2, 25, 35, 7, 5, 2, 2, 26, 29, 5, 6, 4, 2, 27, 28, 9, 2, 2, 2, 28, 30, 5, 8, 5, 2, 29, 27, 3, 2, 2, 2, 29, 30, 3, 2, 2, 2, 30, 36, 3, 2, 2, 2, 31, 32, 5, 10, 6, 2, 32, 33, 7, 8, 2, 2, 33, 34, 7, 9, 2, 2, 34, 36, 3, 2, 2, 2, 35, 26, 3, 2, 2, 2, 35, 31, 3, 2, 2, 2, 36, 46, 3, 2, 2, 2, 37, 42, 7, 10, 2, 2, 38, 39, 5, 12, 7, 2, 39, 40, 7, 11, 2, 2, 40, 41, 5, 14, 8, 2, 41, 43, 3, 2, 2, 2, 42, 38, 3, 2, 2, 2, 43, 44, 3, 2, 2, 2, 44, 42, 3, 2, 2, 2, 44, 45, 3, 2, 2, 2, 45, 47, 3, 2, 2, 2, 46, 37, 3, 2, 2, 2, 46, 47, 3, 2, 2, 2, 47, 48, 3, 2, 2, 2, 48, 49, 7, 12, 2, 2, 49, 5, 3, 2, 2, 2, 50, 51, 9, 3, 2, 2, 51, 7, 3, 2, 2, 2, 52, 53, 9, 3, 2, 2, 53, 9, 3, 2, 2, 2, 54, 55, 9, 3, 2, 2, 55, 11, 3, 2, 2, 2, 56, 57, 9, 4, 2, 2, 57, 13, 3, 2, 2, 2, 58, 59, 9, 4, 2, 2, 59, 15, 3, 2, 2, 2, 7, 19, 29, 35, 44, 46]
--------------------------------------------------------------------------------
/src/vms_cobol/parser/cobolCopy.tokens:
--------------------------------------------------------------------------------
1 | PSEUDO_TEXT_=1
2 | STRING_LITERAL_=2
3 | COPY=3
4 | IN=4
5 | OF=5
6 | FROM=6
7 | DICTIONARY=7
8 | REPLACING=8
9 | BY=9
10 | DOT_=10
11 | NUMERIC_LITERAL_=11
12 | HEX_LITERAL_=12
13 | USER_DEFINED_WORD_=13
14 | COMMA_=14
15 | SEMI_=15
16 | WHITESPACE_=16
17 | NEWLINE_=17
18 | ANY_CHAR_=18
19 | ','=14
20 | ';'=15
21 |
--------------------------------------------------------------------------------
/src/vms_cobol/parser/cobolCopyLexer.tokens:
--------------------------------------------------------------------------------
1 | PSEUDO_TEXT_=1
2 | STRING_LITERAL_=2
3 | COPY=3
4 | IN=4
5 | OF=5
6 | FROM=6
7 | DICTIONARY=7
8 | REPLACING=8
9 | BY=9
10 | DOT_=10
11 | NUMERIC_LITERAL_=11
12 | HEX_LITERAL_=12
13 | USER_DEFINED_WORD_=13
14 | COMMA_=14
15 | SEMI_=15
16 | WHITESPACE_=16
17 | NEWLINE_=17
18 | ANY_CHAR_=18
19 | ','=14
20 | ';'=15
21 |
--------------------------------------------------------------------------------
/src/vms_cobol/parser/cobolParserImpl.ts:
--------------------------------------------------------------------------------
1 | import { cobolParser } from "../parser/cobolParser";
2 | import { TaskDivider } from "../../common/task-divider";
3 | import { TokenStream } from "antlr4ts";
4 | import { testTokenInAreaB } from "../../common/parser/helpers";
5 |
6 | export class cobolParserImpl extends cobolParser {
7 |
8 | private thisTask: number;
9 |
10 | constructor(input: TokenStream, private taskDivider?: TaskDivider) {
11 | super(input);
12 | this.thisTask = taskDivider ? taskDivider.asyncValue : 0;
13 | }
14 |
15 | async cobol_source() {
16 | return super.cobol_source();
17 | }
18 |
19 | async exitRule() {
20 | if (this.thisTask != (this.taskDivider ? await this.taskDivider.testValue() : 0)) {
21 | throw "task has been re-entered";
22 | }
23 | return super.exitRule();
24 | }
25 |
26 | public testCurrentWordInAreaB() {
27 | return testTokenInAreaB(this.inputStream.LT(1));
28 | }
29 | }
--------------------------------------------------------------------------------
/src/vms_cobol/stream/CopyManagerImpl.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 | import * as fs from 'fs';
3 |
4 | import { ICopyManager } from "./cobolInputStream";
5 | import { VmsPathConverter } from "../../synchronizer/vms/vms-path-converter";
6 |
7 | export class CopyManagerImpl implements ICopyManager {
8 |
9 | /**
10 | * key is VMS path
11 | */
12 | private copyContents: Map = new Map();
13 | private copySource: Map = new Map();
14 |
15 | constructor(private root: string) {
16 |
17 | }
18 |
19 | getRoot() {
20 | return this.root;
21 | }
22 |
23 | public clear(fileName?: string): boolean {
24 | if (fileName) {
25 | for (let [name, file] of this.copySource) {
26 | if (file === fileName) {
27 | this.copyContents.delete(name);
28 | this.copySource.delete(name);
29 | return true;
30 | }
31 | }
32 | return false;
33 | }
34 | this.copyContents.clear();
35 | this.copySource.clear();
36 | return true;
37 | }
38 |
39 | getSourcePath(name: string): string | undefined {
40 | return this.copySource.get(name);
41 | }
42 |
43 | getLines(name: string): string[] {
44 | let lines: string[] | undefined = this.copyContents.get(name);
45 | if (!lines) {
46 | try {
47 | let converter = VmsPathConverter.fromVms(name);
48 | let filePath = path.join(this.root, converter.initial);
49 | if (!converter.fileExt) {
50 | filePath += ".lib";
51 | }
52 | let buffer = fs.readFileSync(filePath);
53 | let content = buffer.toString("utf8");
54 | lines = content.split(/\r?\n/g);
55 | this.copyContents.set(name, lines);
56 | this.copySource.set(name, filePath);
57 | } catch(e) {
58 | lines = undefined;
59 | }
60 | }
61 | if (lines) {
62 | return [...lines];
63 | }
64 | return [];
65 | }
66 |
67 | }
--------------------------------------------------------------------------------
/src/vms_cobol/stream/CopyManagers.ts:
--------------------------------------------------------------------------------
1 | import { ICopyManager } from "./cobolInputStream";
2 | import { CopyManagerImpl } from "./CopyManagerImpl";
3 |
4 | const _copyManagers = new Map();
5 |
6 | export function GetCopyManager(scopeName: string, scopePath?: string): ICopyManager | undefined {
7 | let copyManager = _copyManagers.get(scopeName);
8 | if (!copyManager && scopePath) {
9 | copyManager = new CopyManagerImpl(scopePath);
10 | _copyManagers.set(scopeName, copyManager);
11 | }
12 | return copyManager;
13 | }
--------------------------------------------------------------------------------
/src/vms_debug/parsers/debug_variable_info.ts:
--------------------------------------------------------------------------------
1 | export enum ReflectKind
2 | {
3 | Value = -1,
4 | Invalid = 0,
5 | Atomic,
6 | Block,
7 | Array,
8 | Class,
9 | Func,
10 | Map,
11 | Pointer,
12 | String,
13 | Struct
14 | }
15 |
16 | export interface DebugVariable
17 | {
18 | name: string;
19 | nameFull: string;
20 | addr: string;
21 | type: string;
22 | kind: ReflectKind;
23 | value: string;
24 | info: string;
25 | prefix: string;
26 | len: number;
27 | children: DebugVariable[];
28 | unreadable: string;
29 | fullyQualifiedName: string;
30 | }
31 |
32 | export interface VariableFileInfo
33 | {
34 | filePath: string;
35 | moduleName: string;
36 | wrapName: string;//wrap function name
37 | functionName: string;//if "" => global variable
38 | variableName: string;
39 | variableNameFull: string;
40 | variableType: string;
41 | variableValue: string;
42 | variableInfo: string;
43 | variablePrefix: string;
44 | variableAddress: string;
45 | variableKind: ReflectKind;
46 | }
47 |
48 | export class HolderDebugVariableInfo
49 | {
50 | private variables = new Map();
51 |
52 |
53 | public getSize() : number
54 | {
55 | return this.variables.size;
56 | }
57 |
58 | public getVariableFile(pathName : string) : VariableFileInfo[] | undefined
59 | {
60 | return this.variables.get(pathName);
61 | }
62 |
63 | public setVariableFile(pathName : string, vars: VariableFileInfo[]) : void
64 | {
65 | this.variables.set(pathName, vars);
66 | }
67 | }
--------------------------------------------------------------------------------
/src/vms_debug/queue/queues.ts:
--------------------------------------------------------------------------------
1 | export class Queue
2 | {
3 | private data : any[] = [];
4 |
5 | push = (item: T) => this.data.push(item);
6 | pop = (): T => this.data.shift();
7 | size = () : number => this.data.length;
8 | getv = (): T | undefined =>
9 | {
10 | if(this.data.length > 0)
11 | {
12 | return this.data[0];
13 | }
14 |
15 | return undefined;
16 | }
17 | }
--------------------------------------------------------------------------------
/src/vms_debug/ui/status_bar.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode';
2 | import { StatusBarItem, StatusBarAlignment } from "vscode";
3 |
4 |
5 | export class StatusBarDebug
6 | {
7 | private barMessage: StatusBarItem = vscode.window.createStatusBarItem(StatusBarAlignment.Left);
8 |
9 |
10 | public setMessage(message : string)
11 | {
12 | this.barMessage.text = `$(bug) ${message}`;
13 | this.barMessage.show();
14 | }
15 |
16 | public hideMessage()
17 | {
18 | this.barMessage.hide();
19 | }
20 |
21 | dispose()
22 | {
23 | this.barMessage.dispose();
24 | }
25 | }
--------------------------------------------------------------------------------
/src/vms_fortran/context/ContextErrorListener.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { ANTLRErrorListener, Recognizer, RecognitionException, Token, CommonToken } from 'antlr4ts';
4 | import { DiagnosticEntry, DiagnosticType } from './Facade';
5 |
6 |
7 | export class ContextLexerErrorListener implements ANTLRErrorListener
8 | {
9 | constructor(private errorList: DiagnosticEntry[])
10 | { }
11 |
12 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
13 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void
14 | {
15 | let error: DiagnosticEntry = {
16 | type: DiagnosticType.Error,
17 | message: msg,
18 | range: { start: { column: charPositionInLine, row: line }, end: { column: charPositionInLine + 1, row: line }}
19 | };
20 |
21 | this.errorList.push(error);
22 | }
23 | }
24 |
25 | export class ContextErrorListener implements ANTLRErrorListener
26 | {
27 | constructor(private errorList: DiagnosticEntry[])
28 | { }
29 |
30 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
31 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void
32 | {
33 | let error: DiagnosticEntry = {
34 | type: DiagnosticType.Error,
35 | message: msg,
36 | range: { start: { column: charPositionInLine, row: line }, end: { column: charPositionInLine + 1, row: line }}
37 | };
38 |
39 | if (offendingSymbol)
40 | {
41 | error.range.end.column = charPositionInLine + offendingSymbol.stopIndex - offendingSymbol.startIndex + 1;
42 | }
43 |
44 | this.errorList.push(error);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/vms_fortran/providers/CompletionProvider.ts:
--------------------------------------------------------------------------------
1 |
2 | import { TextDocument, Position, CancellationToken, CompletionItem, ProviderResult, CompletionList } from 'vscode';
3 | import { Facade } from '../context/Facade';
4 | import { translateCompletionKind } from '../context/Symbol';
5 |
6 | // Determines the sort order in the completion list. One value for each SymbolKind.
7 | const sortKeys = [
8 | "99", // Other
9 | ];
10 |
11 | // Descriptions for each symbol kind.
12 | const details = [
13 | "Other",
14 | ];
15 |
16 | export class FortranCompletionItemProvider
17 | {
18 | constructor(private backend: Facade) { }
19 |
20 | public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): ProviderResult
21 | {
22 | let candidates = this.backend.getCodeCompletionCandidates(document.fileName, position.character, position.line + 1);
23 | let completionList: CompletionItem[] = [];
24 |
25 | candidates.forEach(info => {
26 | let item = new CompletionItem(info.name.toLowerCase(), translateCompletionKind(info.kind));
27 | item.sortText = sortKeys[info.kind] + info.name;
28 | item.detail = (info.description !== undefined) ? info.description : details[info.kind];
29 | completionList.push(item);
30 | });
31 |
32 | return new CompletionList(completionList, false);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/vms_fortran/providers/DefinitionProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Location, Uri, ProviderResult, DefinitionProvider } from 'vscode';
2 | import { Facade } from '../context/Facade';
3 |
4 | export class FortranDefinitionProvider implements DefinitionProvider
5 | {
6 | constructor(private backend: Facade) { }
7 |
8 | public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): ProviderResult
9 | {
10 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character + 1, position.line + 1);
11 |
12 | if (!info)
13 | {
14 | return undefined;
15 | }
16 |
17 | if (info.definition)
18 | {
19 | let range = new Range(
20 | info.definition.range.start.row - 1, info.definition.range.start.column,
21 | info.definition.range.end.row - 1, info.definition.range.end.column
22 | );
23 | return new Location(Uri.file(info.source), range);
24 | }
25 | else
26 | {
27 | // Empty for built-in entities or self-define attempts.
28 | return new Location(document.uri, position);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/vms_fortran/providers/ReferenceProvider.ts:
--------------------------------------------------------------------------------
1 | import {
2 | CancellationToken,
3 | Location,
4 | Position,
5 | ProviderResult,
6 | Range,
7 | ReferenceContext,
8 | ReferenceProvider,
9 | TextDocument,
10 | Uri,
11 | } from 'vscode';
12 | import { Facade } from '../context/Facade';
13 |
14 | export class FortranReferenceProvider implements ReferenceProvider
15 | {
16 | constructor(private backend: Facade) { }
17 |
18 | public provideReferences(document: TextDocument, position: Position, context: ReferenceContext, token: CancellationToken): ProviderResult
19 | {
20 | const occurences = this.backend.getSymbolOccurences(document.fileName, position.character, position.line + 1);
21 | const result: Location[] = [];
22 |
23 | if (occurences.length > 0 )
24 | {
25 | for (let symbol of occurences)
26 | {
27 | if (symbol.definition)
28 | {
29 | let range = new Range(
30 | symbol.definition.range.start.row - 1, symbol.definition.range.start.column,
31 | symbol.definition.range.end.row - 1, symbol.definition.range.end.column
32 | );
33 |
34 | const loc: Location = {
35 | range,
36 | uri: Uri.file(symbol.source),
37 | };
38 |
39 | result.push(loc);
40 | }
41 | }
42 | }
43 |
44 | return result;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/vms_fortran/providers/RenameProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Uri, ProviderResult, WorkspaceEdit, RenameProvider } from 'vscode';
2 | import { Facade } from '../context/Facade';
3 |
4 | export class FortranRenameProvider implements RenameProvider
5 | {
6 | constructor(private backend: Facade) { }
7 |
8 | public provideRenameEdits(document: TextDocument, position: Position, newName: string,
9 | token: CancellationToken): ProviderResult
10 | {
11 | const occurences = this.backend.getSymbolOccurences(document.fileName, position.character+1, position.line + 1);
12 |
13 | if (occurences.length)
14 | {
15 | const result = new WorkspaceEdit();
16 |
17 | for (let symbol of occurences)
18 | {
19 | if (symbol.definition)
20 | {
21 | let range = new Range(
22 | symbol.definition.range.start.row - 1, symbol.definition.range.start.column,
23 | symbol.definition.range.end.row - 1, symbol.definition.range.end.column
24 | );
25 |
26 | result.replace(Uri.file(symbol.source), range, newName);
27 | }
28 | }
29 |
30 | return result;
31 | }
32 |
33 | return undefined;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/vms_jvm_debug/drop.ts:
--------------------------------------------------------------------------------
1 | import { IDropCommand } from "./communication";
2 |
3 | export class DropCommand implements IDropCommand {
4 |
5 | private _callback?: (reason?: any) => void;
6 |
7 | public onDropCommand(callback: (reason: any) => void): void {
8 | this._callback = callback;
9 | }
10 |
11 | public doDropCommand(reason?: any) {
12 | if (this._callback) {
13 | this._callback(reason);
14 | }
15 | }
16 |
17 | }
--------------------------------------------------------------------------------
/src/vms_jvm_debug/jvm-config.ts:
--------------------------------------------------------------------------------
1 |
2 | import { DebugProtocol } from "@vscode/debugprotocol";
3 | import { DebugConfiguration } from "vscode";
4 |
5 | /**
6 | * This interface describes the vms_jvm_debugger specific launch attributes
7 | * (which are not part of the Debug Adapter Protocol).
8 | * The schema for these attributes lives in the package.json of the mock-debug extension.
9 | * The interface should always match this schema.
10 | */
11 | export interface IJvmLaunchRequestArguments extends DebugProtocol.LaunchRequestArguments {
12 | /** a class to execute. */
13 | class: string;
14 | /** a ':' separated list of directories, JAR archives, and ZIP archives to search for class files. */
15 | classpath: string;
16 | /** a port to debug. */
17 | port?: string;
18 | /** command line arguments */
19 | arguments?: string;
20 | /** automatically stop target after launch. If not specified, target does not stop. */
21 | stopOnEntry?: boolean;
22 | /** enable logging the Debug Adapter Protocol */
23 | trace?: boolean;
24 | /** current scope */
25 | scope?: string;
26 | }
27 |
28 | export interface IJvmDebugConfiguration extends DebugConfiguration {
29 | /** a class to execute. */
30 | class: string;
31 | /** a ':' separated list of directories, JAR archives, and ZIP archives to search for class files. */
32 | classpath: string;
33 | /** a port to debug. */
34 | port?: string;
35 | /** command line arguments */
36 | arguments?: string;
37 | /** automatically stop target after launch. If not specified, target does not stop. */
38 | stopOnEntry?: boolean;
39 | /** enable logging the Debug Adapter Protocol */
40 | trace?: boolean;
41 | }
42 |
43 | export function isJvmDebugConfiguration(candidate: any): candidate is IJvmDebugConfiguration {
44 | return !!candidate &&
45 | typeof candidate.type === "string" &&
46 | typeof candidate.name === "string" &&
47 | typeof candidate.request === "string" &&
48 | typeof candidate.class === "string" &&
49 | typeof candidate.classpath === "string";
50 | }
--------------------------------------------------------------------------------
/src/vms_jvm_debug/jvm-state-machine.ts:
--------------------------------------------------------------------------------
1 |
2 | export enum JvmState {
3 | anyState,
4 | initial,
5 | askAttach,
6 | paused,
7 | askSetBreak,
8 | askClearBreak,
9 | askRun,
10 | askThreads,
11 | askLocals,
12 | askStack,
13 | askStep,
14 | askStop,
15 | running,
16 | waitThreadPrompt,
17 | };
18 |
19 | export enum JvmAction {
20 | attach,
21 | setBreak,
22 | clearBreak,
23 | run,
24 | threads,
25 | locals,
26 | stack,
27 | step,
28 | stop,
29 | };
30 |
31 | export interface IJvmMove {
32 | from: JvmState;
33 | to: JvmState;
34 | reason: JvmAction | RegExp;
35 | emits?: string[];
36 | }
37 |
38 | const JvmMoves: IJvmMove[] = [
39 | { from: JvmState.initial,
40 | to: JvmState.askAttach,
41 | reason: JvmAction.attach,
42 | },
43 | { from: JvmState.askAttach,
44 | to: JvmState.initial,
45 | reason: /Unable to attach to target VM./,
46 | },
47 | { from: JvmState.askAttach,
48 | to: JvmState.paused,
49 | reason: /main\[1\]/,
50 | },
51 | { from: JvmState.anyState,
52 | to: JvmState.askSetBreak,
53 | reason: JvmAction.setBreak,
54 | },
55 | { from: JvmState.paused,
56 | to: JvmState.askClearBreak,
57 | reason: JvmAction.clearBreak,
58 | },
59 | { from: JvmState.paused,
60 | to: JvmState.askRun,
61 | reason: JvmAction.run,
62 | },
63 | { from: JvmState.paused,
64 | to: JvmState.askThreads,
65 | reason: JvmAction.threads,
66 | },
67 | { from: JvmState.paused,
68 | to: JvmState.askLocals,
69 | reason: JvmAction.locals,
70 | },
71 | { from: JvmState.paused,
72 | to: JvmState.askStack,
73 | reason: JvmAction.stack,
74 | },
75 | { from: JvmState.paused,
76 | to: JvmState.askStep,
77 | reason: JvmAction.step,
78 | },
79 | { from: JvmState.paused,
80 | to: JvmState.askStop,
81 | reason: JvmAction.stop,
82 | },
83 | { from: JvmState.askSetBreak,
84 | to: JvmState.askStop,
85 | reason: JvmAction.stop,
86 | },
87 | ];
88 |
89 | export class JvmStateMachine {
90 |
91 |
92 |
93 | }
--------------------------------------------------------------------------------
/src/vms_jvm_debug/shell-splitter.ts:
--------------------------------------------------------------------------------
1 | import { Transform } from "stream";
2 | import { EventEmitter } from "events";
3 | import { ICmdClient } from "./communication";
4 | import { LogFunction, LogType } from "../common/main";
5 |
6 | //const _rgxNL = /(?:\r)?\n/g;
7 | const _rgxNL = /\n/g;
8 |
9 | export class ShellSplitter extends Transform {
10 |
11 | public _lastError: string | undefined;
12 |
13 | constructor(private _client: ICmdClient, private _timeout = 100, private logFn?: LogFunction) {
14 | super();
15 |
16 | this.on('close', () => {
17 | this._client.lineReceived(undefined);
18 | });
19 |
20 | this.on('error', (err) => {
21 | this._lastError = String(err);
22 | this._client.lineReceived(undefined);
23 | });
24 |
25 | this._client.onCommand((line: string) => {
26 | this.push(line.trim() + '\r');
27 | })
28 |
29 | this._client.onData((data: string) => {
30 | this.push(data);
31 | })
32 | }
33 |
34 | private _buffer = "";
35 | public _transform(chunk: any, encoding: string, callback: Function) {
36 | let content = "";
37 | if (Buffer.isBuffer(chunk)) {
38 | content = chunk.toString("utf8");
39 | } else if (typeof chunk === "string") {
40 | content = chunk;
41 | }
42 | if (this.logFn) {
43 | this.logFn(LogType.debug, () => '===' + content);
44 | }
45 | this._buffer += content;
46 | let matchNL = _rgxNL.exec(this._buffer);
47 | let start = 0;
48 | while (matchNL) {
49 | this.sendLine(this._buffer.slice(start, _rgxNL.lastIndex)); // `- matchNL[0].length` is removed, let client know about new line
50 | start = _rgxNL.lastIndex;
51 | matchNL = _rgxNL.exec(this._buffer);
52 | }
53 | this._buffer = this._buffer.slice(start);
54 | // for a prompt we will never receive new line, so wait a timeout and send buffer to the client
55 | setTimeout(() => {
56 | if (this._buffer) {
57 | this.sendLine(this._buffer);
58 | this._buffer = "";
59 | }
60 | }, this._timeout);
61 | callback();
62 | }
63 |
64 | private sendLine(line: string) {
65 | setImmediate(() => {
66 | this._client.lineReceived(line);
67 | });
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/vms_jvm_debug/simple-cmd-client.ts:
--------------------------------------------------------------------------------
1 | import { ICmdClient } from "./communication";
2 | import { EventEmitter } from "vscode";
3 |
4 | export class SimpleCmdClient implements ICmdClient {
5 |
6 | constructor(private emitter: EventEmitter) {
7 | ;
8 | }
9 |
10 | onCommand(cmdListener: (line: string) => void): { dispose: () => void; } {
11 | // no commands allowed
12 | return {
13 | dispose: () => {
14 | return;
15 | }
16 | };
17 | }
18 |
19 | onData(dataListener: (line: string) => void): { dispose: () => void; } {
20 | // no data allowed
21 | return {
22 | dispose: () => {
23 | return;
24 | }
25 | };
26 | }
27 |
28 | lineReceived(line: string | undefined): boolean {
29 | this.emitter.fire(line);
30 | return true;
31 | }
32 | }
--------------------------------------------------------------------------------
/src/vms_pascal/context/AnalysisListener.ts:
--------------------------------------------------------------------------------
1 | import * as nls from "vscode-nls";
2 |
3 | import { pascalListener } from '../parser/pascalListener';
4 | import { DiagnosticEntry, DiagnosticType } from './Facade';
5 | import { Token } from "antlr4ts";
6 | //import { TerminalNode } from "antlr4ts/tree";
7 | import {
8 | ProgramContext,
9 | IdentifierListContext,
10 | } from "../parser/pascalParser";
11 | import { ContextSymbolTable } from "./ContextSymbolTable";
12 | //import { BaseSymbol, ScopedSymbol } from "antlr4-c3";
13 |
14 | nls.config({messageFormat: nls.MessageFormat.both});
15 | //const localize = nls.loadMessageBundle();
16 |
17 | export class AnalysisListener implements pascalListener
18 | {
19 | constructor(public diagnostics: DiagnosticEntry[], public symbolTable: ContextSymbolTable)
20 | { }
21 |
22 | enterProgram(ctx: ProgramContext)
23 | {
24 | }
25 |
26 | exitIdentifierList(ctx: IdentifierListContext)
27 | {
28 | }
29 |
30 | /**
31 | * @returns true if doesn't exeed
32 | */
33 | public testLength(value: string, maxlength: number, message: string, token: Token, type = DiagnosticType.Error )
34 | {
35 | if (value.length > maxlength)
36 | {
37 | this.markToken(token, message, type);
38 | return false;
39 | }
40 |
41 | return true;
42 | }
43 |
44 | /**
45 | * @returns true if value is in range
46 | */
47 | public testRange(value: number, minvalue: number, maxvalue: number, message: string, token: Token, type = DiagnosticType.Error )
48 | {
49 | if (minvalue <= value && value <= maxvalue)
50 | {
51 | return true;
52 | }
53 |
54 | this.markToken(token, message, type);
55 | return false;
56 | }
57 |
58 | public markToken(token: Token, message: string, type = DiagnosticType.Error )
59 | {
60 | this.markText(message, token.charPositionInLine, token.line, (token.text? token.text.length : 0), type);
61 | }
62 |
63 | public markText(message: string, column: number, row: number, length: number, type = DiagnosticType.Error )
64 | {
65 | const error: DiagnosticEntry = {
66 | type,
67 | message,
68 | range:
69 | {
70 | start: { column, row },
71 | end: { column: column + length, row }
72 | }
73 | };
74 |
75 | this.diagnostics.push(error);
76 | }
77 | }
--------------------------------------------------------------------------------
/src/vms_pascal/context/ContextErrorListener.ts:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { ANTLRErrorListener, Recognizer, RecognitionException, Token, CommonToken } from 'antlr4ts';
4 | import { DiagnosticEntry, DiagnosticType } from './Facade';
5 |
6 |
7 | export class ContextLexerErrorListener implements ANTLRErrorListener
8 | {
9 | constructor(private errorList: DiagnosticEntry[])
10 | { }
11 |
12 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
13 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void
14 | {
15 | let error: DiagnosticEntry = {
16 | type: DiagnosticType.Error,
17 | message: msg,
18 | range: { start: { column: charPositionInLine, row: line }, end: { column: charPositionInLine + 1, row: line }}
19 | };
20 |
21 | this.errorList.push(error);
22 | }
23 | }
24 |
25 | export class ContextErrorListener implements ANTLRErrorListener
26 | {
27 | constructor(private errorList: DiagnosticEntry[])
28 | { }
29 |
30 | syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number,
31 | charPositionInLine: number, msg: string, e: RecognitionException | undefined): void
32 | {
33 | let error: DiagnosticEntry = {
34 | type: DiagnosticType.Error,
35 | message: msg,
36 | range: { start: { column: charPositionInLine, row: line }, end: { column: charPositionInLine + 1, row: line }}
37 | };
38 |
39 | if (offendingSymbol)
40 | {
41 | error.range.end.column = charPositionInLine + offendingSymbol.stopIndex - offendingSymbol.startIndex + 1;
42 | }
43 |
44 | this.errorList.push(error);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/vms_pascal/providers/CompletionProvider.ts:
--------------------------------------------------------------------------------
1 |
2 | import { TextDocument, Position, CancellationToken, CompletionItem, ProviderResult, CompletionList } from 'vscode';
3 | import { Facade } from '../context/Facade';
4 | import { translateCompletionKind } from '../context/Symbol';
5 |
6 | // Determines the sort order in the completion list. One value for each SymbolKind.
7 | const sortKeys = [
8 | "99", // Other
9 | ];
10 |
11 | // Descriptions for each symbol kind.
12 | const details = [
13 | "Other",
14 | ];
15 |
16 | export class PascalCompletionItemProvider
17 | {
18 | constructor(private backend: Facade) { }
19 |
20 | public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): ProviderResult
21 | {
22 | let candidates = this.backend.getCodeCompletionCandidates(document.fileName, position.character, position.line + 1);
23 | let completionList: CompletionItem[] = [];
24 |
25 | candidates.forEach(info => {
26 | let item = new CompletionItem(info.name.toLowerCase(), translateCompletionKind(info.kind));
27 | item.sortText = sortKeys[info.kind] + info.name;
28 | item.detail = (info.description !== undefined) ? info.description : details[info.kind];
29 | completionList.push(item);
30 | });
31 |
32 | return new CompletionList(completionList, false);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/vms_pascal/providers/DefinitionProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Location, Uri, ProviderResult, DefinitionProvider } from 'vscode';
2 | import { Facade } from '../context/Facade';
3 |
4 | export class PascalDefinitionProvider implements DefinitionProvider
5 | {
6 | constructor(private backend: Facade) { }
7 |
8 | public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): ProviderResult
9 | {
10 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character + 1, position.line + 1);
11 |
12 | if (!info)
13 | {
14 | return undefined;
15 | }
16 |
17 | if (info.definition)
18 | {
19 | let range = new Range(
20 | info.definition.range.start.row - 1, info.definition.range.start.column,
21 | info.definition.range.end.row - 1, info.definition.range.end.column
22 | );
23 | return new Location(Uri.file(info.source), range);
24 | }
25 | else
26 | {
27 | // Empty for built-in entities or self-define attempts.
28 | return new Location(document.uri, position);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/vms_pascal/providers/HoverProvider.ts:
--------------------------------------------------------------------------------
1 | import { HoverProvider, TextDocument, Position, CancellationToken, Hover, Range, Uri, workspace } from "vscode";
2 | import { SymbolKind, Facade } from "../context/Facade";
3 | import { symbolDescriptionFromEnum } from '../context/Symbol';
4 | import { Pascal } from '../extension';
5 | import * as path from 'path';
6 |
7 |
8 | export class PascalHoverProvider implements HoverProvider
9 | {
10 | constructor(private backend: Facade) { }
11 |
12 | public async provideHover(document: TextDocument, position: Position, token: CancellationToken)//: ProviderResult
13 | {
14 | let positionInfo = "";
15 | let info = this.backend.symbolInfoAtPosition(document.fileName, position.character + 1, position.line + 1);
16 |
17 | if (!info)
18 | {
19 | return undefined;
20 | }
21 |
22 | if(info.definition)
23 | {
24 | if (info.definition.range)
25 | {
26 | positionInfo += ` at ${info.definition.range.start.row}:${info.definition.range.start.column}`;
27 | }
28 | }
29 |
30 | const description = symbolDescriptionFromEnum(info.kind);
31 | return new Hover([
32 | "**" + description + "**\ndefined in: " + path.basename(info.source) + positionInfo,
33 | { language: Pascal.language, value: (info.dataInfo? info.dataInfo : "") }
34 | ]);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/vms_pascal/providers/ReferenceProvider.ts:
--------------------------------------------------------------------------------
1 | import {
2 | CancellationToken,
3 | Location,
4 | Position,
5 | ProviderResult,
6 | Range,
7 | ReferenceContext,
8 | ReferenceProvider,
9 | TextDocument,
10 | Uri,
11 | } from 'vscode';
12 | import { Facade } from '../context/Facade';
13 |
14 | export class PascalReferenceProvider implements ReferenceProvider
15 | {
16 | constructor(private backend: Facade) { }
17 |
18 | public provideReferences(document: TextDocument, position: Position, context: ReferenceContext, token: CancellationToken): ProviderResult
19 | {
20 | const occurences = this.backend.getSymbolOccurences(document.fileName, position.character, position.line + 1);
21 | const result: Location[] = [];
22 |
23 | if (occurences.length > 0 )
24 | {
25 | for (let symbol of occurences)
26 | {
27 | if (symbol.definition)
28 | {
29 | let range = new Range(
30 | symbol.definition.range.start.row - 1, symbol.definition.range.start.column,
31 | symbol.definition.range.end.row - 1, symbol.definition.range.end.column
32 | );
33 |
34 | const loc: Location = {
35 | range,
36 | uri: Uri.file(symbol.source),
37 | };
38 |
39 | result.push(loc);
40 | }
41 | }
42 | }
43 |
44 | return result;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/vms_pascal/providers/RenameProvider.ts:
--------------------------------------------------------------------------------
1 | import { TextDocument, Position, CancellationToken, Range, Uri, ProviderResult, WorkspaceEdit, RenameProvider } from 'vscode';
2 | import { Facade } from '../context/Facade';
3 |
4 | export class PascalRenameProvider implements RenameProvider
5 | {
6 | constructor(private backend: Facade) { }
7 |
8 | public provideRenameEdits(document: TextDocument, position: Position, newName: string,
9 | token: CancellationToken): ProviderResult
10 | {
11 | const occurences = this.backend.getSymbolOccurences(document.fileName, position.character, position.line + 1);
12 |
13 | if (occurences.length)
14 | {
15 | const result = new WorkspaceEdit();
16 |
17 | for (let symbol of occurences)
18 | {
19 | if (symbol.definition)
20 | {
21 | let range = new Range(
22 | symbol.definition.range.start.row - 1, symbol.definition.range.start.column,
23 | symbol.definition.range.end.row - 1, symbol.definition.range.end.column
24 | );
25 |
26 | result.replace(Uri.file(symbol.source), range, newName);
27 | }
28 | }
29 |
30 | return result;
31 | }
32 |
33 | return undefined;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/zip/extension.ts:
--------------------------------------------------------------------------------
1 |
2 | import * as vscode from 'vscode';
3 | import { ZipApi } from './zip-api';
4 |
5 | export async function activate(context: vscode.ExtensionContext) {
6 |
7 | return ZipApi;
8 | }
9 |
10 | export function deactivate() {
11 | // do nothing
12 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "paths": { "*": ["types/*"] },
4 | /* Basic Options */
5 | "target": "es2018",
6 | "module": "commonjs",
7 | "lib": [ "es2018" ],
8 | "declaration": true,
9 | "sourceMap": true,
10 | "outDir": "./out",
11 | "rootDir": "./src",
12 | "strict": true,
13 | "esModuleInterop": true,
14 | "baseUrl": "./src"
15 | },
16 | "exclude": [
17 | "node_modules",
18 | ".vscode-test",
19 | "out"
20 | ]
21 | }
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "max-line-length": false,
4 | "no-unused-expression": true,
5 | "no-duplicate-variable": true,
6 | "curly": true,
7 | "class-name": false,
8 | "semicolon": [ true ],
9 | "triple-equals": true,
10 | "no-var-keyword": true,
11 | "no-bitwise": false
12 | }
13 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | //@ts-check
2 |
3 | 'use strict';
4 |
5 | const path = require('path');
6 |
7 | /**@type {import('webpack').Configuration}*/
8 | const config = {
9 | target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
10 | context: path.resolve(__dirname, 'out'),
11 | node: {
12 | __filename: true, //return relative path of original file
13 | __dirname: false, //returns full path of output file
14 | },
15 | entry: './extension.js', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
16 | output: {
17 | // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
18 | path: path.resolve(__dirname, 'out'),
19 | filename: 'index.js',
20 | libraryTarget: 'commonjs2',
21 | devtoolModuleFilenameTemplate: '../[resource-path]'
22 | },
23 | devtool: 'source-map',
24 | externals: {
25 | vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
26 | },
27 | resolve: {
28 | // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
29 | extensions: ['.ts', '.js']
30 | },
31 | module: {
32 | rules: [
33 | {
34 | test: /\.ts$/,
35 | exclude: /node_modules|test/,
36 | use: [
37 | {
38 | loader: 'ts-loader'
39 | }
40 | ]
41 | },
42 | {
43 | test: /\.node$/,
44 | use: 'raw-loader'
45 | }
46 | ]
47 | }
48 | };
49 | module.exports = config;
50 |
--------------------------------------------------------------------------------