├── .editorconfig ├── .eslintrc.js ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ ├── feature-request.yml │ └── other.yml └── workflows │ ├── build-and-package.yml │ └── publish.yml ├── .gitignore ├── .husky ├── .gitignore └── pre-commit ├── .markdownlint.json ├── .prettierignore ├── .prettierrc.json ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── BUILD.md ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── compile-antlr.ps1 ├── compile-antlr.sh ├── language-configuration.json ├── package-lock.json ├── package.json ├── res ├── bin │ ├── glslangValidatorLinux │ ├── glslangValidatorMac │ └── glslangValidatorWindows.exe ├── gif │ ├── call-hierarchy.gif │ ├── code-completion.gif │ ├── color-picker.gif │ ├── declarations.gif │ ├── definitions.gif │ ├── diagnostic.gif │ ├── documentation.gif │ ├── folding.gif │ ├── formatting.gif │ ├── generate-preprocessed-glsl.gif │ ├── highlights.gif │ ├── hover.gif │ ├── implementations.gif │ ├── references.gif │ ├── rename.gif │ ├── signature-help.gif │ ├── symbols.gif │ └── type-definitions.gif ├── js │ ├── mml-chtml.js │ └── output │ │ └── chtml │ │ └── fonts │ │ └── woff-v2 │ │ ├── MathJax_Main-Regular.woff │ │ ├── MathJax_Math-Italic.woff │ │ ├── MathJax_Size1-Regular.woff │ │ ├── MathJax_Size4-Regular.woff │ │ └── MathJax_Zero.woff ├── png │ ├── icon.png │ └── screenshots │ │ ├── code-injection.png │ │ ├── html.png │ │ ├── inlay-hints.png │ │ ├── js.png │ │ ├── online-documentation.png │ │ └── syntax-highlight.png ├── svg │ └── file-icon.svg └── xhtml │ ├── abs.xhtml │ ├── acos.xhtml │ ├── acosh.xhtml │ ├── all.xhtml │ ├── any.xhtml │ ├── asin.xhtml │ ├── asinh.xhtml │ ├── atan.xhtml │ ├── atanh.xhtml │ ├── ceil.xhtml │ ├── clamp.xhtml │ ├── cos.xhtml │ ├── cosh.xhtml │ ├── cross.xhtml │ ├── dFdx.xhtml │ ├── degrees.xhtml │ ├── determinant.xhtml │ ├── distance.xhtml │ ├── dot.xhtml │ ├── equal.xhtml │ ├── exp.xhtml │ ├── exp2.xhtml │ ├── faceforward.xhtml │ ├── floatBitsToInt.xhtml │ ├── floor.xhtml │ ├── fract.xhtml │ ├── fwidth.xhtml │ ├── gl_FragCoord.xhtml │ ├── gl_FragDepth.xhtml │ ├── gl_FrontFacing.xhtml │ ├── gl_InstanceID.xhtml │ ├── gl_PointCoord.xhtml │ ├── gl_PointSize.xhtml │ ├── gl_Position.xhtml │ ├── gl_VertexID.xhtml │ ├── greaterThan.xhtml │ ├── greaterThanEqual.xhtml │ ├── intBitsToFloat.xhtml │ ├── inverse.xhtml │ ├── inversesqrt.xhtml │ ├── isinf.xhtml │ ├── isnan.xhtml │ ├── length.xhtml │ ├── lessThan.xhtml │ ├── lessThanEqual.xhtml │ ├── log.xhtml │ ├── log2.xhtml │ ├── matrixCompMult.xhtml │ ├── max.xhtml │ ├── min.xhtml │ ├── mix.xhtml │ ├── mod.xhtml │ ├── modf.xhtml │ ├── normalize.xhtml │ ├── not.xhtml │ ├── notEqual.xhtml │ ├── outerProduct.xhtml │ ├── packHalf2x16.xhtml │ ├── packUnorm.xhtml │ ├── pow.xhtml │ ├── radians.xhtml │ ├── reflect.xhtml │ ├── refract.xhtml │ ├── round.xhtml │ ├── roundEven.xhtml │ ├── sign.xhtml │ ├── sin.xhtml │ ├── sinh.xhtml │ ├── smoothstep.xhtml │ ├── sqrt.xhtml │ ├── step.xhtml │ ├── tan.xhtml │ ├── tanh.xhtml │ ├── texelFetch.xhtml │ ├── texelFetchOffset.xhtml │ ├── texture.xhtml │ ├── textureGrad.xhtml │ ├── textureGradOffset.xhtml │ ├── textureLod.xhtml │ ├── textureLodOffset.xhtml │ ├── textureOffset.xhtml │ ├── textureProj.xhtml │ ├── textureProjGrad.xhtml │ ├── textureProjGradOffset.xhtml │ ├── textureProjLod.xhtml │ ├── textureProjLodOffset.xhtml │ ├── textureProjOffset.xhtml │ ├── textureSize.xhtml │ ├── transpose.xhtml │ ├── trunc.xhtml │ ├── unpackHalf2x16.xhtml │ └── unpackUnorm.xhtml ├── snippets.json ├── src ├── builtin │ ├── builtin.ts │ ├── constructor-processor.ts │ ├── documentation.ts │ ├── generic-type-processor.ts │ ├── info │ │ ├── documentation-redirections.ts │ │ ├── function-summaries.ts │ │ ├── functions.ts │ │ ├── generic_types.ts │ │ ├── important-functions.ts │ │ ├── keywords.ts │ │ ├── layout-parameters.ts │ │ ├── preprocessor.ts │ │ ├── qualifiers.ts │ │ ├── reserved.ts │ │ ├── types.ts │ │ └── variables.ts │ └── interfaces.ts ├── core │ ├── configurations.ts │ ├── constants.ts │ ├── document-info.ts │ ├── document-regions.ts │ ├── glsl-editor.ts │ └── glsl-visitor.ts ├── extension-desktop.ts ├── extension-web.ts ├── extension.ts ├── host-dependent.ts ├── processor │ ├── expression-processor.ts │ ├── expression-result.ts │ ├── function-processor.ts │ ├── helper.ts │ ├── type-declaration-processor.ts │ ├── type-usage-processor.ts │ ├── variable-declaration-processor.ts │ └── variable-usage-processor.ts ├── providers │ ├── glsl-call-hierarchy-provider.ts │ ├── glsl-command-provider.ts │ ├── glsl-completion-provider.ts │ ├── glsl-declaration-provider.ts │ ├── glsl-definition-provider.ts │ ├── glsl-diagnostic-provider.ts │ ├── glsl-document-color-provider.ts │ ├── glsl-document-formatting-provider.ts │ ├── glsl-document-highlight-provider.ts │ ├── glsl-document-semantic-token-provider.ts │ ├── glsl-document-symbol-provider.ts │ ├── glsl-file-decoration-provider.ts │ ├── glsl-folding-provider.ts │ ├── glsl-hover-provider.ts │ ├── glsl-implementation-provider.ts │ ├── glsl-injection-error-provider.ts │ ├── glsl-inlay-hints-provider.ts │ ├── glsl-reference-provider.ts │ ├── glsl-rename-provider.ts │ ├── glsl-signature-help-provider.ts │ ├── glsl-text-provider.ts │ ├── glsl-type-definition-provider.ts │ └── helper │ │ ├── debug-highlighter.ts │ │ ├── formatting-context.ts │ │ ├── hierarchy-element.ts │ │ ├── hierarchy-search-stage.ts │ │ ├── positional-provider-base.ts │ │ └── preprocessor-completion-context.ts └── scope │ ├── array-usage.ts │ ├── element.ts │ ├── function │ ├── function-call.ts │ ├── function-declaration.ts │ ├── function-info.ts │ └── logical-function.ts │ ├── interval.ts │ ├── keyword.ts │ ├── qualifier │ ├── layout-parameter.ts │ ├── qualifier-usage.ts │ └── qualifier.ts │ ├── regions │ ├── color-region.ts │ ├── completion-region.ts │ ├── folding-region.ts │ ├── preprocessor-region.ts │ ├── semantic-region.ts │ ├── signature-parameter-region.ts │ └── signature-region.ts │ ├── scope.ts │ ├── shader-stage.ts │ ├── type │ ├── type-base.ts │ ├── type-category.ts │ ├── type-declaration.ts │ └── type-usage.ts │ └── variable │ ├── variable-declaration.ts │ └── variable-usage.ts ├── syntaxes ├── AntlrGlslLexer.g4 ├── AntlrGlslParser.g4 ├── glsl.language.json ├── html-injected-glsl.language.json ├── js-injected-glsl.language.json └── ts-injected-glsl.language.json ├── tsconfig.json ├── vscodeignore ├── linux.vscodeignore ├── mac.vscodeignore ├── universal.vscodeignore ├── web.vscodeignore └── windows.vscodeignore └── webpack.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /**@type {import('eslint').Linter.Config} */ 2 | // eslint-disable-next-line no-undef 3 | module.exports = { 4 | root: true, 5 | parser: '@typescript-eslint/parser', 6 | plugins: ['@typescript-eslint'], 7 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], 8 | rules: { 9 | semi: ['error', 'always'], 10 | '@typescript-eslint/no-unused-vars': 'off', 11 | '@typescript-eslint/no-empty-function': 'off', 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js eol=lf 2 | *.ts eol=lf 3 | *.json eol=lf 4 | *.yml eol=lf 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: Report a bug 2 | description: Report a bug, for example, the extension crashes, or one of the features doesn't work correctly, etc. 3 | title: '[Bug]: ' 4 | labels: ['bug'] 5 | assignees: 6 | - racz16 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: While most of the fields are not required, please give me as much information as possible to be able to reproduce the problem. 11 | - type: input 12 | id: extension-version 13 | attributes: 14 | label: The extension's version 15 | description: You can find it in the extensions's page in the **Extensions** tab, next to the extension's name. 16 | placeholder: eg. 1.3.6 17 | - type: input 18 | id: vs-code-version 19 | attributes: 20 | label: VS Code's version 21 | description: You can find it in **Help** / **About**. 22 | placeholder: eg. 1.84.1 23 | - type: dropdown 24 | id: extension-host 25 | attributes: 26 | label: Extension host 27 | description: Choose **Desktop VS Code** if you downloaded VS Code, and choose **VS Code for the Web**, if you used , , or similar. 28 | options: 29 | - Desktop VS Code 30 | - VS Code for the Web 31 | - type: input 32 | id: operating-system 33 | attributes: 34 | label: Operating system 35 | description: Please provide the CPU architecture as well, like x64, or ARM64, etc. 36 | placeholder: eg. Windows 11 x64 37 | - type: textarea 38 | id: description 39 | attributes: 40 | label: Description 41 | description: Please provide information, like what have you done when the problem happened, what exactly happened, error messages, logs, pictures, etc. 42 | validations: 43 | required: true 44 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Request a feature 2 | description: Request a completely new feature or the enhancement of an already existing feature. 3 | title: '[Feature]: ' 4 | labels: ['enhancement'] 5 | assignees: 6 | - racz16 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: At the moment, the extension is not under regular development. Sometimes there are new releases, but they usually only contain bug fixes and sometimes very small features. If you have a feature request, feel free to create an issue, but I don't promise, that I'll implement it. 11 | - type: textarea 12 | id: feature-details 13 | attributes: 14 | label: Feature details 15 | validations: 16 | required: true 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/other.yml: -------------------------------------------------------------------------------- 1 | name: Other 2 | description: If you have a question, a suggestion, or anything that is not a bug report and not a feature request. 3 | assignees: 4 | - racz16 5 | body: 6 | - type: textarea 7 | id: content 8 | attributes: 9 | label: Content 10 | validations: 11 | required: true 12 | -------------------------------------------------------------------------------- /.github/workflows/build-and-package.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | include: 14 | - os: windows-latest 15 | command: package-windows-x64 16 | - os: ubuntu-latest 17 | command: package-linux-x64 18 | - os: macos-latest 19 | command: package-mac-x64 20 | - os: ubuntu-latest 21 | command: package-web 22 | - os: ubuntu-latest 23 | command: package-universal 24 | runs-on: ${{ matrix.os }} 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | - name: Install Node.js 29 | uses: actions/setup-node@v4 30 | - name: Install dependencies 31 | run: npm ci 32 | - name: Generate Antlr lexer 33 | run: npx antlr4ts -o "../src/_generated" "AntlrGlslLexer.g4" 34 | working-directory: ./syntaxes 35 | - name: Generate Antlr parser 36 | run: npx antlr4ts -o "../src/_generated" -no-listener -visitor "AntlrGlslParser.g4" 37 | working-directory: ./syntaxes 38 | - name: ESLint 39 | run: npm run eslint 40 | - name: Markdownlint 41 | run: npm run markdownlint 42 | - name: Prettier lint 43 | run: npm run prettier-lint 44 | - name: Build in production mode 45 | run: npm run build-production 46 | - name: Package 47 | run: npm run ${{ matrix.command }} 48 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: publish 2 | on: 3 | release: 4 | types: 5 | - published 6 | jobs: 7 | publish: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v4 12 | - name: Install Node.js 13 | uses: actions/setup-node@v4 14 | - name: Install dependencies 15 | run: npm ci 16 | - name: Generate Antlr lexer 17 | run: npx antlr4ts -o "../src/_generated" "AntlrGlslLexer.g4" 18 | working-directory: ./syntaxes 19 | - name: Generate Antlr parser 20 | run: npx antlr4ts -o "../src/_generated" -no-listener -visitor "AntlrGlslParser.g4" 21 | working-directory: ./syntaxes 22 | - name: Build in production mode 23 | run: npm run build-production 24 | - name: Package universal 25 | run: npm run package-universal 26 | - name: Package to web 27 | run: npm run package-web 28 | - name: Package to Windows x64 29 | run: npm run package-windows-x64 30 | - name: Package to Mac x64 31 | run: npm run package-mac-x64 32 | - name: Package to linux-x64 33 | run: npm run package-linux-x64 34 | - name: Publish 35 | run: npx vsce publish --packagePath $(find . -type f -name "*.vsix" | paste -sd " ") 36 | env: 37 | VSCE_PAT: ${{ secrets.VSCE_PAT }} 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # folder 2 | .vscode-test 3 | .vscode-test-web 4 | dist 5 | node_modules 6 | private 7 | src/_generated 8 | syntaxes/.antlr 9 | 10 | # file type 11 | **/*.vsix 12 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": true, 3 | "line-length": false, 4 | "commands-show-output": false, 5 | "heading-style": { "style": "atx" }, 6 | "ul-style": { "style": "asterisk" }, 7 | "ul-indent": { "indent": 4 }, 8 | "no-trailing-spaces": { "br_spaces": 0, "strict": true }, 9 | "no-duplicate-heading": { "siblings_only": true }, 10 | "ol-prefix": { "style": "ordered" }, 11 | "code-block-style": { "style": "fenced" }, 12 | "code-fence-style": { "style": "backtick" }, 13 | "emphasis-style": { "style": "asterisk" }, 14 | "strong-style": { "style": "underscore" } 15 | } 16 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # folder 2 | .vscode-test 3 | .vscode-test-web 4 | dist 5 | node_modules 6 | private 7 | src/_generated 8 | res 9 | 10 | # file type 11 | **/*.md 12 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "tabWidth": 4, 4 | "singleQuote": true, 5 | "printWidth": 120, 6 | "trailingComma": "es5", 7 | "plugins": ["prettier-plugin-organize-imports"] 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "mike-lischke.vscode-antlr4", 5 | "editorconfig.editorconfig", 6 | "github.vscode-github-actions", 7 | "davidanson.vscode-markdownlint", 8 | "esbenp.prettier-vscode", 9 | "robertohuertasm.vscode-marketplace-preview", 10 | "redcmd.tmlanguage-syntax-highlighter", 11 | "amodio.tsl-problem-matcher" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Run Desktop Extension", 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "runtimeExecutable": "${execPath}", 9 | "args": ["--extensionDevelopmentPath=${workspaceFolder}"], 10 | "outFiles": ["${workspaceFolder}/dist/**/*.js"], 11 | "preLaunchTask": { 12 | "type": "npm", 13 | "script": "watch" 14 | } 15 | }, 16 | { 17 | "name": "Run Web Extension", 18 | "type": "extensionHost", 19 | "request": "launch", 20 | "debugWebWorkerHost": true, 21 | "args": ["--extensionDevelopmentPath=${workspaceFolder}", "--extensionDevelopmentKind=web"], 22 | "outFiles": ["${workspaceFolder}/dist/**/*.js"], 23 | "preLaunchTask": { 24 | "type": "npm", 25 | "script": "watch" 26 | } 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[javascript]": { 3 | "editor.defaultFormatter": "esbenp.prettier-vscode" 4 | }, 5 | "[typescript]": { 6 | "editor.defaultFormatter": "esbenp.prettier-vscode" 7 | }, 8 | "[json]": { 9 | "editor.defaultFormatter": "esbenp.prettier-vscode" 10 | }, 11 | "[jsonc]": { 12 | "editor.defaultFormatter": "esbenp.prettier-vscode" 13 | }, 14 | "[yaml]": { 15 | "editor.defaultFormatter": "esbenp.prettier-vscode" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "Build Extension", 6 | "type": "npm", 7 | "script": "build", 8 | "group": "build", 9 | "presentation": { 10 | "panel": "dedicated", 11 | "reveal": "never" 12 | }, 13 | "problemMatcher": ["$ts-webpack", "$ts-checker-eslint-webpack"] 14 | }, 15 | { 16 | "label": "Watch Extension", 17 | "type": "npm", 18 | "script": "watch", 19 | "isBackground": true, 20 | "group": { 21 | "kind": "build", 22 | "isDefault": true 23 | }, 24 | "presentation": { 25 | "panel": "dedicated", 26 | "reveal": "never" 27 | }, 28 | "problemMatcher": ["$ts-webpack-watch", "$ts-checker-eslint-webpack-watch"] 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | # This is a safeguard, which makes packaging fail if you use the default configuration. 2 | # Instead, use the packaging scripts defined in the package.json file, which uses the real configurations in the vscodeignore folder. 3 | dist 4 | -------------------------------------------------------------------------------- /BUILD.md: -------------------------------------------------------------------------------- 1 | # More information about the project 2 | 3 | If you want to know more about a project structure, how to build, run, package, and much more, read the [extension's wiki page](https://github.com/racz16/WebGL-GLSL-Editor/wiki). 4 | 5 | Originally this file contained this information, but over time it grew too big, that's why I moved it into the wiki. This file is here for compatibility reasons. 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2024 Rácz Zalán 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | For diagnostics, the extension uses the glslang, you can read its license here: https://raw.githubusercontent.com/KhronosGroup/glslang/master/LICENSE.txt 10 | 11 | For the documentation, the extension uses docs.gl, you can read its license here: http://docs.gl/about.html 12 | 13 | For the math formulas, the extension uses MathJax, you can read its license here: https://github.com/mathjax/MathJax/blob/master/LICENSE 14 | -------------------------------------------------------------------------------- /compile-antlr.ps1: -------------------------------------------------------------------------------- 1 | Set-Location "syntaxes" 2 | Remove-Item "../src/_generated" -Recurse -ErrorAction Ignore 3 | npx antlr4ts -o "../src/_generated" "AntlrGlslLexer.g4" 4 | npx antlr4ts -o "../src/_generated" -no-listener -visitor "AntlrGlslParser.g4" -------------------------------------------------------------------------------- /compile-antlr.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "syntaxes" 4 | rm -r -d "../src/_generated" 5 | npx antlr4ts -o "../src/_generated" "AntlrGlslLexer.g4" 6 | npx antlr4ts -o "../src/_generated" -no-listener -visitor "AntlrGlslParser.g4" -------------------------------------------------------------------------------- /language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "//", 4 | "blockComment": ["/*", "*/"] 5 | }, 6 | "brackets": [ 7 | ["{", "}"], 8 | ["(", ")"], 9 | ["[", "]"] 10 | ], 11 | "autoClosingPairs": [ 12 | { 13 | "open": "{", 14 | "close": "}" 15 | }, 16 | { 17 | "open": "[", 18 | "close": "]" 19 | }, 20 | { 21 | "open": "(", 22 | "close": ")" 23 | }, 24 | { 25 | "open": "/*", 26 | "close": "*/" 27 | } 28 | ], 29 | "surroundingPairs": [ 30 | ["{", "}"], 31 | ["[", "]"], 32 | ["(", ")"] 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /res/bin/glslangValidatorLinux: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/bin/glslangValidatorLinux -------------------------------------------------------------------------------- /res/bin/glslangValidatorMac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/bin/glslangValidatorMac -------------------------------------------------------------------------------- /res/bin/glslangValidatorWindows.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/bin/glslangValidatorWindows.exe -------------------------------------------------------------------------------- /res/gif/call-hierarchy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/call-hierarchy.gif -------------------------------------------------------------------------------- /res/gif/code-completion.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/code-completion.gif -------------------------------------------------------------------------------- /res/gif/color-picker.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/color-picker.gif -------------------------------------------------------------------------------- /res/gif/declarations.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/declarations.gif -------------------------------------------------------------------------------- /res/gif/definitions.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/definitions.gif -------------------------------------------------------------------------------- /res/gif/diagnostic.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/diagnostic.gif -------------------------------------------------------------------------------- /res/gif/documentation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/documentation.gif -------------------------------------------------------------------------------- /res/gif/folding.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/folding.gif -------------------------------------------------------------------------------- /res/gif/formatting.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/formatting.gif -------------------------------------------------------------------------------- /res/gif/generate-preprocessed-glsl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/generate-preprocessed-glsl.gif -------------------------------------------------------------------------------- /res/gif/highlights.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/highlights.gif -------------------------------------------------------------------------------- /res/gif/hover.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/hover.gif -------------------------------------------------------------------------------- /res/gif/implementations.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/implementations.gif -------------------------------------------------------------------------------- /res/gif/references.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/references.gif -------------------------------------------------------------------------------- /res/gif/rename.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/rename.gif -------------------------------------------------------------------------------- /res/gif/signature-help.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/signature-help.gif -------------------------------------------------------------------------------- /res/gif/symbols.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/symbols.gif -------------------------------------------------------------------------------- /res/gif/type-definitions.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/gif/type-definitions.gif -------------------------------------------------------------------------------- /res/js/output/chtml/fonts/woff-v2/MathJax_Main-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/js/output/chtml/fonts/woff-v2/MathJax_Main-Regular.woff -------------------------------------------------------------------------------- /res/js/output/chtml/fonts/woff-v2/MathJax_Math-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/js/output/chtml/fonts/woff-v2/MathJax_Math-Italic.woff -------------------------------------------------------------------------------- /res/js/output/chtml/fonts/woff-v2/MathJax_Size1-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/js/output/chtml/fonts/woff-v2/MathJax_Size1-Regular.woff -------------------------------------------------------------------------------- /res/js/output/chtml/fonts/woff-v2/MathJax_Size4-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/js/output/chtml/fonts/woff-v2/MathJax_Size4-Regular.woff -------------------------------------------------------------------------------- /res/js/output/chtml/fonts/woff-v2/MathJax_Zero.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/js/output/chtml/fonts/woff-v2/MathJax_Zero.woff -------------------------------------------------------------------------------- /res/png/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/png/icon.png -------------------------------------------------------------------------------- /res/png/screenshots/code-injection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/png/screenshots/code-injection.png -------------------------------------------------------------------------------- /res/png/screenshots/html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/png/screenshots/html.png -------------------------------------------------------------------------------- /res/png/screenshots/inlay-hints.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/png/screenshots/inlay-hints.png -------------------------------------------------------------------------------- /res/png/screenshots/js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/png/screenshots/js.png -------------------------------------------------------------------------------- /res/png/screenshots/online-documentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/png/screenshots/online-documentation.png -------------------------------------------------------------------------------- /res/png/screenshots/syntax-highlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racz16/WebGL-GLSL-Editor/2e4a5b33826fae8d9f55ae16ba84268a5cdd2458/res/png/screenshots/syntax-highlight.png -------------------------------------------------------------------------------- /res/svg/file-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /res/xhtml/ceil.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

ceil — find the nearest integer that is greater than or equal to the parameter

6 |
7 |
8 |

Declaration

9 |
10 | 11 | 12 | 15 | 16 | 17 |
13 | genType ceil( 14 | genType x);
18 |
 
19 |
20 |
21 |
22 |

Parameters

23 |
24 |
25 |
26 | 27 | 28 | x 29 | 30 | 31 |
32 |
33 |

34 | Specify the value to evaluate. 35 |

36 |
37 |
38 |
39 |
40 |
41 |

Description

42 |

43 | ceil returns a value equal to the nearest integer that is 44 | greater than or equal to x. 45 |

46 |
47 | 48 |
49 |

Version Support

50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 63 | 66 | 67 | 68 | 71 | 74 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 |
61 | 62 | 64 | OpenGL ES Shading Language Version 65 |
69 | Function Name 70 | 72 | 1.00 73 | 75 | 3.00 76 | 78 | 3.10 79 |
ceil (genType)
91 |
92 |
93 |
94 |

See Also

95 |

96 | floor, 97 | round 98 |

99 |
100 | 109 |
110 | -------------------------------------------------------------------------------- /res/xhtml/exp.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

exp — return the natural exponentiation of the parameter

6 |
7 |
8 |

Declaration

9 |
10 | 11 | 12 | 15 | 16 | 17 |
13 | genType exp( 14 | genType x);
18 |
 
19 |
20 |
21 |
22 |

Parameters

23 |
24 |
25 |
26 | 27 | 28 | x 29 | 30 | 31 |
32 |
33 |

34 | Specify the value to exponentiate. 35 |

36 |
37 |
38 |
39 |
40 |
41 |

Description

42 |

43 | exp returns the natural exponentiation of x. i.e., 44 | ex. 45 |

46 |
47 | 48 |
49 |

Version Support

50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 63 | 66 | 67 | 68 | 71 | 74 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 |
61 | 62 | 64 | OpenGL ES Shading Language Version 65 |
69 | Function Name 70 | 72 | 1.00 73 | 75 | 3.00 76 | 78 | 3.10 79 |
exp
91 |
92 |
93 |
94 |

See Also

95 |

96 | exp2, 97 | pow 98 |

99 |
100 | 109 |
110 | -------------------------------------------------------------------------------- /res/xhtml/floor.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

floor — find the nearest integer less than or equal to the parameter

6 |
7 |
8 |

Declaration

9 |
10 | 11 | 12 | 15 | 16 | 17 |
13 | genType floor( 14 | genType x);
18 |
 
19 |
20 |
21 |
22 |

Parameters

23 |
24 |
25 |
26 | 27 | 28 | x 29 | 30 | 31 |
32 |
33 |

34 | Specify the value to evaluate. 35 |

36 |
37 |
38 |
39 |
40 |
41 |

Description

42 |

43 | floor returns a value equal to the nearest integer that is less than or equal to x. 44 |

45 |
46 | 47 |
48 |

Version Support

49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 62 | 65 | 66 | 67 | 70 | 73 | 76 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
60 | 61 | 63 | OpenGL ES Shading Language Version 64 |
68 | Function Name 69 | 71 | 1.00 72 | 74 | 3.00 75 | 77 | 3.10 78 |
floor (genType)
90 |
91 |
92 |
93 |

See Also

94 |

95 | trunc, 96 | round 97 |

98 |
99 | 108 |
109 | -------------------------------------------------------------------------------- /res/xhtml/gl_FragCoord.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

gl_FragCoord — contains the window-relative coordinates of the current fragment

6 |
7 |
8 |

Declaration

9 | in highp vec4 gl_FragCoord ; 11 |
12 |
13 |

Description

14 |

15 | Available only in the fragment language, gl_FragCoord is an input variable that 16 | contains the 17 | window relative coordinate (x, y, z, 1/w) values for the fragment. If multi-sampling, 18 | this value can be for any location within the pixel, or one of the fragment samples. 19 | This value is the result of fixed functionality that interpolates primitives after vertex 20 | processing to generate fragments. The z component is the depth value that would be used for the 21 | fragment's depth if no shader contained any writes to gl_FragDepth. 24 |

25 |
26 | 27 |
28 |

Version Support

29 |
30 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 43 | 46 | 47 | 48 | 51 | 54 | 57 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
41 | 42 | 44 | OpenGL ES Shading Language Version 45 |
49 | Variable Name 50 | 52 | 1.00 53 | 55 | 3.00 56 | 58 | 3.10 59 |
gl_FragCoord
71 |
72 |
73 |
74 |

See Also

75 |

76 | gl_FragDepth 78 |

79 |
80 | 89 |
-------------------------------------------------------------------------------- /res/xhtml/gl_FragDepth.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

gl_FragDepth — establishes a depth value for the current fragment

6 |
7 |
8 |

Declaration

9 | out highp float gl_FragDepth ; 10 |
11 |
12 |

Description

13 |

14 | Available only in the fragment language, gl_FragDepth is an output variable 15 | that is used to establish the depth value for the current fragment. If depth buffering is enabled 16 | and no shader writes to gl_FragDepth, then the fixed varname value for 17 | depth will be used (this value is contained in the z component of gl_FragCoord) 18 | otherwise, the value written to gl_FragDepth is used. 19 | If a shader statically assigns to gl_FragDepth, then the value of the fragment's depth 20 | may be undefined for executions of the shader that take that path. That is, if the set of linked fragment 21 | shaders statically contain a write to gl_FragDepth, then it is responsible for always 22 | writing it. 23 |

24 |
25 | 26 |
27 |

Version Support

28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 41 | 44 | 45 | 46 | 49 | 52 | 55 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
39 | 40 | 42 | OpenGL ES Shading Language Version 43 |
47 | Variable Name 48 | 50 | 1.00 51 | 53 | 3.00 54 | 56 | 3.10 57 |
gl_FragDepth-
69 |
70 |
71 |
72 |

See Also

73 |

74 | gl_FragCoord 75 |

76 |
77 | 86 |
87 | -------------------------------------------------------------------------------- /res/xhtml/gl_InstanceID.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

gl_InstanceID — contains the index of the current primitive in an instanced draw command

6 |
7 |
8 |

Declaration

9 | in highp int gl_InstanceID ; 10 |
11 |
12 |

Description

13 |

14 | gl_InstanceID is a vertex language input variable that 15 | holds the integer index of the current primitive in an instanced draw 16 | command such as glDrawArraysInstanced. If the current 17 | primitive does not originate from an instanced draw command, the value 18 | of gl_InstanceID is zero. 19 |

20 |
21 | 22 |
23 |

Version Support

24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | 40 | 41 | 42 | 45 | 48 | 51 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |
35 | 36 | 38 | OpenGL ES Shading Language Version 39 |
43 | Variable Name 44 | 46 | 1.00 47 | 49 | 3.00 50 | 52 | 3.10 53 |
gl_InstanceID-
65 |
66 |
67 |
68 |

See Also

69 |

70 | gl_VertexID 71 |

72 |
73 | 82 |
83 | -------------------------------------------------------------------------------- /res/xhtml/gl_PointCoord.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

gl_PointCoord — contains the coordinate of a fragment within a point

6 |
7 |
8 |

Declaration

9 | in mediump vec2 gl_PointCoord ; 10 |
11 |
12 |

Description

13 |

14 | gl_PointCoord is a fragment language input variable that contains 15 | the two-dimensional coordinates indicating where within a point primitive the current 16 | fragment is located. If the current primitive is not a point, then values read 17 | from gl_PointCoord are undefined. 18 |

19 |

20 | gl_PointCoord.s ranges from 0.0 to 1.0 across the point horizontally 21 | from left to right. gl_PointCoord.t varies 22 | from 0.0 to 1.0 vertically from top to bottom. 23 |

24 |
25 | 26 |
27 |

Version Support

28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 41 | 44 | 45 | 46 | 49 | 52 | 55 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
39 | 40 | 42 | OpenGL ES Shading Language Version 43 |
47 | Variable Name 48 | 50 | 1.00 51 | 53 | 3.00 54 | 56 | 3.10 57 |
gl_PointCoord
69 |
70 |
71 |
72 |

See Also

73 |

74 | gl_FragCoord, 75 | gl_FragDepth 76 |

77 |
78 | 87 |
88 | -------------------------------------------------------------------------------- /res/xhtml/gl_PointSize.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

gl_PointSize — contains size of rasterized points, in pixels

6 |
7 |
8 |

Declaration

9 | out highp float gl_PointSize ; 10 |
11 |
12 |

Description

13 |

14 | The variable gl_PointSize is intended for a vertex shader to write 15 | the size of the point to be rasterized. It is measured in pixels. 16 | If gl_PointSize is not written to, its value is undefined in subsequent 17 | pipeline stages. 18 |

19 |
20 | 21 |
22 |

Version Support

23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 36 | 39 | 40 | 41 | 44 | 47 | 50 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
34 | 35 | 37 | OpenGL ES Shading Language Version 38 |
42 | Variable Name 43 | 45 | 1.00 46 | 48 | 3.00 49 | 51 | 3.10 52 |
gl_PointSize
64 |
65 |
66 |
67 |

See Also

68 |

69 | gl_Position 70 |

71 |
72 | 81 |
82 | -------------------------------------------------------------------------------- /res/xhtml/gl_Position.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

gl_Position — contains the position of the current vertex

6 |
7 |
8 |

Declaration

9 | out highp vec4 gl_Position ; 10 |
11 |
12 |

Description

13 |

14 | The variable gl_Position is intended for writing the homogeneous 15 | vertex position. It can be written at any time during vertexshader execution. This value 16 | will be used by primitive assembly, clipping, culling, and other fixed functionality 17 | operations, if present, that operate on primitives after vertex processing has occurred. 18 | Its value is undefined after the vertex processing stage if the vertex shader executable 19 | does not write gl_Position. 20 |

21 |
22 | 23 |
24 |

Version Support

25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 41 | 42 | 43 | 46 | 49 | 52 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 |
36 | 37 | 39 | OpenGL ES Shading Language Version 40 |
44 | Variable Name 45 | 47 | 1.00 48 | 50 | 3.00 51 | 53 | 3.10 54 |
gl_Position
66 |
67 |
68 |
69 |

See Also

70 |

71 | gl_PointSize 72 |

73 |
74 | 83 |
84 | -------------------------------------------------------------------------------- /res/xhtml/gl_VertexID.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

gl_VertexID — contains the index of the current vertex

6 |
7 |
8 |

Declaration

9 | in highp int gl_VertexID ; 10 |
11 |
12 |

Description

13 |

14 | gl_VertexID is a vertex language input variable that holds an 15 | integer index for the vertex. The index is impliclty generated by glDrawArrays 16 | and other commands that do not reference the content of the GL_ELEMENT_ARRAY_BUFFER, or 17 | explicitly generated from the content of the GL_ELEMENT_ARRAY_BUFFER 18 | by commands such as glDrawElements. 19 |

20 |
21 | 22 |
23 |

Version Support

24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | 40 | 41 | 42 | 45 | 48 | 51 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |
35 | 36 | 38 | OpenGL ES Shading Language Version 39 |
43 | Variable Name 44 | 46 | 1.00 47 | 49 | 3.00 50 | 52 | 3.10 53 |
gl_VertexID-
65 |
66 |
67 |
68 |

See Also

69 |

70 | gl_InstanceID 71 |

72 |
73 | 82 |
83 | -------------------------------------------------------------------------------- /res/xhtml/isinf.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

isinf — determine whether the parameter is positive or negative infinity

6 |
7 |
8 |

Declaration

9 |
10 | 11 | 12 | 15 | 16 | 17 |
13 | genBType isinf( 14 | genType x);
18 |
 
19 |
20 |
21 |
22 |

Parameters

23 |
24 |
25 |
26 | 27 | 28 | x 29 | 30 | 31 |
32 |
33 |

34 | Specifies the value to test for infinity. 35 |

36 |
37 |
38 |
39 |
40 |
41 |

Description

42 |

43 | For each element element i of the result, isinf returns true if 44 | x[i] is posititve or negative floating point infinity and false otherwise. 45 |

46 |
47 | 48 |
49 |

Version Support

50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 63 | 66 | 67 | 68 | 71 | 74 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 |
61 | 62 | 64 | OpenGL ES Shading Language Version 65 |
69 | Function Name 70 | 72 | 1.00 73 | 75 | 3.00 76 | 78 | 3.10 79 |
isinf (genType)-
91 |
92 |
93 |
94 |

See Also

95 |

96 | isnan 97 |

98 |
99 | 108 |
109 | -------------------------------------------------------------------------------- /res/xhtml/normalize.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

normalize — calculate the normalize product of two vectors

6 |
7 |
8 |

Declaration

9 |
10 | 11 | 12 | 15 | 16 | 17 |
13 | genType normalize( 14 | genType v);
18 |
 
19 |
20 |
21 |
22 |

Parameters

23 |
24 |
25 |
26 | 27 | 28 | v 29 | 30 | 31 |
32 |
33 |

34 | Specifies the vector to normalize. 35 |

36 |
37 |
38 |
39 |
40 |
41 |

Description

42 |

43 | normalize returns a vector with the same direction as its parameter, v, but with length 1. 44 |

45 |
46 | 47 |
48 |

Version Support

49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 62 | 65 | 66 | 67 | 70 | 73 | 76 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
60 | 61 | 63 | OpenGL ES Shading Language Version 64 |
68 | Function Name 69 | 71 | 1.00 72 | 74 | 3.00 75 | 77 | 3.10 78 |
normalize (genType)
90 |
91 |
92 |
93 |

See Also

94 |

95 | length 96 |

97 |
98 | 107 |
108 | -------------------------------------------------------------------------------- /res/xhtml/sqrt.xhtml: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Name

5 |

sqrt — return the square root of the parameter

6 |
7 |
8 |

Declaration

9 |
10 | 11 | 12 | 15 | 16 | 17 |
13 | genType sqrt( 14 | genType x);
18 |
 
19 |
20 |
21 |
22 |

Parameters

23 |
24 |
25 |
26 | 27 | 28 | x 29 | 30 | 31 |
32 |
33 |

34 | Specify the value of which to take the square root. 35 |

36 |
37 |
38 |
39 |
40 |
41 |

Description

42 |

43 | sqrt returns the square root of x. i.e., the value 44 | x. 45 | Results are undefined if x<0. 46 |

47 |
48 | 49 |
50 |

Version Support

51 |
52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 64 | 67 | 68 | 69 | 72 | 75 | 78 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |
62 | 63 | 65 | OpenGL ES Shading Language Version 66 |
70 | Function Name 71 | 73 | 1.00 74 | 76 | 3.00 77 | 79 | 3.10 80 |
sqrt (genType)
92 |
93 |
94 |
95 |

See Also

96 |

97 | inversesqrt 98 |

99 |
100 | 109 |
110 | -------------------------------------------------------------------------------- /snippets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": { 3 | "prefix": "version", 4 | "body": "#version ${1:300} es", 5 | "description": "Creates the version declaration" 6 | }, 7 | "main": { 8 | "prefix": "main", 9 | "body": ["void main(){", "\t$0", "}"], 10 | "description": "Creates the main function" 11 | }, 12 | "function": { 13 | "prefix": "func", 14 | "body": ["${1:vec3} ${2:getValue}($3){", "\t$0", "}"], 15 | "description": "Creates a function" 16 | }, 17 | "for": { 18 | "prefix": "for", 19 | "body": ["for(${1:int} ${2:i} = ${3:0}; ${2:i} < ${4:max}; ${2:i}++) {", "\t$0", "}"], 20 | "description": "Creates a for loop" 21 | }, 22 | "while": { 23 | "prefix": "while", 24 | "body": ["while(${1:true}) {", "\t$0", "}"], 25 | "description": "Creates a while loop" 26 | }, 27 | "if": { 28 | "prefix": "if", 29 | "body": ["if(${1:true}) {", "\t$0", "}"], 30 | "description": "Creates an if statement" 31 | }, 32 | "iffloat": { 33 | "prefix": ["iffloat", "iff"], 34 | "body": ["if(${1:value} < ${2:0.0001f} && ${1:value} > ${3:-0.0001f}) {", "\t$0", "}"], 35 | "description": "Creates a float comparison if statement" 36 | }, 37 | "ifelse": { 38 | "prefix": ["ifelse", "ife"], 39 | "body": ["if(${1:true}) {", "\t$0", "}else{", "\t", "}"], 40 | "description": "Creates an if-else statement" 41 | }, 42 | "struct": { 43 | "prefix": "struct", 44 | "body": ["struct ${1:Type} {", "\t${2:vec3} ${3:vec};$0", "};"], 45 | "description": "Creates a struct" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/builtin/constructor-processor.ts: -------------------------------------------------------------------------------- 1 | import { Helper } from '../processor/helper'; 2 | import { ArrayUsage } from '../scope/array-usage'; 3 | import { LogicalFunction } from '../scope/function/logical-function'; 4 | import { TypeCategory } from '../scope/type/type-category'; 5 | import { TypeDeclaration } from '../scope/type/type-declaration'; 6 | 7 | export class ConstructorProcessor { 8 | private static result: Array; 9 | private static td: TypeDeclaration; 10 | private static typeSize: number; 11 | private static types: Map; 12 | 13 | private static initialize(td: TypeDeclaration, types: Map): void { 14 | this.result = new Array(); 15 | this.td = td; 16 | this.typeSize = td.width * td.height; 17 | this.types = types; 18 | } 19 | 20 | public static getConstructors(td: TypeDeclaration, types: Map): Array { 21 | this.initialize(td, types); 22 | if (td.isScalar()) { 23 | this.addScalarConstructors(); 24 | } else if (td.isVector()) { 25 | this.addVectorConstructors(); 26 | } else if (td.typeCategory === TypeCategory.CUSTOM) { 27 | this.addConstructor(this.td.members.map((vd) => vd.type.declaration)); 28 | } 29 | return this.result; 30 | } 31 | 32 | private static addScalarConstructors(): void { 33 | for (const type of this.types) { 34 | if (this.canBeParameter(type)) { 35 | const parameters = new Array(type[1]); 36 | this.addConstructor(parameters); 37 | } 38 | } 39 | } 40 | 41 | private static addVectorConstructors(parameters = new Array()): void { 42 | const paramSize = this.getParametersSize(parameters); 43 | if (parameters.length === 1) { 44 | const param = parameters[0]; 45 | if (param.isScalar() || paramSize >= this.typeSize) { 46 | this.addConstructor(parameters); 47 | } 48 | } else if (parameters.length > 1) { 49 | if (paramSize === this.typeSize) { 50 | this.addConstructor(parameters); 51 | } 52 | } 53 | if (paramSize < this.typeSize) { 54 | for (const type of this.types) { 55 | if (this.canBeParameter(type)) { 56 | parameters.push(type[1]); 57 | this.addVectorConstructors(parameters); 58 | parameters.pop(); 59 | } 60 | } 61 | } 62 | } 63 | 64 | private static addConstructor(parameters: Array): void { 65 | const rtu = Helper.createTypeUsage(this.td.name, this.td, new ArrayUsage()); 66 | const fd = Helper.createFunctionDeclaration(this.td.name, rtu, true); 67 | for (let i = 0; i < parameters.length; i++) { 68 | const ptd = parameters[i]; 69 | const ptu = Helper.createTypeUsage(ptd.name, ptd, new ArrayUsage()); 70 | const name = this.getParameterName(parameters, i); 71 | const vd = Helper.createVariableDeclaration(name, ptu, true, false); 72 | fd.parameters.push(vd); 73 | } 74 | const lf = new LogicalFunction(); 75 | lf.prototypes.push(fd); 76 | fd.logicalFunction = lf; 77 | this.result.push(lf); 78 | } 79 | 80 | private static getParameterName(parameters: Array, i: number): string { 81 | if (this.td.typeCategory === TypeCategory.CUSTOM) { 82 | return this.td.members[i].name; 83 | } else if (parameters.length === 1) { 84 | return 'value'; 85 | } else { 86 | return `v${i}`; 87 | } 88 | } 89 | 90 | private static canBeParameter([name, td]: [string, TypeDeclaration]): boolean { 91 | return ( 92 | td.typeCategory === TypeCategory.TRANSPARENT && name !== 'mat2x2' && name !== 'mat3x3' && name !== 'mat4x4' 93 | ); 94 | } 95 | 96 | private static getParametersSize(parameters: Array): number { 97 | let result = 0; 98 | for (const td of parameters) { 99 | result += td.width * td.height; 100 | } 101 | return result; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/builtin/documentation.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import { Uri } from 'vscode'; 3 | import { GlslEditor } from '../core/glsl-editor'; 4 | import { documentationRedirections } from './info/documentation-redirections'; 5 | 6 | export class Documentation { 7 | private static readonly documentations = new Map(); 8 | private static readonly redirections = new Map(); 9 | private static initialized = false; 10 | 11 | private static initialize(): void { 12 | if (!this.initialized) { 13 | for (const redirection of documentationRedirections) { 14 | this.redirections.set(redirection.from, redirection.to); 15 | } 16 | this.initialized = true; 17 | } 18 | } 19 | 20 | public static getDocumentation(name: string, uri: Uri): string { 21 | this.initialize(); 22 | const redirectedName = this.redirections.get(name) ?? name; 23 | let documentation = this.documentations.get(redirectedName); 24 | if (!documentation) { 25 | documentation = this.getDocumentationFromFile(name, redirectedName, uri); 26 | this.documentations.set(redirectedName, documentation); 27 | } 28 | return documentation; 29 | } 30 | 31 | private static getDocumentationFromFile(name: string, redirectedName: string, uri: Uri): string { 32 | const filePath = Uri.file(`${GlslEditor.getContext().extensionPath}/res/xhtml/${redirectedName}.xhtml`); 33 | if (!fs.existsSync(filePath.fsPath)) { 34 | return `${name} — documentation is not available`; 35 | } 36 | const fileContent = fs.readFileSync(filePath.fsPath, 'utf8'); 37 | return this.createHtml(redirectedName, uri, fileContent); 38 | } 39 | 40 | private static createHtml(redirectedName: string, uri: Uri, fileContent: string): string { 41 | return ` 42 | 43 | 44 | 45 | 46 | 47 | ${redirectedName} 48 | 55 | 56 | 57 | 58 | ${fileContent} 59 | 60 | 61 | `; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/builtin/generic-type-processor.ts: -------------------------------------------------------------------------------- 1 | import { IFunction, IParameter } from './interfaces'; 2 | 3 | export class GenericTypeProcessor { 4 | private static func: IFunction; 5 | private static genTypes: Map>; 6 | 7 | private static initialize(func: IFunction, genTypes: Map>): void { 8 | this.func = func; 9 | this.genTypes = genTypes; 10 | } 11 | 12 | public static getFunctions(func: IFunction, genTypes: Map>): Array { 13 | this.initialize(func, genTypes); 14 | const gtg = this.getGenericTypeGroup(); 15 | const ret = new Array(); 16 | if (gtg === GenericTypeGroup.NONE) { 17 | ret.push(func); 18 | return ret; 19 | } else { 20 | const vc = this.getVariantCount(gtg); 21 | for (let i = 0; i < vc; i++) { 22 | const f = this.createFunction(i); 23 | ret.push(f); 24 | } 25 | return ret; 26 | } 27 | } 28 | 29 | private static createFunction(i: number): IFunction { 30 | const f: IFunction = { 31 | name: this.func.name, 32 | qualifiers: this.func.qualifiers, 33 | stage: this.func.stage, 34 | returnType: this.getType(this.func.returnType, i), 35 | parameters: new Array(), 36 | extension: this.func.extension, 37 | }; 38 | this.addParameters(f, i); 39 | return f; 40 | } 41 | 42 | private static addParameters(func: IFunction, i: number): void { 43 | for (const param of this.func.parameters) { 44 | const p: IParameter = { 45 | name: param.name, 46 | qualifiers: param.qualifiers, 47 | type: this.getType(param.type, i), 48 | }; 49 | func.parameters.push(p); 50 | } 51 | } 52 | 53 | private static getType(type: string, index: number): string { 54 | const realType = this.genTypes.get(type); 55 | return realType ? realType[index] : type; 56 | } 57 | 58 | private static getGenericTypeGroup(): GenericTypeGroup { 59 | const rgtg = this.getGenericTypeGroupOf(this.func.returnType); 60 | if (rgtg !== GenericTypeGroup.NONE) { 61 | return rgtg; 62 | } 63 | for (const parameter of this.func.parameters) { 64 | const pgtg = this.getGenericTypeGroupOf(parameter.type); 65 | if (pgtg !== GenericTypeGroup.NONE) { 66 | return pgtg; 67 | } 68 | } 69 | return GenericTypeGroup.NONE; 70 | } 71 | 72 | private static getGenericTypeGroupOf(type: string): GenericTypeGroup { 73 | switch (type) { 74 | case 'genType': 75 | case 'genIType': 76 | case 'genUType': 77 | case 'genBType': 78 | return GenericTypeGroup.GEN_TYPE; 79 | case 'vec': 80 | case 'ivec': 81 | case 'uvec': 82 | case 'bvec': 83 | return GenericTypeGroup.X_VEC; 84 | case 'gvec2': 85 | case 'gvec3': 86 | case 'gvec4': 87 | case 'gsampler2D': 88 | case 'gsampler3D': 89 | case 'gsamplerCube': 90 | case 'gsampler2DArray': 91 | return GenericTypeGroup.G_SAMPLER; 92 | case 'mat': 93 | return GenericTypeGroup.MAT; 94 | default: 95 | return GenericTypeGroup.NONE; 96 | } 97 | } 98 | 99 | private static getVariantCount(gtg: GenericTypeGroup): number { 100 | switch (gtg) { 101 | case GenericTypeGroup.GEN_TYPE: 102 | return this.genTypes.get('genType').length; 103 | case GenericTypeGroup.X_VEC: 104 | return this.genTypes.get('vec').length; 105 | case GenericTypeGroup.G_SAMPLER: 106 | return this.genTypes.get('gsampler2D').length; 107 | case GenericTypeGroup.MAT: 108 | return this.genTypes.get('mat').length; 109 | default: 110 | throw new Error(); 111 | } 112 | } 113 | } 114 | 115 | export enum GenericTypeGroup { 116 | GEN_TYPE, 117 | X_VEC, 118 | G_SAMPLER, 119 | MAT, 120 | NONE, 121 | } 122 | -------------------------------------------------------------------------------- /src/builtin/info/documentation-redirections.ts: -------------------------------------------------------------------------------- 1 | import { IRedirection } from '../interfaces'; 2 | 3 | export const documentationRedirections: Array = [ 4 | { 5 | from: 'dFdy', 6 | to: 'dFdx', 7 | }, 8 | { 9 | from: 'floatBitsToUint', 10 | to: 'floatBitsToInt', 11 | }, 12 | { 13 | from: 'uintBitsToFloat', 14 | to: 'intBitsToFloat', 15 | }, 16 | { 17 | from: 'packUnorm2x16', 18 | to: 'packUnorm', 19 | }, 20 | { 21 | from: 'packSnorm2x16', 22 | to: 'packUnorm', 23 | }, 24 | { 25 | from: 'unpackUnorm2x16', 26 | to: 'unpackUnorm', 27 | }, 28 | { 29 | from: 'unpackSnorm2x16', 30 | to: 'unpackUnorm', 31 | }, 32 | ]; 33 | -------------------------------------------------------------------------------- /src/builtin/info/generic_types.ts: -------------------------------------------------------------------------------- 1 | import { IGenericType } from '../interfaces'; 2 | 3 | export const genericTypes = new Map>([ 4 | [ 5 | '100', 6 | [ 7 | { 8 | generic: 'genType', 9 | real: ['float', 'vec2', 'vec3', 'vec4'], 10 | }, 11 | { 12 | generic: 'genIType', 13 | real: ['int', 'ivec2', 'ivec3', 'ivec4'], 14 | }, 15 | { 16 | generic: 'genBType', 17 | real: ['bool', 'bvec2', 'bvec3', 'bvec4'], 18 | }, 19 | { 20 | generic: 'vec', 21 | real: ['vec2', 'vec3', 'vec4'], 22 | }, 23 | { 24 | generic: 'ivec', 25 | real: ['ivec2', 'ivec3', 'ivec4'], 26 | }, 27 | { 28 | generic: 'bvec', 29 | real: ['bvec2', 'bvec3', 'bvec4'], 30 | }, 31 | { 32 | generic: 'gvec2', 33 | real: ['vec2', 'ivec2'], 34 | }, 35 | { 36 | generic: 'gvec3', 37 | real: ['vec3', 'ivec3'], 38 | }, 39 | { 40 | generic: 'gvec4', 41 | real: ['vec4', 'ivec4'], 42 | }, 43 | { 44 | generic: 'mat', 45 | real: ['mat2', 'mat3', 'mat4'], 46 | }, 47 | ], 48 | ], 49 | [ 50 | '300', 51 | [ 52 | { 53 | generic: 'genType', 54 | real: ['float', 'vec2', 'vec3', 'vec4'], 55 | }, 56 | { 57 | generic: 'genIType', 58 | real: ['int', 'ivec2', 'ivec3', 'ivec4'], 59 | }, 60 | { 61 | generic: 'genUType', 62 | real: ['uint', 'uvec2', 'uvec3', 'uvec4'], 63 | }, 64 | { 65 | generic: 'genBType', 66 | real: ['bool', 'bvec2', 'bvec3', 'bvec4'], 67 | }, 68 | { 69 | generic: 'vec', 70 | real: ['vec2', 'vec3', 'vec4'], 71 | }, 72 | { 73 | generic: 'ivec', 74 | real: ['ivec2', 'ivec3', 'ivec4'], 75 | }, 76 | { 77 | generic: 'uvec', 78 | real: ['uvec2', 'uvec3', 'uvec4'], 79 | }, 80 | { 81 | generic: 'bvec', 82 | real: ['bvec2', 'bvec3', 'bvec4'], 83 | }, 84 | { 85 | generic: 'gvec2', 86 | real: ['vec2', 'ivec2', 'uvec2'], 87 | }, 88 | { 89 | generic: 'gvec3', 90 | real: ['vec3', 'ivec3', 'uvec3'], 91 | }, 92 | { 93 | generic: 'gvec4', 94 | real: ['vec4', 'ivec4', 'uvec4'], 95 | }, 96 | { 97 | generic: 'gsampler2D', 98 | real: ['sampler2D', 'isampler2D', 'usampler2D'], 99 | }, 100 | { 101 | generic: 'gsampler3D', 102 | real: ['sampler3D', 'isampler3D', 'usampler3D'], 103 | }, 104 | { 105 | generic: 'gsamplerCube', 106 | real: ['samplerCube', 'isamplerCube', 'usamplerCube'], 107 | }, 108 | { 109 | generic: 'gsampler2DArray', 110 | real: ['sampler2DArray', 'isampler2DArray', 'usampler2DArray'], 111 | }, 112 | { 113 | generic: 'mat', 114 | real: [ 115 | 'mat2', 116 | 'mat3', 117 | 'mat4', 118 | 'mat2x2', 119 | 'mat3x3', 120 | 'mat4x4', 121 | 'mat2x3', 122 | 'mat3x2', 123 | 'mat4x2', 124 | 'mat2x4', 125 | 'mat3x4', 126 | 'mat4x3', 127 | ], 128 | }, 129 | ], 130 | ], 131 | ]); 132 | -------------------------------------------------------------------------------- /src/builtin/info/important-functions.ts: -------------------------------------------------------------------------------- 1 | export const importantFunctions: Array = [ 2 | 'cross', 3 | 'distance', 4 | 'dot', 5 | 'inverse', 6 | 'length', 7 | 'normalize', 8 | 'reflect', 9 | 'refract', 10 | 'texture', 11 | 'texture2D', 12 | 'transpose', 13 | 'vec2', 14 | 'vec3', 15 | 'vec4', 16 | 'mat3', 17 | 'mat4', 18 | ]; 19 | -------------------------------------------------------------------------------- /src/builtin/info/keywords.ts: -------------------------------------------------------------------------------- 1 | import { IKeyword } from '../interfaces'; 2 | 3 | export const keywords = new Map>([ 4 | [ 5 | '100', 6 | [ 7 | { 8 | name: 'break', 9 | }, 10 | { 11 | name: 'continue', 12 | }, 13 | { 14 | name: 'do', 15 | }, 16 | { 17 | name: 'for', 18 | }, 19 | { 20 | name: 'while', 21 | }, 22 | { 23 | name: 'if', 24 | }, 25 | { 26 | name: 'else', 27 | }, 28 | { 29 | name: 'discard', 30 | stage: 'fragment', 31 | }, 32 | { 33 | name: 'return', 34 | }, 35 | { 36 | name: 'struct', 37 | }, 38 | { 39 | name: 'void', 40 | }, 41 | { 42 | name: 'true', 43 | }, 44 | { 45 | name: 'false', 46 | }, 47 | ], 48 | ], 49 | [ 50 | '300', 51 | [ 52 | { 53 | name: 'break', 54 | }, 55 | { 56 | name: 'continue', 57 | }, 58 | { 59 | name: 'do', 60 | }, 61 | { 62 | name: 'for', 63 | }, 64 | { 65 | name: 'while', 66 | }, 67 | { 68 | name: 'switch', 69 | }, 70 | { 71 | name: 'case', 72 | }, 73 | { 74 | name: 'default', 75 | }, 76 | { 77 | name: 'if', 78 | }, 79 | { 80 | name: 'else', 81 | }, 82 | { 83 | name: 'discard', 84 | stage: 'fragment', 85 | }, 86 | { 87 | name: 'return', 88 | }, 89 | { 90 | name: 'struct', 91 | }, 92 | { 93 | name: 'void', 94 | }, 95 | { 96 | name: 'true', 97 | }, 98 | { 99 | name: 'false', 100 | }, 101 | ], 102 | ], 103 | ]); 104 | -------------------------------------------------------------------------------- /src/builtin/info/layout-parameters.ts: -------------------------------------------------------------------------------- 1 | import { ILayoutParameter } from '../interfaces'; 2 | 3 | export const layoutParameters: Array = [ 4 | { 5 | name: 'location', 6 | assignable: true, 7 | }, 8 | { 9 | name: 'shared', 10 | }, 11 | { 12 | name: 'packed', 13 | }, 14 | { 15 | name: 'std140', 16 | }, 17 | { 18 | name: 'row_major', 19 | }, 20 | { 21 | name: 'column_major', 22 | }, 23 | { 24 | name: 'num_views', 25 | assignable: true, 26 | extension: 'GL_OVR_multiview2', 27 | }, 28 | ]; 29 | -------------------------------------------------------------------------------- /src/builtin/info/preprocessor.ts: -------------------------------------------------------------------------------- 1 | export const preprocessorDirectives: Array>> = [ 2 | [['version'], ['100', '300'], ['es']], 3 | [['define']], 4 | [['undef']], 5 | [['if']], 6 | [['ifdef']], 7 | [['ifndef']], 8 | [['else']], 9 | [['elif']], 10 | [['endif']], 11 | [['error']], 12 | [['pragma'], ['STDGL', 'optimize(on)', 'optimize(off)', 'debug(on)', 'debug(off)']], 13 | [ 14 | ['extension'], 15 | [ 16 | 'all', 17 | 'GL_ANGLE_multi_draw', 18 | 'GL_EXT_draw_buffers', 19 | 'GL_OVR_multiview2', 20 | 'GL_OES_standard_derivatives', 21 | 'GL_EXT_shader_texture_lod', 22 | 'GL_EXT_frag_depth', 23 | ], 24 | ['require', 'enable', 'warn', 'disable'], 25 | ], 26 | [['line']], 27 | ]; 28 | 29 | export const preprocessorMacros: Array = [ 30 | '__LINE__', 31 | '__FILE__', 32 | '__VERSION__', 33 | 'GL_ES', 34 | 'GL_ANGLE_multi_draw', 35 | 'GL_OVR_multiview2', 36 | 'GL_OES_standard_derivatives', 37 | 'GL_EXT_shader_texture_lod', 38 | 'GL_EXT_frag_depth', 39 | ]; 40 | -------------------------------------------------------------------------------- /src/builtin/info/qualifiers.ts: -------------------------------------------------------------------------------- 1 | import { IQualifier } from '../interfaces'; 2 | 3 | export const qualifiers = new Map>([ 4 | [ 5 | '100', 6 | [ 7 | { 8 | name: 'precision', 9 | order: 10, 10 | }, 11 | { 12 | name: 'invariant', 13 | order: 10, 14 | }, 15 | { 16 | name: 'const', 17 | order: 30, 18 | }, 19 | { 20 | name: 'inout', 21 | order: 31, 22 | }, 23 | { 24 | name: 'in', 25 | order: 31, 26 | }, 27 | { 28 | name: 'out', 29 | order: 31, 30 | }, 31 | { 32 | name: 'uniform', 33 | order: 30, 34 | }, 35 | { 36 | name: 'varying', 37 | order: 31, 38 | }, 39 | { 40 | name: 'attribute', 41 | order: 31, 42 | }, 43 | { 44 | name: 'highp', 45 | order: 40, 46 | }, 47 | { 48 | name: 'mediump', 49 | order: 40, 50 | }, 51 | { 52 | name: 'lowp', 53 | order: 40, 54 | }, 55 | ], 56 | ], 57 | [ 58 | '300', 59 | [ 60 | { 61 | name: 'precision', 62 | order: 10, 63 | }, 64 | { 65 | name: 'layout', 66 | order: 10, 67 | }, 68 | { 69 | name: 'invariant', 70 | order: 10, 71 | }, 72 | { 73 | name: 'smooth', 74 | order: 20, 75 | }, 76 | { 77 | name: 'flat', 78 | order: 20, 79 | }, 80 | { 81 | name: 'const', 82 | order: 30, 83 | }, 84 | { 85 | name: 'inout', 86 | order: 31, 87 | }, 88 | { 89 | name: 'in', 90 | order: 31, 91 | }, 92 | { 93 | name: 'out', 94 | order: 31, 95 | }, 96 | { 97 | name: 'centroid', 98 | order: 30, 99 | }, 100 | { 101 | name: 'uniform', 102 | order: 30, 103 | }, 104 | { 105 | name: 'highp', 106 | order: 40, 107 | }, 108 | { 109 | name: 'mediump', 110 | order: 40, 111 | }, 112 | { 113 | name: 'lowp', 114 | order: 40, 115 | }, 116 | ], 117 | ], 118 | ]); 119 | -------------------------------------------------------------------------------- /src/builtin/info/reserved.ts: -------------------------------------------------------------------------------- 1 | export const reservedWords = new Map>([ 2 | [ 3 | '100', 4 | [ 5 | 'asm', 6 | 'class', 7 | 'union', 8 | 'enum', 9 | 'typedef', 10 | 'template', 11 | 'this', 12 | 'goto', 13 | 'inline', 14 | 'noinline', 15 | 'volatile', 16 | 'public', 17 | 'static', 18 | 'extern', 19 | 'external', 20 | 'interface', 21 | 'long', 22 | 'short', 23 | 'double', 24 | 'half', 25 | 'fixed', 26 | 'unsigned', 27 | 'superp', 28 | 'input', 29 | 'output', 30 | 'hvec2', 31 | 'hvec3', 32 | 'hvec4', 33 | 'dvec2', 34 | 'dvec3', 35 | 'dvec4', 36 | 'fvec2', 37 | 'fvec3', 38 | 'fvec4', 39 | 'sampler3DRect', 40 | 'sampler1D', 41 | 'sampler1DShadow', 42 | 'sampler2DRect', 43 | 'sampler2DRectShadow', 44 | 'sizeof', 45 | 'cast', 46 | 'namespace', 47 | 'using', 48 | 'packed', 49 | 'switch', 50 | 'default', 51 | 'flat', 52 | 'sampler3D', 53 | 'sampler2DShadow', 54 | ], 55 | ], 56 | [ 57 | '300', 58 | [ 59 | 'attribute', 60 | 'varying', 61 | 'coherent', 62 | 'volatile', 63 | 'restrict', 64 | 'readonly', 65 | 'writeonly', 66 | 'resource', 67 | 'atomic_uint', 68 | 'noperspective', 69 | 'patch sample', 70 | 'subroutine', 71 | 'common', 72 | 'partition', 73 | 'active', 74 | 'asm', 75 | 'class', 76 | 'union', 77 | 'enum', 78 | 'typedef', 79 | 'template', 80 | 'this', 81 | 'goto', 82 | 'inline', 83 | 'noinline', 84 | 'public', 85 | 'static', 86 | 'extern', 87 | 'external', 88 | 'interface', 89 | 'long', 90 | 'short', 91 | 'double', 92 | 'half', 93 | 'fixed', 94 | 'unsigned', 95 | 'superp', 96 | 'input', 97 | 'output', 98 | 'hvec2', 99 | 'hvec3', 100 | 'hvec4', 101 | 'dvec2', 102 | 'dvec3', 103 | 'dvec4', 104 | 'fvec2', 105 | 'fvec3', 106 | 'fvec4', 107 | 'sampler3DRect', 108 | 'filter', 109 | 'image1D', 110 | 'image2D', 111 | 'image3D', 112 | 'imageCube', 113 | 'iimage1D', 114 | 'iimage2D', 115 | 'iimage3D', 116 | 'iimageCube', 117 | 'uimage1D', 118 | 'uimage2D', 119 | 'uimage3D', 120 | 'uimageCube', 121 | 'image1DArray', 122 | 'image2DArray', 123 | 'iimage1DArray', 124 | 'iimage2DArray', 125 | 'uimage1DArray', 126 | 'uimage2DArray', 127 | 'imageBuffer', 128 | 'iimageBuffer', 129 | 'uimageBuffer', 130 | 'sampler1D', 131 | 'sampler1DShadow', 132 | 'sampler1DArray', 133 | 'sampler1DArrayShadow', 134 | 'isampler1D', 135 | 'isampler1DArray', 136 | 'usampler1D', 137 | 'usampler1DArray', 138 | 'sampler2DRect', 139 | 'sampler2DRectShadow', 140 | 'isampler2DRect', 141 | 'usampler2DRect', 142 | 'samplerBuffer', 143 | 'isamplerBuffer', 144 | 'usamplerBuffer', 145 | 'sampler2DMS', 146 | 'isampler2DMS', 147 | 'usampler2DMS', 148 | 'sampler2DMSArray', 149 | 'isampler2DMSArray', 150 | 'usampler2DMSArray', 151 | 'sizeof', 152 | 'cast', 153 | 'namespace', 154 | 'using', 155 | ], 156 | ], 157 | ]); 158 | -------------------------------------------------------------------------------- /src/builtin/interfaces.ts: -------------------------------------------------------------------------------- 1 | // FUNCTION 2 | export interface IFunction { 3 | qualifiers?: Array; 4 | returnType: string; 5 | name: string; 6 | parameters: Array; 7 | stage?: string; 8 | extension?: string; 9 | } 10 | 11 | export interface IParameter { 12 | qualifiers?: Array; 13 | type: string; 14 | name: string; 15 | } 16 | 17 | export interface IFunctionSummary { 18 | name: string; 19 | summary?: string; 20 | stage?: string; 21 | parameters: Array; 22 | extension?: string; 23 | } 24 | 25 | export interface IFunctionParameterSummary { 26 | name: string; 27 | summary?: string; 28 | } 29 | 30 | // KEYWORD 31 | export interface IKeyword { 32 | name: string; 33 | stage?: string; 34 | } 35 | 36 | // QUALIFIER 37 | export interface IQualifier { 38 | name: string; 39 | order: number; 40 | } 41 | 42 | export interface ILayoutParameter { 43 | name: string; 44 | assignable?: boolean; 45 | extension?: string; 46 | } 47 | 48 | // REDIRECTION 49 | export interface IRedirection { 50 | from: string; 51 | to: string; 52 | } 53 | 54 | // TYPE 55 | export interface ITransparentType { 56 | name: string; 57 | width: number; 58 | height: number; 59 | base: string; 60 | alias?: string; 61 | } 62 | 63 | export interface IOpaqueType { 64 | name: string; 65 | } 66 | 67 | export interface ICustomType { 68 | name: string; 69 | members: Array; 70 | } 71 | 72 | export interface ITypeMember { 73 | memberPrecision: string; 74 | memberType: string; 75 | memberName: string; 76 | } 77 | 78 | export interface IGenericType { 79 | generic: string; 80 | real: Array; 81 | } 82 | 83 | // VARIABLE 84 | export interface IVariable { 85 | min?: number; 86 | summary?: string; 87 | notDocumented?: boolean; 88 | type: string; 89 | name: string; 90 | array?: number; 91 | qualifiers?: Array; 92 | stage?: string; 93 | extension?: string; 94 | } 95 | -------------------------------------------------------------------------------- /src/core/constants.ts: -------------------------------------------------------------------------------- 1 | export class Constants { 2 | public static readonly EXTENSION_NAME = 'webgl-glsl-editor'; 3 | public static readonly GLSL = 'glsl'; 4 | 5 | public static readonly VERT_GLSL = 'vert.glsl'; 6 | public static readonly VS_GLSL = 'vs.glsl'; 7 | public static readonly VERT = 'vert'; 8 | public static readonly VS = 'vs'; 9 | public static readonly VERTEX_EXTS = [this.VERT_GLSL, this.VS_GLSL, this.VERT, this.VS]; 10 | 11 | public static readonly FRAG_GLSL = 'frag.glsl'; 12 | public static readonly FS_GLSL = 'fs.glsl'; 13 | public static readonly FRAG = 'frag'; 14 | public static readonly FS = 'fs'; 15 | public static readonly FRAGMENT_EXTS = [this.FRAG_GLSL, this.FS_GLSL, this.FRAG, this.FS]; 16 | 17 | public static readonly PREPROCESSED_GLSL = 'webgl-glsl-editor-preprocessed'; 18 | 19 | public static readonly CAN_RUN_COMPILER_CONTEXT = `${Constants.EXTENSION_NAME}.canRunCompiler`; 20 | 21 | public static readonly VEC3 = 'vec3'; 22 | public static readonly VEC4 = 'vec4'; 23 | public static readonly BOOL = 'bool'; 24 | public static readonly FLOAT = 'float'; 25 | public static readonly INT = 'int'; 26 | public static readonly UINT = 'uint'; 27 | public static readonly COLOR = 'color'; 28 | public static readonly COLOUR = 'colour'; 29 | 30 | public static readonly EMPTY = ''; 31 | public static readonly LRB = '('; 32 | public static readonly RRB = ')'; 33 | public static readonly LCB = '{'; 34 | public static readonly RCB = '}'; 35 | public static readonly LSB = '['; 36 | public static readonly RSB = ']'; 37 | public static readonly NEW_LINE = '\n'; 38 | public static readonly TAB = '\t'; 39 | public static readonly SPACE = ' '; 40 | public static readonly COMMA = ','; 41 | public static readonly COLON = ':'; 42 | public static readonly SEMICOLON = ';'; 43 | public static readonly DOT = '.'; 44 | 45 | public static readonly xyzw = ['x', 'y', 'z', 'w']; 46 | public static readonly rgba = ['r', 'g', 'b', 'a']; 47 | public static readonly stpq = ['s', 't', 'p', 'q']; 48 | 49 | public static readonly INVALID = -1; 50 | } 51 | -------------------------------------------------------------------------------- /src/core/document-regions.ts: -------------------------------------------------------------------------------- 1 | import { Interval } from '../scope/interval'; 2 | import { ColorRegion } from '../scope/regions/color-region'; 3 | import { CompletionRegion } from '../scope/regions/completion-region'; 4 | import { FoldingRegion } from '../scope/regions/folding-region'; 5 | import { PreprocessorRegion } from '../scope/regions/preprocessor-region'; 6 | import { SemanticRegion } from '../scope/regions/semantic-region'; 7 | import { SignatureRegion } from '../scope/regions/signature-region'; 8 | 9 | export class DocumentRegions { 10 | public readonly completionRegions = new Array(); 11 | public readonly foldingRegions = new Array(); 12 | public readonly semanticRegions = new Array(); 13 | public readonly colorRegions = new Array(); 14 | public readonly signatureRegions = new Array(); 15 | public readonly forHeaderRegions = new Array(); 16 | public readonly typeDeclarationRegions = new Array(); 17 | public readonly unaryExpressionRegions = new Array(); 18 | public readonly caseHeaderRegions = new Array(); 19 | public readonly caseStatementsRegions = new Array(); 20 | public readonly scopelessInterfaceBlockRegions = new Array(); 21 | public readonly commentRegions = new Array(); 22 | public readonly preprocessorRegions = new Array(); 23 | public readonly layoutRegions = new Array(); 24 | public readonly scopedCurlyBracePositions = new Array(); 25 | public readonly functionParametersRegions = new Array(); 26 | 27 | public reset(): void { 28 | this.completionRegions.length = 0; 29 | this.foldingRegions.length = 0; 30 | this.semanticRegions.length = 0; 31 | this.colorRegions.length = 0; 32 | this.signatureRegions.length = 0; 33 | this.forHeaderRegions.length = 0; 34 | this.typeDeclarationRegions.length = 0; 35 | this.unaryExpressionRegions.length = 0; 36 | this.caseHeaderRegions.length = 0; 37 | this.caseStatementsRegions.length = 0; 38 | this.scopelessInterfaceBlockRegions.length = 0; 39 | this.commentRegions.length = 0; 40 | this.preprocessorRegions.length = 0; 41 | this.layoutRegions.length = 0; 42 | this.scopedCurlyBracePositions.length = 0; 43 | this.functionParametersRegions.length = 0; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/core/glsl-editor.ts: -------------------------------------------------------------------------------- 1 | import { DiagnosticCollection, ExtensionContext, TextDocument, Uri, languages } from 'vscode'; 2 | import { HostDependent } from '../host-dependent'; 3 | import { Configurations } from './configurations'; 4 | import { Constants } from './constants'; 5 | import { DocumentInfo } from './document-info'; 6 | 7 | export class GlslEditor { 8 | public static readonly CONFIGURATIONS = new Configurations(); 9 | 10 | private static readonly documentInfos = new Map(); 11 | private static context: ExtensionContext; 12 | private static readonly collection = languages.createDiagnosticCollection(Constants.GLSL); 13 | 14 | public static initialize(context: ExtensionContext): void { 15 | this.context = context; 16 | } 17 | 18 | public static getContext(): ExtensionContext { 19 | return this.context; 20 | } 21 | 22 | public static processElements(document: TextDocument): void { 23 | const di = this.getDocumentInfo(document.uri); 24 | di.processElements(document); 25 | } 26 | 27 | public static getDocumentInfo(uri: Uri): DocumentInfo { 28 | const key = `${uri.scheme}:${uri.path}`; 29 | let di = this.documentInfos.get(key); 30 | if (!di) { 31 | di = new DocumentInfo(uri); 32 | this.documentInfos.set(key, di); 33 | } 34 | return di; 35 | } 36 | 37 | public static invalidateDocuments(): void { 38 | for (const di of this.documentInfos.values()) { 39 | di.invalidate(); 40 | if (!di.getDocument().isClosed) { 41 | HostDependent.textChanged(di.getDocument()); 42 | } 43 | } 44 | } 45 | 46 | public static getDiagnosticCollection(): DiagnosticCollection { 47 | return this.collection; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/extension-desktop.ts: -------------------------------------------------------------------------------- 1 | import { ExtensionContext, languages, window, workspace } from 'vscode'; 2 | import { Documentation } from './builtin/documentation'; 3 | import { Constants } from './core/constants'; 4 | import { GlslEditor } from './core/glsl-editor'; 5 | import { addSharedCommands, addSharedFeatures, selector, setContext } from './extension'; 6 | import { HostDependent } from './host-dependent'; 7 | import { GlslDiagnosticProvider } from './providers/glsl-diagnostic-provider'; 8 | import { GlslFileDecorationProvider } from './providers/glsl-file-decoration-provider'; 9 | import { GlslInjectionErrorProvider } from './providers/glsl-injection-error-provider'; 10 | import { GlslTextProvider } from './providers/glsl-text-provider'; 11 | 12 | import * as os from 'os'; 13 | 14 | export async function activate(context: ExtensionContext): Promise { 15 | GlslEditor.initialize(context); 16 | await setContext(Constants.CAN_RUN_COMPILER_CONTEXT, canRunCompiler()); 17 | addHostDependentCode(); 18 | addDiagnostic(context); 19 | addSharedCommands(context); 20 | addFeatures(context); 21 | addSharedFeatures(context); 22 | } 23 | 24 | function addHostDependentCode(): void { 25 | HostDependent.getDocumentation = (name, uri) => Documentation.getDocumentation(name, uri); 26 | HostDependent.textChanged = (document) => new GlslDiagnosticProvider().textChanged(document); 27 | HostDependent.displayPreprocessedCode = (document) => 28 | new GlslDiagnosticProvider().displayPreprocessedCode(document); 29 | } 30 | 31 | function addDiagnostic(context: ExtensionContext): void { 32 | if (!canRunCompiler()) { 33 | return; 34 | } 35 | //diagnostic 36 | for (const editor of window.visibleTextEditors) { 37 | if (editor.document.languageId === Constants.GLSL) { 38 | try { 39 | new GlslDiagnosticProvider().textChanged(editor.document); 40 | } catch (error) { 41 | //if i catch the error here, it can't break the activation 42 | } 43 | } 44 | } 45 | context.subscriptions.push( 46 | workspace.onDidOpenTextDocument((event) => { 47 | if (event.languageId === Constants.GLSL) { 48 | new GlslDiagnosticProvider().textChanged(event); 49 | } 50 | }) 51 | ); 52 | context.subscriptions.push( 53 | workspace.onDidCloseTextDocument((event) => { 54 | if (event.languageId === Constants.GLSL) { 55 | GlslEditor.getDiagnosticCollection().delete(event.uri); 56 | } 57 | }) 58 | ); 59 | context.subscriptions.push( 60 | workspace.onDidChangeTextDocument((event) => { 61 | if (event.document.languageId === Constants.GLSL) { 62 | new GlslDiagnosticProvider().textChanged(event.document); 63 | } 64 | }) 65 | ); 66 | context.subscriptions.push(languages.registerCodeLensProvider(selector, new GlslInjectionErrorProvider())); 67 | } 68 | 69 | function addFeatures(context: ExtensionContext): void { 70 | //preprocessed glsl 71 | context.subscriptions.push( 72 | workspace.registerTextDocumentContentProvider(Constants.PREPROCESSED_GLSL, new GlslTextProvider()) 73 | ); 74 | window.registerFileDecorationProvider(new GlslFileDecorationProvider()); 75 | } 76 | 77 | export function canRunCompiler(): boolean { 78 | const platform = os.platform(); 79 | return (platform === 'win32' || platform === 'darwin' || platform === 'linux') && os.arch() === 'x64'; 80 | } 81 | -------------------------------------------------------------------------------- /src/extension-web.ts: -------------------------------------------------------------------------------- 1 | import { ExtensionContext } from 'vscode'; 2 | import { Constants } from './core/constants'; 3 | import { GlslEditor } from './core/glsl-editor'; 4 | import { addSharedCommands, addSharedFeatures, setContext } from './extension'; 5 | import { HostDependent } from './host-dependent'; 6 | 7 | export async function activate(context: ExtensionContext): Promise { 8 | GlslEditor.initialize(context); 9 | HostDependent.webExtension = true; 10 | await setContext(Constants.CAN_RUN_COMPILER_CONTEXT, false); 11 | addSharedCommands(context); 12 | addSharedFeatures(context); 13 | } 14 | -------------------------------------------------------------------------------- /src/host-dependent.ts: -------------------------------------------------------------------------------- 1 | import { TextDocument, Uri } from 'vscode'; 2 | 3 | export class HostDependent { 4 | public static webExtension = false; 5 | 6 | public static getDocumentation(name: string, uri: Uri): string { 7 | return ''; 8 | } 9 | 10 | public static displayPreprocessedCode(document: TextDocument): void {} 11 | 12 | public static textChanged(document: TextDocument): void {} 13 | } 14 | -------------------------------------------------------------------------------- /src/processor/expression-result.ts: -------------------------------------------------------------------------------- 1 | import { ArrayUsage } from '../scope/array-usage'; 2 | import { FunctionCall } from '../scope/function/function-call'; 3 | import { TypeDeclaration } from '../scope/type/type-declaration'; 4 | 5 | export class ExpressionResult { 6 | public readonly type: TypeDeclaration; 7 | public readonly array: ArrayUsage; 8 | public readonly constant: boolean; 9 | public readonly value: number; 10 | public readonly numberLiteral: boolean; 11 | public readonly colorVariable: boolean; 12 | public readonly constructorCall: FunctionCall; 13 | public readonly constructorParameters: Array; 14 | 15 | public constructor( 16 | type: TypeDeclaration, 17 | array = new ArrayUsage(), 18 | constant = false, 19 | value: number = null, 20 | floatLiteral = false, 21 | colorVariable = false, 22 | constructorCall: FunctionCall = null, 23 | constructorParameters = new Array() 24 | ) { 25 | this.type = type; 26 | this.array = array; 27 | this.constant = constant; 28 | this.value = value; 29 | this.numberLiteral = floatLiteral; 30 | this.colorVariable = colorVariable; 31 | this.constructorCall = constructorCall; 32 | this.constructorParameters = constructorParameters; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/processor/variable-usage-processor.ts: -------------------------------------------------------------------------------- 1 | import { Token } from 'antlr4ts'; 2 | import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; 3 | import { DocumentInfo } from '../core/document-info'; 4 | import { SemanticModifier, SemanticRegion, SemanticType } from '../scope/regions/semantic-region'; 5 | import { Scope } from '../scope/scope'; 6 | import { VariableDeclaration } from '../scope/variable/variable-declaration'; 7 | import { VariableUsage } from '../scope/variable/variable-usage'; 8 | import { Helper } from './helper'; 9 | import { VariableDeclarationProcessor } from './variable-declaration-processor'; 10 | 11 | export class VariableUsageProcessor { 12 | private di: DocumentInfo; 13 | 14 | public getVariableUsage(identifier: TerminalNode, scope: Scope, di: DocumentInfo): VariableUsage { 15 | this.di = di; 16 | const interval = Helper.getIntervalFromTerminalNode(identifier, di); 17 | const name = identifier.text; 18 | const vd = VariableDeclarationProcessor.searchVariableDeclaration(name, interval, scope, di); 19 | const vu = new VariableUsage(name, scope, interval, vd); 20 | if (vd) { 21 | scope.variableUsages.push(vu); 22 | vd.usages.push(vu); 23 | this.addSemanticToken(vd, identifier.symbol); 24 | } 25 | return vu; 26 | } 27 | 28 | private addSemanticToken(vd: VariableDeclaration, token: Token): void { 29 | if (vd.name && !vd.builtin) { 30 | const modifiers = []; 31 | if (vd.type.qualifiers.some((q) => q.name === 'const')) { 32 | modifiers.push(SemanticModifier.CONST); 33 | } 34 | const sr = new SemanticRegion(token, SemanticType.VARIABLE, modifiers); 35 | this.di.getRegions().semanticRegions.push(sr); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/providers/glsl-command-provider.ts: -------------------------------------------------------------------------------- 1 | import { Disposable, Uri, ViewColumn, WebviewPanel, env, window } from 'vscode'; 2 | import { GlslEditor } from '../core/glsl-editor'; 3 | import { HostDependent } from '../host-dependent'; 4 | 5 | export class GlslCommandProvider { 6 | public static readonly OPEN_DOCS_GL = 'opendocsgl'; 7 | public static readonly OPEN_GL_ES_2 = 'opengles2'; 8 | public static readonly OPEN_GL_ES_3 = 'opengles3'; 9 | public static readonly OPEN_DOC = 'opendoc'; 10 | public static readonly GENERATE_PREPROCESSED = 'generatepreprocessed'; 11 | 12 | private static panel: WebviewPanel; 13 | private static isPanelUsable = false; 14 | private static panelEventHandler: Disposable; 15 | 16 | public static openDocsGl(): void { 17 | env.openExternal(Uri.parse('http://docs.gl')); 18 | } 19 | 20 | public static openGlEs2(): void { 21 | env.openExternal(Uri.parse('https://www.khronos.org/registry/OpenGL-Refpages/es2.0')); 22 | } 23 | 24 | public static openGlEs3(): void { 25 | env.openExternal(Uri.parse('https://www.khronos.org/registry/OpenGL-Refpages/es3.0')); 26 | } 27 | 28 | public static openDoc(name: string): void { 29 | if (HostDependent.webExtension || GlslEditor.CONFIGURATIONS.getAlwaysOpenOnlineDoc()) { 30 | env.openExternal(Uri.parse(`http://docs.gl/el3/${name}`)); 31 | } else { 32 | this.openOfflineDoc(name); 33 | } 34 | } 35 | 36 | public static openPreprocessedGlsl(): void { 37 | const doc = window.activeTextEditor.document; 38 | HostDependent.displayPreprocessedCode(doc); 39 | } 40 | 41 | private static openOfflineDoc(name: string): void { 42 | if (!this.panel || !this.isPanelUsable || GlslEditor.CONFIGURATIONS.getAlwaysOpenOfflineDocInNewTab()) { 43 | this.panel = this.createPanel(name); 44 | } 45 | this.panel.title = name; 46 | const filePath = Uri.file(`${GlslEditor.getContext().extensionPath}/res/js/mml-chtml.js`); 47 | const specialFilePath = this.panel.webview.asWebviewUri(filePath); 48 | this.panel.webview.html = HostDependent.getDocumentation(name, specialFilePath); 49 | } 50 | 51 | private static createPanel(name: string): WebviewPanel { 52 | const panel = window.createWebviewPanel('documentation', name, ViewColumn.Beside, { 53 | enableScripts: true, 54 | enableCommandUris: true, 55 | localResourceRoots: [Uri.file(`${GlslEditor.getContext().extensionPath}/res/js`)], 56 | }); 57 | 58 | this.panelEventHandler?.dispose(); 59 | this.isPanelUsable = true; 60 | this.panelEventHandler = panel.onDidDispose(() => { 61 | this.isPanelUsable = false; 62 | }); 63 | 64 | return panel; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/providers/glsl-declaration-provider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | Declaration, 4 | DeclarationProvider, 5 | Location, 6 | Position, 7 | ProviderResult, 8 | TextDocument, 9 | } from 'vscode'; 10 | import { FunctionCall } from '../scope/function/function-call'; 11 | import { FunctionDeclaration } from '../scope/function/function-declaration'; 12 | import { LogicalFunction } from '../scope/function/logical-function'; 13 | import { TypeDeclaration } from '../scope/type/type-declaration'; 14 | import { TypeUsage } from '../scope/type/type-usage'; 15 | import { VariableDeclaration } from '../scope/variable/variable-declaration'; 16 | import { VariableUsage } from '../scope/variable/variable-usage'; 17 | import { PositionalProviderBase } from './helper/positional-provider-base'; 18 | 19 | export class GlslDeclarationProvider extends PositionalProviderBase implements DeclarationProvider { 20 | public provideDeclaration( 21 | document: TextDocument, 22 | position: Position, 23 | token: CancellationToken 24 | ): ProviderResult { 25 | return this.processElements(document, position); 26 | } 27 | 28 | protected processFunctionPrototype(fp: FunctionDeclaration): Declaration { 29 | return this.processFunction(fp.logicalFunction); 30 | } 31 | 32 | protected processFunctionDefinition(fd: FunctionDeclaration): Declaration { 33 | return this.processFunction(fd.logicalFunction); 34 | } 35 | 36 | protected processFunctionCall(fc: FunctionCall): Declaration { 37 | return this.processFunction(fc.logicalFunction); 38 | } 39 | 40 | protected processVariableDeclaration(vd: VariableDeclaration): Declaration { 41 | if (!vd.nameInterval.isInjected()) { 42 | return this.di.intervalToLocation(vd.nameInterval); 43 | } 44 | return null; 45 | } 46 | 47 | protected processVariableUsage(vu: VariableUsage): Declaration { 48 | return this.processUsage(vu); 49 | } 50 | 51 | protected processTypeDeclaration(td: TypeDeclaration): Declaration { 52 | if (!td.nameInterval.isInjected()) { 53 | return this.di.intervalToLocation(td.nameInterval); 54 | } 55 | return null; 56 | } 57 | 58 | protected processTypeUsage(tu: TypeUsage): Declaration { 59 | return this.processUsage(tu); 60 | } 61 | 62 | private processFunction(lf: LogicalFunction): Declaration { 63 | const ret = new Array(); 64 | if (!lf.getDeclaration().builtIn) { 65 | if (lf.getDeclaration().ctor) { 66 | return this.processTypeDeclaration(lf.getDeclaration().returnType.declaration); 67 | } else { 68 | for (const fp of lf.prototypes) { 69 | this.addLocation(ret, fp.nameInterval); 70 | } 71 | } 72 | } 73 | return ret; 74 | } 75 | 76 | private processUsage(element: VariableUsage | TypeUsage): Declaration { 77 | const declaration = element.declaration; 78 | if (declaration && !declaration.builtin && !declaration.nameInterval.isInjected()) { 79 | return this.di.intervalToLocation(declaration.nameInterval); 80 | } 81 | return null; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/providers/glsl-definition-provider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | DefinitionProvider, 4 | Location, 5 | LocationLink, 6 | Position, 7 | ProviderResult, 8 | TextDocument, 9 | } from 'vscode'; 10 | import { FunctionCall } from '../scope/function/function-call'; 11 | import { FunctionDeclaration } from '../scope/function/function-declaration'; 12 | import { LogicalFunction } from '../scope/function/logical-function'; 13 | import { TypeDeclaration } from '../scope/type/type-declaration'; 14 | import { TypeUsage } from '../scope/type/type-usage'; 15 | import { VariableDeclaration } from '../scope/variable/variable-declaration'; 16 | import { VariableUsage } from '../scope/variable/variable-usage'; 17 | import { PositionalProviderBase } from './helper/positional-provider-base'; 18 | 19 | export class GlslDefinitionProvider 20 | extends PositionalProviderBase> 21 | implements DefinitionProvider 22 | { 23 | public provideDefinition( 24 | document: TextDocument, 25 | position: Position, 26 | token: CancellationToken 27 | ): ProviderResult { 28 | return this.processElements(document, position); 29 | } 30 | 31 | protected processFunctionPrototype(fp: FunctionDeclaration): Array | Location { 32 | return this.processFunction(fp.logicalFunction); 33 | } 34 | 35 | protected processFunctionDefinition(fd: FunctionDeclaration): Array | Location { 36 | return this.processFunction(fd.logicalFunction); 37 | } 38 | 39 | protected processFunctionCall(fc: FunctionCall): Array | Location { 40 | return this.processFunction(fc.logicalFunction); 41 | } 42 | 43 | protected processVariableDeclaration(vd: VariableDeclaration): Location { 44 | if (!vd.nameInterval.isInjected()) { 45 | return this.di.intervalToLocation(vd.nameInterval); 46 | } 47 | return null; 48 | } 49 | 50 | protected processVariableUsage(vu: VariableUsage): Location { 51 | return this.processUsage(vu); 52 | } 53 | 54 | protected processTypeDeclaration(td: TypeDeclaration): Location { 55 | if (!td.nameInterval.isInjected()) { 56 | return this.di.intervalToLocation(td.nameInterval); 57 | } 58 | return null; 59 | } 60 | 61 | protected processTypeUsage(tu: TypeUsage): Location { 62 | return this.processUsage(tu); 63 | } 64 | 65 | private processFunction(lf: LogicalFunction): Array | Location { 66 | const ret = new Array(); 67 | if (!lf.getDeclaration().builtIn && !lf.getDeclaration().ctor) { 68 | for (const fd of lf.definitions) { 69 | this.addLocation(ret, fd.nameInterval); 70 | } 71 | } 72 | return ret; 73 | } 74 | 75 | private processUsage(element: TypeUsage | VariableUsage): Location { 76 | const declaration = element.declaration; 77 | if (declaration && !declaration.builtin && !declaration.nameInterval.isInjected()) { 78 | return this.di.intervalToLocation(declaration.nameInterval); 79 | } 80 | return null; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/providers/glsl-document-highlight-provider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | DocumentHighlight, 4 | DocumentHighlightKind, 5 | DocumentHighlightProvider, 6 | Position, 7 | ProviderResult, 8 | TextDocument, 9 | } from 'vscode'; 10 | import { Element } from '../scope/element'; 11 | import { FunctionCall } from '../scope/function/function-call'; 12 | import { FunctionDeclaration } from '../scope/function/function-declaration'; 13 | import { LogicalFunction } from '../scope/function/logical-function'; 14 | import { TypeDeclaration } from '../scope/type/type-declaration'; 15 | import { TypeUsage } from '../scope/type/type-usage'; 16 | import { VariableDeclaration } from '../scope/variable/variable-declaration'; 17 | import { VariableUsage } from '../scope/variable/variable-usage'; 18 | import { PositionalProviderBase } from './helper/positional-provider-base'; 19 | 20 | export class GlslDocumentHighlightProvider 21 | extends PositionalProviderBase> 22 | implements DocumentHighlightProvider 23 | { 24 | public provideDocumentHighlights( 25 | document: TextDocument, 26 | position: Position, 27 | token: CancellationToken 28 | ): ProviderResult { 29 | return this.processElements(document, position); 30 | } 31 | 32 | protected processFunctionPrototype(fp: FunctionDeclaration): Array { 33 | return this.processFunction(fp.logicalFunction); 34 | } 35 | 36 | protected processFunctionDefinition(fd: FunctionDeclaration): Array { 37 | return this.processFunction(fd.logicalFunction); 38 | } 39 | 40 | protected processFunctionCall(fc: FunctionCall): Array { 41 | return this.processFunction(fc.logicalFunction); 42 | } 43 | 44 | protected processVariableDeclaration(vd: VariableDeclaration): Array { 45 | return this.processDeclaration(vd); 46 | } 47 | 48 | protected processVariableUsage(vu: VariableUsage): Array { 49 | return this.processUsage(vu); 50 | } 51 | 52 | protected processTypeDeclaration(td: TypeDeclaration): Array { 53 | return this.processDeclaration(td); 54 | } 55 | 56 | protected processTypeUsage(tu: TypeUsage): Array { 57 | return this.processUsage(tu); 58 | } 59 | 60 | private processFunction(lf: LogicalFunction): Array { 61 | const ret = new Array(); 62 | if (!lf.getDeclaration().builtIn && !lf.getDeclaration().ctor) { 63 | this.addHighlight(ret, lf.prototypes, DocumentHighlightKind.Write); 64 | this.addHighlight(ret, lf.definitions, DocumentHighlightKind.Read); 65 | } 66 | this.addHighlight(ret, lf.calls, DocumentHighlightKind.Text); 67 | return ret; 68 | } 69 | 70 | private processDeclaration(element: VariableDeclaration | TypeDeclaration): Array { 71 | const ret = new Array(); 72 | if (!(element instanceof TypeDeclaration && (element.interfaceBlock || element.builtin))) { 73 | if (!element.builtin && !element.nameInterval.isInjected()) { 74 | const range = this.di.intervalToRange(element.nameInterval); 75 | ret.push(new DocumentHighlight(range, DocumentHighlightKind.Read)); 76 | } 77 | this.addHighlight(ret, element.usages, DocumentHighlightKind.Text); 78 | } 79 | return ret; 80 | } 81 | 82 | private processUsage(element: VariableUsage | TypeUsage): Array { 83 | if (element.declaration) { 84 | return this.processDeclaration(element.declaration); 85 | } else if (element.name !== 'void') { 86 | const range = this.di.intervalToRange(element.nameInterval); 87 | return new Array(new DocumentHighlight(range, DocumentHighlightKind.Text)); 88 | } else { 89 | return null; 90 | } 91 | } 92 | 93 | private addHighlight(ret: Array, elements: Array, dhk: DocumentHighlightKind): void { 94 | for (const element of elements) { 95 | if (element.nameInterval && !element.nameInterval.isInjected()) { 96 | const range = this.di.intervalToRange(element.nameInterval); 97 | ret.push(new DocumentHighlight(range, dhk)); 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/providers/glsl-document-semantic-token-provider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | DocumentSemanticTokensProvider, 4 | ProviderResult, 5 | Range, 6 | SemanticTokens, 7 | SemanticTokensBuilder, 8 | SemanticTokensLegend, 9 | TextDocument, 10 | } from 'vscode'; 11 | import { DocumentInfo } from '../core/document-info'; 12 | import { GlslEditor } from '../core/glsl-editor'; 13 | import { SemanticRegion } from '../scope/regions/semantic-region'; 14 | 15 | export class GlslDocumentSemanticTokensProvider implements DocumentSemanticTokensProvider { 16 | private di: DocumentInfo; 17 | private result: SemanticTokensBuilder; 18 | 19 | private initialize(document: TextDocument): void { 20 | GlslEditor.processElements(document); 21 | this.di = GlslEditor.getDocumentInfo(document.uri); 22 | const legend = new GlslSemanticTokensLegend(); 23 | this.result = new SemanticTokensBuilder(legend); 24 | } 25 | 26 | public provideDocumentSemanticTokens( 27 | document: TextDocument, 28 | token: CancellationToken 29 | ): ProviderResult { 30 | this.initialize(document); 31 | for (const sr of this.di.getRegions().semanticRegions) { 32 | this.addSemanticToken(sr); 33 | } 34 | return this.result.build(); 35 | } 36 | 37 | private addSemanticToken(sr: SemanticRegion): void { 38 | const realLine = sr.token.line - this.di.getInjectionLineCount(); 39 | if (realLine >= 0) { 40 | const p1 = this.di.offsetToPosition(sr.token.startIndex - this.di.getInjectionOffset()); 41 | const p2 = this.di.offsetToPosition(sr.token.stopIndex - this.di.getInjectionOffset() + 1); 42 | const range = new Range(p1, p2); 43 | this.result.push(range, sr.type, sr.modifiers); 44 | } 45 | } 46 | } 47 | 48 | export class GlslSemanticTokensLegend implements SemanticTokensLegend { 49 | public readonly tokenTypes = [ 50 | 'type', //user type 51 | 'struct', //builtin type 52 | 'function', 53 | 'variable', 54 | ]; 55 | public readonly tokenModifiers = ['declaration', 'definition', 'readonly']; 56 | } 57 | -------------------------------------------------------------------------------- /src/providers/glsl-document-symbol-provider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | DocumentSymbol, 4 | DocumentSymbolProvider, 5 | ProviderResult, 6 | Range, 7 | SymbolInformation, 8 | SymbolKind, 9 | TextDocument, 10 | } from 'vscode'; 11 | import { DocumentInfo } from '../core/document-info'; 12 | import { GlslEditor } from '../core/glsl-editor'; 13 | import { FunctionDeclaration } from '../scope/function/function-declaration'; 14 | import { Interval } from '../scope/interval'; 15 | import { Scope } from '../scope/scope'; 16 | import { TypeDeclaration } from '../scope/type/type-declaration'; 17 | import { VariableDeclaration } from '../scope/variable/variable-declaration'; 18 | 19 | export class GlslDocumentSymbolProvider implements DocumentSymbolProvider { 20 | private di: DocumentInfo; 21 | private result: Array; 22 | 23 | private initialize(document: TextDocument): void { 24 | GlslEditor.processElements(document); 25 | this.di = GlslEditor.getDocumentInfo(document.uri); 26 | this.result = new Array(); 27 | } 28 | 29 | public provideDocumentSymbols( 30 | document: TextDocument, 31 | token: CancellationToken 32 | ): ProviderResult { 33 | this.initialize(document); 34 | for (const td of this.di.getRootScope().typeDeclarations) { 35 | if (!td.interval.isInjected()) { 36 | this.addStruct(td, null); 37 | } 38 | } 39 | for (const vd of this.di.getRootScope().variableDeclarations) { 40 | if (!vd.declarationInterval.isInjected()) { 41 | this.addVariable(vd, null, false); 42 | } 43 | } 44 | for (const fd of this.di.getRootScope().functionDefinitions) { 45 | if (!fd.interval.isInjected()) { 46 | this.addFunction(fd); 47 | } 48 | } 49 | return this.result; 50 | } 51 | 52 | private addFunction(fd: FunctionDeclaration): void { 53 | const range = this.di.intervalToRange(fd.interval); 54 | const selectionRange = this.di.intervalToRange(fd.nameInterval); 55 | const type = fd.returnType.toStringWithoutQualifiers(); 56 | const ds = new DocumentSymbol(fd.name, type, SymbolKind.Function, range, selectionRange); 57 | this.addLocalElements(ds, fd, fd.functionScope); 58 | this.result.push(ds); 59 | } 60 | 61 | private addStruct(td: TypeDeclaration, parent: DocumentSymbol): void { 62 | const range = this.di.intervalToRange(td.interval); 63 | const selectionRange = this.getRange(td.nameInterval, td.interval); 64 | const name = td.toStringName(true); 65 | const kind = td.interfaceBlock ? SymbolKind.Interface : SymbolKind.Struct; 66 | const ds = new DocumentSymbol(name, null, kind, range, selectionRange); 67 | for (const vd of td.members) { 68 | this.addVariable(vd, ds, true); 69 | } 70 | if (parent) { 71 | parent.children.push(ds); 72 | } else { 73 | this.result.push(ds); 74 | } 75 | } 76 | 77 | private addVariable(vd: VariableDeclaration, parent: DocumentSymbol, property: boolean): void { 78 | const range = this.di.intervalToRange(vd.declarationInterval); 79 | const selectionRange = this.getRange(vd.nameInterval, vd.declarationInterval); 80 | const name = vd.name ?? ''; 81 | let info = vd.type.toStringWithoutQualifiers(true); 82 | info = vd.functionDefinitionParameter ? info + ' (parameter)' : info; 83 | const sk = this.getSymbolKind(vd, property); 84 | const ds = new DocumentSymbol(name, info, sk, range, selectionRange); 85 | if (parent) { 86 | parent.children.push(ds); 87 | } else { 88 | this.result.push(ds); 89 | } 90 | } 91 | 92 | private getSymbolKind(vd: VariableDeclaration, property: boolean): SymbolKind { 93 | if (property) { 94 | return SymbolKind.Property; 95 | } 96 | return vd.scope.parent ? SymbolKind.Variable : SymbolKind.Field; 97 | } 98 | 99 | private addLocalElements(ds: DocumentSymbol, fd: FunctionDeclaration, scope: Scope): void { 100 | for (const td of scope.typeDeclarations) { 101 | this.addStruct(td, ds); 102 | } 103 | for (const vd of scope.variableDeclarations) { 104 | this.addVariable(vd, ds, false); 105 | } 106 | for (const childScope of scope.children) { 107 | this.addLocalElements(ds, fd, childScope); 108 | } 109 | } 110 | 111 | private getRange(interval: Interval, defaultInterval: Interval): Range { 112 | const availableInterval = interval ?? defaultInterval; 113 | return this.di.intervalToRange(availableInterval); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/providers/glsl-file-decoration-provider.ts: -------------------------------------------------------------------------------- 1 | import { CancellationToken, FileDecoration, FileDecorationProvider, ProviderResult, Uri } from 'vscode'; 2 | import { Constants } from '../core/constants'; 3 | 4 | export class GlslFileDecorationProvider implements FileDecorationProvider { 5 | public provideFileDecoration(uri: Uri, token: CancellationToken): ProviderResult { 6 | if (uri.scheme === Constants.PREPROCESSED_GLSL) { 7 | const fd = new FileDecoration(); 8 | fd.tooltip = 'This is the read-only view of the preprocessed GLSL source code.'; 9 | fd.badge = 'P'; 10 | return fd; 11 | } else { 12 | return null; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/providers/glsl-folding-provider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | FoldingContext, 4 | FoldingRange, 5 | FoldingRangeProvider, 6 | ProviderResult, 7 | TextDocument, 8 | } from 'vscode'; 9 | 10 | import { GlslEditor } from '../core/glsl-editor'; 11 | 12 | export class GlslFoldingProvider implements FoldingRangeProvider { 13 | public provideFoldingRanges( 14 | document: TextDocument, 15 | context: FoldingContext, 16 | token: CancellationToken 17 | ): ProviderResult { 18 | GlslEditor.processElements(document); 19 | const di = GlslEditor.getDocumentInfo(document.uri); 20 | const results = new Array(); 21 | for (const fr of di.getRegions().foldingRegions) { 22 | results.push(new FoldingRange(fr.startLine, fr.stopLine, fr.kind)); 23 | } 24 | return results; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/providers/glsl-hover-provider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | Hover, 4 | HoverProvider, 5 | MarkdownString, 6 | Position, 7 | ProviderResult, 8 | TextDocument, 9 | } from 'vscode'; 10 | import { Constants } from '../core/constants'; 11 | import { Helper } from '../processor/helper'; 12 | import { FunctionCall } from '../scope/function/function-call'; 13 | import { TypeCategory } from '../scope/type/type-category'; 14 | import { TypeUsage } from '../scope/type/type-usage'; 15 | import { VariableUsage } from '../scope/variable/variable-usage'; 16 | import { PositionalProviderBase } from './helper/positional-provider-base'; 17 | 18 | export class GlslHoverProvider extends PositionalProviderBase implements HoverProvider { 19 | public provideHover(document: TextDocument, position: Position, token: CancellationToken): ProviderResult { 20 | return this.processElements(document, position); 21 | } 22 | 23 | protected processFunctionCall(fc: FunctionCall): Hover { 24 | const fd = fc.logicalFunction?.getDeclaration(); 25 | if (fd && Helper.isInCorrectStage(fd.stage, this.di)) { 26 | const fi = this.di.builtin.functionSummaries.get(fd.name); 27 | const md = new MarkdownString(fd.toStringDocumentation()); 28 | if (fi && fi.summary) { 29 | md.appendText(Constants.NEW_LINE); 30 | md.appendMarkdown(fi.summary.value); 31 | md.isTrusted = true; 32 | } 33 | return new Hover(md); 34 | } 35 | return null; 36 | } 37 | 38 | protected processVariableUsage(vu: VariableUsage): Hover { 39 | if (vu.declaration && Helper.isInCorrectStage(vu.declaration.stage, this.di)) { 40 | if (vu.declaration.summary) { 41 | return new Hover(vu.declaration.summary); 42 | } else { 43 | const md = new MarkdownString(vu.declaration.toStringDocumentation()); 44 | return new Hover(md); 45 | } 46 | } 47 | return null; 48 | } 49 | 50 | protected processTypeUsage(tu: TypeUsage): Hover { 51 | if (tu.declaration && tu.declaration.typeCategory === TypeCategory.CUSTOM && !tu.declaration.interfaceBlock) { 52 | const md = new MarkdownString(tu.declaration.toStringDocumentation()); 53 | return new Hover(md); 54 | } 55 | return null; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/providers/glsl-implementation-provider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | ImplementationProvider, 4 | Location, 5 | LocationLink, 6 | Position, 7 | ProviderResult, 8 | TextDocument, 9 | } from 'vscode'; 10 | import { FunctionCall } from '../scope/function/function-call'; 11 | import { FunctionDeclaration } from '../scope/function/function-declaration'; 12 | import { LogicalFunction } from '../scope/function/logical-function'; 13 | import { PositionalProviderBase } from './helper/positional-provider-base'; 14 | 15 | export class GlslImplementationProvider 16 | extends PositionalProviderBase> 17 | implements ImplementationProvider 18 | { 19 | public provideImplementation( 20 | document: TextDocument, 21 | position: Position, 22 | token: CancellationToken 23 | ): ProviderResult { 24 | return this.processElements(document, position); 25 | } 26 | 27 | protected processFunctionPrototype(fp: FunctionDeclaration): Array { 28 | return this.processFunction(fp.logicalFunction); 29 | } 30 | 31 | protected processFunctionDefinition(fd: FunctionDeclaration): Array { 32 | return this.processFunction(fd.logicalFunction); 33 | } 34 | 35 | protected processFunctionCall(fc: FunctionCall): Array { 36 | return this.processFunction(fc.logicalFunction); 37 | } 38 | 39 | private processFunction(lf: LogicalFunction): Array { 40 | const ret = new Array(); 41 | if (!lf.getDeclaration().builtIn) { 42 | for (const fd of lf.definitions) { 43 | this.addLocation(ret, fd.nameInterval); 44 | } 45 | } 46 | return ret; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/providers/glsl-injection-error-provider.ts: -------------------------------------------------------------------------------- 1 | import { CancellationToken, CodeLens, CodeLensProvider, ProviderResult, TextDocument } from 'vscode'; 2 | import { GlslEditor } from '../core/glsl-editor'; 3 | 4 | export class GlslInjectionErrorProvider implements CodeLensProvider { 5 | public provideCodeLenses(document: TextDocument, token: CancellationToken): ProviderResult { 6 | GlslEditor.processElements(document); 7 | const di = GlslEditor.getDocumentInfo(document.uri); 8 | if (di.hasInjectionError()) { 9 | const range = document.lineAt(0).range; 10 | const cl = new CodeLens(range, { 11 | title: 'The injected code contains errors.', 12 | command: null, 13 | arguments: null, 14 | tooltip: '', 15 | }); 16 | return [cl]; 17 | } else { 18 | return []; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/providers/glsl-inlay-hints-provider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | InlayHint, 4 | InlayHintKind, 5 | InlayHintLabelPart, 6 | InlayHintsProvider, 7 | MarkdownString, 8 | ProviderResult, 9 | Range, 10 | TextDocument, 11 | } from 'vscode'; 12 | import { DocumentInfo } from '../core/document-info'; 13 | import { GlslEditor } from '../core/glsl-editor'; 14 | import { FunctionCall } from '../scope/function/function-call'; 15 | import { FunctionDeclaration } from '../scope/function/function-declaration'; 16 | import { Scope } from '../scope/scope'; 17 | 18 | export class GlslInlayHintsProvider implements InlayHintsProvider { 19 | private di: DocumentInfo; 20 | private range: Range; 21 | private result: Array; 22 | 23 | private initialize(document: TextDocument, range: Range): void { 24 | GlslEditor.processElements(document); 25 | this.range = range; 26 | this.di = GlslEditor.getDocumentInfo(document.uri); 27 | this.result = new Array(); 28 | } 29 | 30 | public provideInlayHints( 31 | document: TextDocument, 32 | range: Range, 33 | token: CancellationToken 34 | ): ProviderResult { 35 | this.initialize(document, range); 36 | this.addHintsFromScope(this.di.getRootScope()); 37 | return this.result; 38 | } 39 | 40 | private addHintsFromScope(scope: Scope): void { 41 | for (const fc of scope.functionCalls) { 42 | this.addHintsFromFunctionCall(fc); 43 | } 44 | for (const childScope of scope.children) { 45 | this.addHintsFromScope(childScope); 46 | } 47 | } 48 | 49 | private addHintsFromFunctionCall(fc: FunctionCall): void { 50 | if (this.isInsideTheRegion(fc) && fc.logicalFunction) { 51 | const declaration = fc.logicalFunction.getDeclaration(); 52 | for (let i = 0; i < fc.parametersStartOffset.length && i < declaration.parameters.length; i++) { 53 | this.addHint(fc, declaration, i); 54 | } 55 | } 56 | } 57 | 58 | private isInsideTheRegion(fc: FunctionCall): boolean { 59 | const start = this.di.offsetToPosition(fc.interval.startIndex); 60 | const stop = this.di.offsetToPosition(fc.interval.stopIndex); 61 | const functionCallRange = new Range(start, stop); 62 | return !!functionCallRange.intersection(this.range); 63 | } 64 | 65 | private addHint(fc: FunctionCall, declaration: FunctionDeclaration, i: number): void { 66 | const startIndex = fc.parametersStartOffset[i]; 67 | const position = this.di.offsetToPosition(startIndex - this.di.getInjectionOffset()); 68 | const label = this.createLabel(declaration, i); 69 | const ih = new InlayHint(position, label, InlayHintKind.Parameter); 70 | ih.paddingRight = true; 71 | this.result.push(ih); 72 | } 73 | 74 | private createLabel(declaration: FunctionDeclaration, i: number): string | InlayHintLabelPart[] { 75 | const parameter = declaration.parameters[i]; 76 | const name = `${parameter.name}:`; 77 | if (declaration.builtIn) { 78 | return name; 79 | } else { 80 | return [ 81 | { 82 | value: name, 83 | tooltip: new MarkdownString(parameter.toStringDocumentation()), 84 | location: this.di.intervalToLocation(parameter.nameInterval), 85 | }, 86 | ]; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/providers/glsl-reference-provider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | Location, 4 | Position, 5 | ProviderResult, 6 | ReferenceContext, 7 | ReferenceProvider, 8 | TextDocument, 9 | } from 'vscode'; 10 | import { FunctionCall } from '../scope/function/function-call'; 11 | import { FunctionDeclaration } from '../scope/function/function-declaration'; 12 | import { LogicalFunction } from '../scope/function/logical-function'; 13 | import { TypeDeclaration } from '../scope/type/type-declaration'; 14 | import { TypeUsage } from '../scope/type/type-usage'; 15 | import { VariableDeclaration } from '../scope/variable/variable-declaration'; 16 | import { VariableUsage } from '../scope/variable/variable-usage'; 17 | import { PositionalProviderBase } from './helper/positional-provider-base'; 18 | 19 | export class GlslReferenceProvider extends PositionalProviderBase> implements ReferenceProvider { 20 | private referenceContext: ReferenceContext; 21 | 22 | public provideReferences( 23 | document: TextDocument, 24 | position: Position, 25 | context: ReferenceContext, 26 | token: CancellationToken 27 | ): ProviderResult { 28 | this.referenceContext = context; 29 | return this.processElements(document, position); 30 | } 31 | 32 | protected processFunctionPrototype(fp: FunctionDeclaration): Array { 33 | return this.processFunction(fp.logicalFunction); 34 | } 35 | 36 | protected processFunctionDefinition(fd: FunctionDeclaration): Array { 37 | return this.processFunction(fd.logicalFunction); 38 | } 39 | 40 | protected processFunctionCall(fc: FunctionCall): Array { 41 | return this.processFunction(fc.logicalFunction); 42 | } 43 | 44 | protected processVariableDeclaration(vd: VariableDeclaration): Array { 45 | return this.processDeclaration(vd); 46 | } 47 | 48 | protected processVariableUsage(vu: VariableUsage): Array { 49 | return this.processUsage(vu); 50 | } 51 | 52 | protected processTypeDeclaration(td: TypeDeclaration): Array { 53 | return this.processDeclaration(td); 54 | } 55 | 56 | protected processTypeUsage(tu: TypeUsage): Array { 57 | return this.processUsage(tu); 58 | } 59 | 60 | private processFunction(lf: LogicalFunction): Array { 61 | const ret = new Array(); 62 | if (!lf.getDeclaration().builtIn && !lf.getDeclaration().ctor) { 63 | for (const fp of lf.prototypes) { 64 | this.addLocation(ret, fp.nameInterval); 65 | } 66 | for (const fd of lf.definitions) { 67 | this.addLocation(ret, fd.nameInterval); 68 | } 69 | } 70 | for (const fc of lf.calls) { 71 | this.addLocation(ret, fc.nameInterval); 72 | } 73 | return ret; 74 | } 75 | 76 | private processDeclaration(element: TypeDeclaration | VariableDeclaration): Array { 77 | const ret = new Array(); 78 | if (!element.builtin && this.referenceContext.includeDeclaration) { 79 | this.addLocation(ret, element.nameInterval); 80 | } 81 | for (const usage of element.usages) { 82 | this.addLocation(ret, usage.nameInterval); 83 | } 84 | return ret; 85 | } 86 | 87 | private processUsage(element: TypeUsage | VariableUsage): Array { 88 | const declaration = element.declaration; 89 | if (declaration) { 90 | return this.processDeclaration(declaration); 91 | } else { 92 | return []; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/providers/glsl-text-provider.ts: -------------------------------------------------------------------------------- 1 | import { CancellationToken, EventEmitter, ProviderResult, TextDocumentContentProvider, Uri } from 'vscode'; 2 | import { GlslEditor } from '../core/glsl-editor'; 3 | 4 | export class GlslTextProvider implements TextDocumentContentProvider { 5 | public static onDidChangeEmitter = new EventEmitter(); 6 | public onDidChange = GlslTextProvider.onDidChangeEmitter.event; 7 | 8 | public provideTextDocumentContent(uri: Uri, token: CancellationToken): ProviderResult { 9 | return GlslEditor.getDocumentInfo(uri).getPreprocessedText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/providers/glsl-type-definition-provider.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | Location, 4 | LocationLink, 5 | Position, 6 | ProviderResult, 7 | TextDocument, 8 | TypeDefinitionProvider, 9 | } from 'vscode'; 10 | import { TypeDeclarationProcessor } from '../processor/type-declaration-processor'; 11 | import { FunctionCall } from '../scope/function/function-call'; 12 | import { VariableDeclaration } from '../scope/variable/variable-declaration'; 13 | import { VariableUsage } from '../scope/variable/variable-usage'; 14 | import { PositionalProviderBase } from './helper/positional-provider-base'; 15 | 16 | export class GlslTypeDefinitionProvider extends PositionalProviderBase implements TypeDefinitionProvider { 17 | public provideTypeDefinition( 18 | document: TextDocument, 19 | position: Position, 20 | token: CancellationToken 21 | ): ProviderResult { 22 | return this.processElements(document, position); 23 | } 24 | 25 | protected processFunctionCall(fc: FunctionCall): Location { 26 | const scope = this.di.getScopeAt(this.position); 27 | const td = TypeDeclarationProcessor.searchTypeDeclaration(fc.name, fc.nameInterval, scope, this.di); 28 | if (td && !td.builtin && !td.nameInterval.isInjected()) { 29 | return this.di.intervalToLocation(td.nameInterval); 30 | } 31 | return null; 32 | } 33 | 34 | protected processVariableDeclaration(vd: VariableDeclaration): Location { 35 | const td = vd.type.declaration; 36 | if (td && !td.builtin) { 37 | if (td.nameInterval && !td.nameInterval.isInjected()) { 38 | return this.di.intervalToLocation(td.nameInterval); 39 | } else { 40 | return this.di.intervalToLocation(td.interval); 41 | } 42 | } 43 | return null; 44 | } 45 | 46 | protected processVariableUsage(vu: VariableUsage): Location { 47 | const vd = vu.declaration; 48 | return vd ? this.processVariableDeclaration(vd) : null; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/providers/helper/debug-highlighter.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CancellationToken, 3 | DocumentHighlight, 4 | DocumentHighlightProvider, 5 | Position, 6 | ProviderResult, 7 | TextDocument, 8 | } from 'vscode'; 9 | import { DocumentInfo } from '../../core/document-info'; 10 | import { GlslEditor } from '../../core/glsl-editor'; 11 | 12 | export class DebugHighlighter implements DocumentHighlightProvider { 13 | protected di: DocumentInfo; 14 | protected document: TextDocument; 15 | protected position: Position; 16 | 17 | protected initialize(document: TextDocument, position: Position): void { 18 | GlslEditor.processElements(document); 19 | this.di = GlslEditor.getDocumentInfo(document.uri); 20 | this.document = document; 21 | this.position = position; 22 | } 23 | 24 | public provideDocumentHighlights( 25 | document: TextDocument, 26 | position: Position, 27 | token: CancellationToken 28 | ): ProviderResult { 29 | this.initialize(document, position); 30 | //return this.scopeHighlights(); 31 | //return this.regionHighlight('scopelessInterfaceBlockRegions'); 32 | return this.regionHighlight('forHeaderRegions'); 33 | } 34 | 35 | private scopeHighlights(): Array { 36 | const scope = this.di.getScopeAt(this.position); 37 | return [new DocumentHighlight(this.di.intervalToRange(scope.interval))]; 38 | } 39 | 40 | private regionHighlight(region: string): Array { 41 | const result = new Array(); 42 | const offset = this.di.positionToOffset(this.position); 43 | for (const interval of this.di[region]) { 44 | if (interval.startIndex <= offset && interval.stopIndex >= offset) { 45 | result.push(new DocumentHighlight(this.di.intervalToRange(interval))); 46 | } 47 | } 48 | return result; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/providers/helper/formatting-context.ts: -------------------------------------------------------------------------------- 1 | import { Constants } from '../../core/constants'; 2 | 3 | export class FormattingContext { 4 | lastt1TokenIndex = Constants.INVALID; 5 | lastt2TokenIndex = Constants.INVALID; 6 | t1NewLine = false; 7 | t2NewLineCount = 0; 8 | 9 | currentTokenIndex = 0; 10 | 11 | firstNewLineIndex = Constants.INVALID; 12 | lastNewLineIndex = Constants.INVALID; 13 | 14 | forHeader: boolean; 15 | forHeaderEnd: boolean; 16 | typeDeclaration: boolean; 17 | unaryExpression: boolean; 18 | caseHeader: boolean; 19 | caseStatementsStart: boolean; 20 | scopelessInterfaceBlock: boolean; 21 | inlineStruct: boolean; 22 | functionParameters: boolean; 23 | } 24 | -------------------------------------------------------------------------------- /src/providers/helper/hierarchy-element.ts: -------------------------------------------------------------------------------- 1 | import { CallHierarchyIncomingCall, CallHierarchyItem, CallHierarchyOutgoingCall, Range } from 'vscode'; 2 | import { LogicalFunction } from '../../scope/function/logical-function'; 3 | 4 | export class HierarchyElement { 5 | private item: CallHierarchyItem; 6 | private logicalFunction: LogicalFunction; 7 | private ranges = new Array(); 8 | 9 | public constructor(item: CallHierarchyItem, logicalFunction: LogicalFunction) { 10 | this.item = item; 11 | this.logicalFunction = logicalFunction; 12 | } 13 | 14 | public getItem(): CallHierarchyItem { 15 | return this.item; 16 | } 17 | 18 | public getLogicalFunction(): LogicalFunction { 19 | return this.logicalFunction; 20 | } 21 | 22 | public getRanges(): Array { 23 | return this.ranges; 24 | } 25 | 26 | public toIncomingCall(): CallHierarchyIncomingCall { 27 | return new CallHierarchyIncomingCall(this.item, this.ranges); 28 | } 29 | 30 | public toOutgoingCall(): CallHierarchyOutgoingCall { 31 | return new CallHierarchyOutgoingCall(this.item, this.ranges); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/providers/helper/hierarchy-search-stage.ts: -------------------------------------------------------------------------------- 1 | export enum HierarcySearchStage { 2 | PREPARE, 3 | INCOMING, 4 | OUTGOING, 5 | } 6 | -------------------------------------------------------------------------------- /src/providers/helper/positional-provider-base.ts: -------------------------------------------------------------------------------- 1 | import { Location, Position, TextDocument } from 'vscode'; 2 | import { DocumentInfo } from '../../core/document-info'; 3 | import { GlslEditor } from '../../core/glsl-editor'; 4 | import { FunctionCall } from '../../scope/function/function-call'; 5 | import { FunctionDeclaration } from '../../scope/function/function-declaration'; 6 | import { Interval } from '../../scope/interval'; 7 | import { TypeDeclaration } from '../../scope/type/type-declaration'; 8 | import { TypeUsage } from '../../scope/type/type-usage'; 9 | import { VariableDeclaration } from '../../scope/variable/variable-declaration'; 10 | import { VariableUsage } from '../../scope/variable/variable-usage'; 11 | 12 | export class PositionalProviderBase { 13 | protected di: DocumentInfo; 14 | protected document: TextDocument; 15 | protected position: Position; 16 | protected offset: number; 17 | 18 | protected initialize(document: TextDocument, position: Position): void { 19 | GlslEditor.processElements(document); 20 | this.di = GlslEditor.getDocumentInfo(document.uri); 21 | this.document = document; 22 | this.position = position; 23 | this.offset = this.di.positionToOffset(this.position); 24 | } 25 | 26 | protected processElements(document: TextDocument, position: Position): T { 27 | this.initialize(document, position); 28 | 29 | //function 30 | const fp = this.di.getFunctionPrototypeAt(position); 31 | if (fp && !fp.ctor && this.di.isExtensionAvailable(fp.extension, this.offset)) { 32 | return this.processFunctionPrototype(fp); 33 | } 34 | 35 | const fd = this.di.getFunctionDefinitionAt(position); 36 | if (fd && !fd.ctor && this.di.isExtensionAvailable(fd.extension, this.offset)) { 37 | return this.processFunctionDefinition(fd); 38 | } 39 | 40 | const fc = this.di.getFunctionCallAt(position); 41 | if ( 42 | fc && 43 | (fc.logicalFunction.prototypes.length === 0 || 44 | this.di.isExtensionAvailable(fc.logicalFunction.getDeclaration().extension, this.offset)) 45 | ) { 46 | return this.processFunctionCall(fc); 47 | } 48 | 49 | //variable 50 | const vd = this.di.getVariableDeclarationAt(position); 51 | if (vd && vd.name && this.di.isExtensionAvailable(vd.extension, this.offset)) { 52 | return this.processVariableDeclaration(vd); 53 | } 54 | 55 | const vu = this.di.getVariableUsageAt(position); 56 | if (vu && vu.name && (!vu.declaration || this.di.isExtensionAvailable(vu.declaration.extension, this.offset))) { 57 | return this.processVariableUsage(vu); 58 | } 59 | 60 | //type 61 | const td = this.di.getTypeDeclarationAt(position); 62 | if (td && td.name) { 63 | return this.processTypeDeclaration(td); 64 | } 65 | 66 | const tu = this.di.getTypeUsageAt(position); 67 | if (tu && tu.name) { 68 | return this.processTypeUsage(tu); 69 | } 70 | 71 | return this.defaultReturn(); 72 | } 73 | 74 | protected processFunctionPrototype(fp: FunctionDeclaration): T { 75 | return null; 76 | } 77 | 78 | protected processFunctionDefinition(fd: FunctionDeclaration): T { 79 | return null; 80 | } 81 | 82 | protected processFunctionCall(fc: FunctionCall): T { 83 | return null; 84 | } 85 | 86 | protected processVariableDeclaration(vd: VariableDeclaration): T { 87 | return null; 88 | } 89 | 90 | protected processVariableUsage(vu: VariableUsage): T { 91 | return null; 92 | } 93 | 94 | protected processTypeDeclaration(td: TypeDeclaration): T { 95 | return null; 96 | } 97 | 98 | protected processTypeUsage(tu: TypeUsage): T { 99 | return null; 100 | } 101 | 102 | protected defaultReturn(): T { 103 | return null; 104 | } 105 | 106 | protected addLocation(list: Array, interval: Interval): void { 107 | if (interval && !interval.isInjected()) { 108 | list.push(this.di.intervalToLocation(interval)); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/providers/helper/preprocessor-completion-context.ts: -------------------------------------------------------------------------------- 1 | export class PreprocessorCompletionContext { 2 | public readonly nextWordIndex: number; 3 | public readonly words: Array; 4 | 5 | public constructor(nextWordIndex: number, words: Array) { 6 | this.nextWordIndex = nextWordIndex; 7 | this.words = words; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/scope/array-usage.ts: -------------------------------------------------------------------------------- 1 | import { Constants } from '../core/constants'; 2 | import { Interval } from './interval'; 3 | 4 | export class ArrayUsage { 5 | public readonly arraySize: number; 6 | public readonly interval: Interval; 7 | public readonly multidimensional: boolean; 8 | 9 | public constructor(arraySize = Constants.INVALID, interval = null, multidimensional = false) { 10 | this.arraySize = arraySize; 11 | this.interval = interval; 12 | this.multidimensional = multidimensional; 13 | } 14 | 15 | public isArray(): boolean { 16 | return this.arraySize !== Constants.INVALID; 17 | } 18 | 19 | public isUndefinedSize(): boolean { 20 | return this.arraySize === 0; 21 | } 22 | 23 | public mergeArrays(au: ArrayUsage): ArrayUsage { 24 | if (!au || (this.isArray() && !au.isArray())) { 25 | return this; 26 | } else if (!this.isArray() && au.isArray()) { 27 | return au; 28 | } else if (!this.isArray() && !au.isArray()) { 29 | return new ArrayUsage(); 30 | } else { 31 | return new ArrayUsage(this.arraySize, this.interval, true); 32 | } 33 | } 34 | 35 | public specifyArraySize(arraySize: number): ArrayUsage { 36 | if (arraySize <= 0 || this.arraySize > 0) { 37 | return this; 38 | } else { 39 | return new ArrayUsage(arraySize, this.interval, this.multidimensional); 40 | } 41 | } 42 | 43 | public toString(): string { 44 | if (!this.isArray()) { 45 | return Constants.EMPTY; 46 | } else if (this.isUndefinedSize()) { 47 | return '[]'; 48 | } else { 49 | return `[${this.arraySize}]`; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/scope/element.ts: -------------------------------------------------------------------------------- 1 | import { DocumentInfo } from '../core/document-info'; 2 | import { Interval } from './interval'; 3 | import { Scope } from './scope'; 4 | 5 | export abstract class Element { 6 | public readonly nameInterval: Interval; 7 | public readonly name: string; 8 | public readonly scope: Scope; 9 | 10 | public constructor(name: string, nameInterval: Interval, scope: Scope) { 11 | this.name = name; 12 | this.nameInterval = nameInterval; 13 | this.scope = scope; 14 | } 15 | 16 | public isDuplicateOf(element: Element, di: DocumentInfo): boolean { 17 | return element && this.name === element.name && element !== this; 18 | } 19 | 20 | public toString(): string { 21 | return this.name; 22 | } 23 | 24 | public toStringDocumentation(): string { 25 | return `\t${this.toString()};`; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/scope/function/function-call.ts: -------------------------------------------------------------------------------- 1 | import { Element } from '../element'; 2 | import { Interval } from '../interval'; 3 | import { Scope } from '../scope'; 4 | import { FunctionDeclaration } from './function-declaration'; 5 | import { LogicalFunction } from './logical-function'; 6 | 7 | export class FunctionCall extends Element { 8 | public readonly logicalFunction: LogicalFunction; 9 | public readonly interval: Interval; 10 | public readonly builtin: boolean; 11 | public readonly incomingCall: FunctionDeclaration; 12 | public readonly parametersStartOffset = new Array(); 13 | 14 | public constructor( 15 | name: string, 16 | nameInterval: Interval, 17 | scope: Scope, 18 | interval: Interval, 19 | logicalFunction: LogicalFunction, 20 | builtin: boolean, 21 | incomingCall: FunctionDeclaration 22 | ) { 23 | super(name, nameInterval, scope); 24 | this.logicalFunction = logicalFunction; 25 | this.interval = interval; 26 | this.builtin = builtin; 27 | this.incomingCall = incomingCall; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/scope/function/function-declaration.ts: -------------------------------------------------------------------------------- 1 | import { Constants } from '../../core/constants'; 2 | import { DocumentInfo } from '../../core/document-info'; 3 | import { Element } from '../element'; 4 | import { Interval } from '../interval'; 5 | import { Scope } from '../scope'; 6 | import { ShaderStage } from '../shader-stage'; 7 | import { TypeUsage } from '../type/type-usage'; 8 | import { VariableDeclaration } from '../variable/variable-declaration'; 9 | import { FunctionCall } from './function-call'; 10 | import { LogicalFunction } from './logical-function'; 11 | 12 | export class FunctionDeclaration extends Element { 13 | public logicalFunction: LogicalFunction; 14 | public readonly interval: Interval; 15 | public readonly returnType: TypeUsage; 16 | public readonly parameters = new Array(); 17 | public readonly builtIn: boolean; 18 | public readonly ctor: boolean; 19 | public readonly functionScope: Scope; 20 | public readonly stage: ShaderStage; 21 | public readonly outgoingCalls = new Array(); 22 | public readonly extension: string; 23 | 24 | public constructor( 25 | name: string, 26 | nameInterval: Interval, 27 | scope: Scope, 28 | returnType: TypeUsage, 29 | builtIn: boolean, 30 | ctor: boolean, 31 | interval: Interval, 32 | functionScope: Scope, 33 | stage = ShaderStage.DEFAULT, 34 | extension = '' 35 | ) { 36 | super(name, nameInterval, scope); 37 | this.interval = interval; 38 | this.returnType = returnType; 39 | this.builtIn = builtIn; 40 | this.ctor = ctor; 41 | this.functionScope = functionScope; 42 | this.stage = stage; 43 | this.extension = extension; 44 | } 45 | 46 | public isConnectableWith(fd: FunctionDeclaration): boolean { 47 | if (!fd || this.name !== fd.name || this.parameters.length !== fd.parameters.length) { 48 | return false; 49 | } 50 | return this.areParametersConnectableWith(fd); 51 | } 52 | 53 | public areParametersConnectableWith(fd: FunctionDeclaration): boolean { 54 | for (let i = 0; i < this.parameters.length; i++) { 55 | const vd = this.parameters[i]; 56 | const vd2 = fd.parameters[i]; 57 | if ( 58 | !vd.type.declaration || 59 | !vd2.type.declaration || 60 | vd.type.declaration !== vd2.type.declaration || 61 | !vd.type.areArrayDimensionsMatch(vd2.type) 62 | ) { 63 | return false; 64 | } 65 | } 66 | return true; 67 | } 68 | 69 | public isDuplicateOf(element: Element, di: DocumentInfo): boolean { 70 | if (element instanceof FunctionDeclaration) { 71 | const fd = element; 72 | const prototypes = this.logicalFunction.prototypes; 73 | const definitions = this.logicalFunction.definitions; 74 | return ( 75 | element !== this && 76 | ((definitions.includes(fd) && definitions.includes(this)) || 77 | (di.isGlsl100es() && prototypes.includes(fd) && prototypes.includes(this))) 78 | ); 79 | } 80 | return super.isDuplicateOf(element, di); 81 | } 82 | 83 | // 84 | //toString 85 | // 86 | public toStringSignature(showParameters: boolean): string { 87 | const arrayCtor = 88 | this.returnType.array.isArray && this.ctor ? this.returnType.array.toString() : Constants.EMPTY; 89 | let ret = this.name + arrayCtor + Constants.LRB; 90 | if (showParameters) { 91 | ret += this.toStringParameters(); 92 | } 93 | ret += Constants.RRB; 94 | return ret; 95 | } 96 | 97 | public toStringParameters(): string { 98 | let ret = Constants.EMPTY; 99 | for (let i = 0; i < this.parameters.length; i++) { 100 | ret += this.toStringParameter(i); 101 | } 102 | return ret; 103 | } 104 | 105 | private toStringParameter(index: number): string { 106 | let ret = this.parameters[index].toString(); 107 | if (index !== this.parameters.length - 1) { 108 | ret += ', '; 109 | } 110 | return ret; 111 | } 112 | 113 | public toString(): string { 114 | if (this.ctor) { 115 | return this.toStringSignature(true); 116 | } else { 117 | return this.returnType + Constants.SPACE + this.toStringSignature(true); 118 | } 119 | } 120 | 121 | public toStringDocumentation(): string { 122 | return `\t${this.toString()};`; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/scope/function/function-info.ts: -------------------------------------------------------------------------------- 1 | import { MarkdownString } from 'vscode'; 2 | import { ShaderStage } from '../shader-stage'; 3 | 4 | export class FunctionInfo { 5 | public readonly name: string; 6 | public readonly summary: MarkdownString; 7 | public readonly stage: ShaderStage; 8 | public readonly ctor: boolean; 9 | public readonly parameters = new Map(); 10 | public readonly extension: string; 11 | 12 | public constructor(name: string, summary: MarkdownString, stage: ShaderStage, ctor: boolean, extension: string) { 13 | this.name = name; 14 | this.summary = summary; 15 | this.stage = stage; 16 | this.ctor = ctor; 17 | this.extension = extension; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/scope/function/logical-function.ts: -------------------------------------------------------------------------------- 1 | import { FunctionCall } from './function-call'; 2 | import { FunctionDeclaration } from './function-declaration'; 3 | 4 | export class LogicalFunction { 5 | public readonly prototypes = new Array(); 6 | public readonly calls = new Array(); 7 | public readonly definitions = new Array(); 8 | 9 | public connects(fd: FunctionDeclaration): boolean { 10 | return this.getDeclaration().isConnectableWith(fd); 11 | } 12 | 13 | public getDeclaration(): FunctionDeclaration { 14 | if (this.prototypes.length) { 15 | return this.prototypes[0]; 16 | } else if (this.definitions.length) { 17 | return this.definitions[0]; 18 | } else { 19 | return null; 20 | } 21 | } 22 | 23 | public hasDeclaration(): boolean { 24 | return this.prototypes.length !== 0 || this.definitions.length !== 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/scope/interval.ts: -------------------------------------------------------------------------------- 1 | import { DocumentInfo } from '../core/document-info'; 2 | 3 | export class Interval { 4 | private readonly _startIndex: number; 5 | private readonly _stopIndex: number; 6 | 7 | public constructor(startIndex: number, stopIndex: number, di: DocumentInfo) { 8 | this._startIndex = startIndex - di.getInjectionOffset(); 9 | this._stopIndex = stopIndex - di.getInjectionOffset(); 10 | } 11 | 12 | public get startIndex(): number { 13 | return this._startIndex; 14 | } 15 | 16 | public get stopIndex(): number { 17 | return this._stopIndex; 18 | } 19 | 20 | public isInjected(): boolean { 21 | return this.startIndex < 0; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/scope/keyword.ts: -------------------------------------------------------------------------------- 1 | import { ShaderStage } from './shader-stage'; 2 | 3 | export class Keyword { 4 | public readonly name: string; 5 | public readonly stage: ShaderStage; 6 | 7 | public constructor(name: string, stage: ShaderStage) { 8 | this.name = name; 9 | this.stage = stage; 10 | } 11 | 12 | public toString(): string { 13 | return this.name; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/scope/qualifier/layout-parameter.ts: -------------------------------------------------------------------------------- 1 | export class LayoutParameter { 2 | public readonly name: string; 3 | public readonly assignable: boolean; 4 | public readonly extension: string; 5 | 6 | public constructor(name: string, assignable: boolean, extension: string) { 7 | this.name = name; 8 | this.assignable = assignable; 9 | this.extension = extension; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/scope/qualifier/qualifier-usage.ts: -------------------------------------------------------------------------------- 1 | import { Element } from '../element'; 2 | import { Interval } from '../interval'; 3 | import { Scope } from '../scope'; 4 | import { Qualifier } from './qualifier'; 5 | 6 | export class QualifierUsage extends Element { 7 | public readonly qualifier: Qualifier; 8 | 9 | public constructor(name: string, nameInterval: Interval, scope: Scope, qualifier: Qualifier) { 10 | super(name, nameInterval, scope); 11 | this.qualifier = qualifier; 12 | } 13 | 14 | public isConstQualifier(): boolean { 15 | return this.qualifier && this.qualifier.isConstQualifier(); 16 | } 17 | 18 | public isParameterQualifier(): boolean { 19 | return this.qualifier && this.qualifier.isParameterQualifier(); 20 | } 21 | 22 | public isPrecisionQualifier(): boolean { 23 | return this.qualifier && this.qualifier.isPrecisionQualifier(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/scope/qualifier/qualifier.ts: -------------------------------------------------------------------------------- 1 | import { DocumentInfo } from '../../core/document-info'; 2 | import { QualifierUsage } from './qualifier-usage'; 3 | 4 | export class Qualifier { 5 | public readonly name: string; 6 | public readonly order: number; 7 | public readonly usages = new Array(); 8 | 9 | public constructor(name: string, order: number) { 10 | this.name = name; 11 | this.order = order; 12 | } 13 | 14 | public isConstQualifier(): boolean { 15 | return this.name === 'const'; 16 | } 17 | 18 | public isParameterQualifier(): boolean { 19 | return this.name === 'in' || this.name === 'out' || this.name === 'inout'; 20 | } 21 | 22 | public isPrecisionQualifier(): boolean { 23 | return this.name === 'lowp' || this.name === 'mediump' || this.name === 'highp'; 24 | } 25 | 26 | public isCompatibleWith(qualifier: Qualifier, di: DocumentInfo): boolean { 27 | if (this === qualifier) { 28 | return false; 29 | } 30 | return this.isCompatibleWithUnsafe(qualifier, di); 31 | } 32 | 33 | private isCompatibleWithUnsafe(qualifier: Qualifier, di: DocumentInfo): boolean { 34 | for (const qs of di.builtin.qualifierRules) { 35 | if (qs.has(this) && qs.has(qualifier)) { 36 | return false; 37 | } 38 | } 39 | return true; 40 | } 41 | 42 | public toString(): string { 43 | return this.name; 44 | } 45 | 46 | public toStringDocumentation(): string { 47 | return `\t${this.toString()}`; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/scope/regions/color-region.ts: -------------------------------------------------------------------------------- 1 | import { FunctionCall } from '../function/function-call'; 2 | 3 | export class ColorRegion { 4 | public readonly constructorCall: FunctionCall; 5 | public readonly parameters: Array; 6 | 7 | public constructor(constructorCall: FunctionCall, parameters: Array) { 8 | this.constructorCall = constructorCall; 9 | this.parameters = parameters; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/scope/regions/completion-region.ts: -------------------------------------------------------------------------------- 1 | import { Interval } from '../interval'; 2 | import { TypeUsage } from '../type/type-usage'; 3 | 4 | export class CompletionRegion { 5 | public readonly type: TypeUsage; 6 | public readonly interval: Interval; 7 | public readonly text: string; 8 | 9 | public constructor(tu: TypeUsage, interval: Interval, text: string) { 10 | this.type = tu; 11 | this.interval = interval; 12 | this.text = text; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/scope/regions/folding-region.ts: -------------------------------------------------------------------------------- 1 | import { FoldingRangeKind } from 'vscode'; 2 | 3 | export class FoldingRegion { 4 | public readonly startLine: number; 5 | public readonly stopLine: number; 6 | public readonly kind: FoldingRangeKind; 7 | 8 | public constructor(startLine: number, stopLine: number, kind = FoldingRangeKind.Region) { 9 | this.startLine = startLine; 10 | this.stopLine = stopLine; 11 | this.kind = kind; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/scope/regions/preprocessor-region.ts: -------------------------------------------------------------------------------- 1 | import { Interval } from '../interval'; 2 | 3 | export class PreprocessorRegion { 4 | public readonly text: string; 5 | public readonly interval: Interval; 6 | public readonly extension: string; 7 | public readonly extensionState: string; 8 | 9 | public constructor(text: string, interval: Interval, extension: string, extensionState: string) { 10 | this.text = text; 11 | this.interval = interval; 12 | this.extension = extension; 13 | this.extensionState = extensionState; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/scope/regions/semantic-region.ts: -------------------------------------------------------------------------------- 1 | import { Token } from 'antlr4ts'; 2 | 3 | export class SemanticRegion { 4 | public readonly token: Token; 5 | public readonly type: SemanticType; 6 | public readonly modifiers: Array; 7 | 8 | public constructor(token: Token, type: SemanticType, modifiers = new Array()) { 9 | this.token = token; 10 | this.type = type; 11 | this.modifiers = modifiers; 12 | } 13 | } 14 | 15 | export enum SemanticType { 16 | USER_TYPE = 'type', 17 | BUILTIN_TYPE = 'struct', 18 | FUNCTION = 'function', 19 | VARIABLE = 'variable', 20 | } 21 | 22 | export enum SemanticModifier { 23 | DECLARATION = 'declaration', 24 | DEFINITION = 'definition', 25 | CONST = 'readonly', 26 | } 27 | -------------------------------------------------------------------------------- /src/scope/regions/signature-parameter-region.ts: -------------------------------------------------------------------------------- 1 | import { ArrayUsage } from '../array-usage'; 2 | import { Interval } from '../interval'; 3 | import { TypeDeclaration } from '../type/type-declaration'; 4 | 5 | export class SignatureParameterRegion { 6 | public readonly typeDeclaration: TypeDeclaration; 7 | public readonly array: ArrayUsage; 8 | public readonly interval: Interval; 9 | 10 | public constructor(typeDeclaration: TypeDeclaration, array: ArrayUsage, interval: Interval) { 11 | this.typeDeclaration = typeDeclaration; 12 | this.array = array; 13 | this.interval = interval; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/scope/regions/signature-region.ts: -------------------------------------------------------------------------------- 1 | import { Interval } from '../interval'; 2 | import { SignatureParameterRegion } from './signature-parameter-region'; 3 | 4 | export class SignatureRegion { 5 | public readonly name: string; 6 | public readonly interval: Interval; 7 | public readonly parameters = new Array(); 8 | 9 | public constructor(name: string, interval: Interval) { 10 | this.name = name; 11 | this.interval = interval; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/scope/scope.ts: -------------------------------------------------------------------------------- 1 | import { FunctionCall } from './function/function-call'; 2 | import { FunctionDeclaration } from './function/function-declaration'; 3 | import { LogicalFunction } from './function/logical-function'; 4 | import { Interval } from './interval'; 5 | import { TypeDeclaration } from './type/type-declaration'; 6 | import { TypeUsage } from './type/type-usage'; 7 | import { VariableDeclaration } from './variable/variable-declaration'; 8 | import { VariableUsage } from './variable/variable-usage'; 9 | 10 | export class Scope { 11 | public readonly parent: Scope; 12 | public readonly children = new Array(); 13 | public readonly interval: Interval; 14 | 15 | public readonly functions = new Array(); 16 | public readonly functionPrototypes = new Array(); 17 | public readonly functionDefinitions = new Array(); 18 | public readonly functionCalls = new Array(); 19 | 20 | public readonly variableDeclarations = new Array(); 21 | public readonly variableUsages = new Array(); 22 | 23 | public readonly typeDeclarations = new Array(); 24 | public readonly typeUsages = new Array(); 25 | 26 | public readonly elseIfScope: boolean; 27 | 28 | public constructor(interval: Interval, parent: Scope, elseIfScope = false) { 29 | this.interval = interval; 30 | this.parent = parent; 31 | this.elseIfScope = elseIfScope; 32 | } 33 | 34 | public isGlobal(): boolean { 35 | return !this.parent; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/scope/shader-stage.ts: -------------------------------------------------------------------------------- 1 | export enum ShaderStage { 2 | DEFAULT, 3 | VERTEX, 4 | FRAGMENT, 5 | } 6 | -------------------------------------------------------------------------------- /src/scope/type/type-base.ts: -------------------------------------------------------------------------------- 1 | export enum TypeBase { 2 | BOOL, 3 | INT, 4 | UINT, 5 | FLOAT, 6 | NONE, 7 | } 8 | -------------------------------------------------------------------------------- /src/scope/type/type-category.ts: -------------------------------------------------------------------------------- 1 | export enum TypeCategory { 2 | CUSTOM, 3 | TRANSPARENT, 4 | FLOATING_POINT_OPAQUE, 5 | SIGNED_INTEGER_OPAQUE, 6 | UNSIGNED_INTEGER_OPAQUE, 7 | } 8 | -------------------------------------------------------------------------------- /src/scope/type/type-declaration.ts: -------------------------------------------------------------------------------- 1 | import { Constants } from '../../core/constants'; 2 | import { Element } from '../element'; 3 | import { FunctionCall } from '../function/function-call'; 4 | import { Interval } from '../interval'; 5 | import { Scope } from '../scope'; 6 | import { VariableDeclaration } from '../variable/variable-declaration'; 7 | import { TypeBase } from './type-base'; 8 | import { TypeCategory } from './type-category'; 9 | import { TypeUsage } from './type-usage'; 10 | 11 | export class TypeDeclaration extends Element { 12 | public readonly builtin: boolean; 13 | public readonly interval: Interval; 14 | public readonly typeBase: TypeBase; 15 | public readonly typeCategory: TypeCategory; 16 | public readonly width: number; 17 | public readonly height: number; 18 | public readonly interfaceBlock: boolean; 19 | public readonly members = new Array(); 20 | public readonly interfaceMembers = new Array(); 21 | public readonly usages = new Array(); 22 | public readonly ctorCalls = new Array(); 23 | public readonly inline: boolean; 24 | 25 | public constructor( 26 | name: string, 27 | nameInterval: Interval, 28 | scope: Scope, 29 | builtIn: boolean, 30 | interval: Interval, 31 | width: number, 32 | height: number, 33 | typeBase: TypeBase, 34 | typeCategory = TypeCategory.CUSTOM, 35 | interfaceBlock = false, 36 | inline = false 37 | ) { 38 | super(name, nameInterval, scope); 39 | this.builtin = builtIn; 40 | this.interval = interval; 41 | this.width = width; 42 | this.height = height; 43 | this.typeBase = typeBase; 44 | this.typeCategory = typeCategory; 45 | this.interfaceBlock = interfaceBlock; 46 | this.inline = inline; 47 | } 48 | 49 | public isScalar(): boolean { 50 | return this.width === 1 && this.height === 1; 51 | } 52 | 53 | public isVector(): boolean { 54 | return this.width > 1 && this.height === 1; 55 | } 56 | 57 | public isMatrix(): boolean { 58 | return this.width > 1 && this.height > 1; 59 | } 60 | 61 | public isOpaque(): boolean { 62 | return ( 63 | this.typeCategory === TypeCategory.FLOATING_POINT_OPAQUE || 64 | this.typeCategory === TypeCategory.SIGNED_INTEGER_OPAQUE || 65 | this.typeCategory === TypeCategory.UNSIGNED_INTEGER_OPAQUE 66 | ); 67 | } 68 | 69 | public toStringName(toOutline = false): string { 70 | if (this.name) { 71 | return this.name; 72 | } else { 73 | if (toOutline) { 74 | return this.interfaceBlock ? '' : ''; 75 | } else { 76 | return this.interfaceBlock ? 'uniform {...}' : 'struct {...}'; 77 | } 78 | } 79 | } 80 | 81 | public toString(): string { 82 | let result = `struct ${this.name} {`; 83 | for (const vd of this.members) { 84 | result += `${vd.toString()};`; 85 | } 86 | result += '};'; 87 | return result; 88 | } 89 | 90 | public toStringDocumentation(): string { 91 | let result = `\tstruct ${this.name} {${Constants.NEW_LINE}`; 92 | for (const vd of this.members) { 93 | result += `\t\t${vd.toString()};${Constants.NEW_LINE}`; 94 | } 95 | result += '\t};'; 96 | return result; 97 | } 98 | 99 | public toStringConstructorParameters(): string { 100 | let ret = Constants.EMPTY; 101 | for (let i = 0; i < this.members.length; i++) { 102 | ret += this.members[i].toString(); 103 | if (i !== this.members.length - 1) { 104 | ret += ', '; 105 | } 106 | } 107 | return ret; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/scope/type/type-usage.ts: -------------------------------------------------------------------------------- 1 | import { Constants } from '../../core/constants'; 2 | import { ArrayUsage } from '../array-usage'; 3 | import { Element } from '../element'; 4 | import { Interval } from '../interval'; 5 | import { Qualifier } from '../qualifier/qualifier'; 6 | import { QualifierUsage } from '../qualifier/qualifier-usage'; 7 | import { Scope } from '../scope'; 8 | import { TypeDeclaration } from './type-declaration'; 9 | 10 | export class TypeUsage extends Element { 11 | public readonly declaration: TypeDeclaration; 12 | public readonly qualifiers = new Array(); 13 | public readonly implicitQualifiers = new Array(); 14 | public readonly interval: Interval; 15 | public readonly array: ArrayUsage; 16 | public readonly inlineStructDeclaration: boolean; 17 | 18 | public constructor( 19 | name: string, 20 | interval: Interval, 21 | nameInterval: Interval, 22 | scope: Scope, 23 | declaration: TypeDeclaration, 24 | array: ArrayUsage, 25 | inlineStructDeclaration = false 26 | ) { 27 | super(name, nameInterval, scope); 28 | this.declaration = declaration; 29 | this.interval = interval; 30 | this.array = array; 31 | this.inlineStructDeclaration = inlineStructDeclaration; 32 | } 33 | 34 | public isVoid(): boolean { 35 | return this.name === 'void'; 36 | } 37 | 38 | public areArrayDimensionsMatch(tu: TypeUsage): boolean { 39 | return ( 40 | tu && 41 | this.array.arraySize === tu.array.arraySize && 42 | this.array.multidimensional === tu.array.multidimensional 43 | ); 44 | } 45 | 46 | public qualifiersEqualsExceptPrecisionWith(tu: TypeUsage): boolean { 47 | if (!tu) { 48 | return false; 49 | } 50 | return this.qualifiersEqualsExceptPrecisionWithHalf(tu) && tu.qualifiersEqualsExceptPrecisionWithHalf(this); 51 | } 52 | 53 | private qualifiersEqualsExceptPrecisionWithHalf(tu: TypeUsage): boolean { 54 | for (const qu of this.qualifiers) { 55 | if ( 56 | !qu.qualifier.isPrecisionQualifier() && 57 | !tu.containsQualifier(qu.qualifier) && 58 | !tu.implicitQualifiers.includes(qu.qualifier) 59 | ) { 60 | return false; 61 | } 62 | } 63 | for (const q of this.implicitQualifiers) { 64 | if (!q.isPrecisionQualifier() && !tu.containsQualifier(q) && !tu.implicitQualifiers.includes(q)) { 65 | return false; 66 | } 67 | } 68 | return true; 69 | } 70 | 71 | public containsQualifier(q: Qualifier): boolean { 72 | for (const qu of this.qualifiers) { 73 | if (qu.qualifier === q) { 74 | return true; 75 | } 76 | } 77 | return false; 78 | } 79 | 80 | // 81 | //toString 82 | // 83 | public toString(): string { 84 | let qualifiers = Constants.EMPTY; 85 | for (let i = 0; i < this.qualifiers.length; i++) { 86 | qualifiers += this.qualifiers[i].toString() + Constants.SPACE; 87 | } 88 | return qualifiers + this.toStringWithoutQualifiers(); 89 | } 90 | 91 | public toStringName(toOutline = false): string { 92 | if (this.name) { 93 | return this.name; 94 | } else { 95 | return this.declaration ? this.declaration.toStringName(toOutline) : Constants.EMPTY; 96 | } 97 | } 98 | 99 | public toStringWithoutQualifiers(toOutline = false): string { 100 | return this.toStringName(toOutline) + this.array.toString(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/scope/variable/variable-declaration.ts: -------------------------------------------------------------------------------- 1 | import { MarkdownString } from 'vscode'; 2 | import { Constants } from '../../core/constants'; 3 | import { Element } from '../element'; 4 | import { Interval } from '../interval'; 5 | import { Scope } from '../scope'; 6 | import { ShaderStage } from '../shader-stage'; 7 | import { TypeUsage } from '../type/type-usage'; 8 | import { VariableUsage } from './variable-usage'; 9 | 10 | export class VariableDeclaration extends Element { 11 | public readonly builtin: boolean; 12 | public readonly type: TypeUsage; 13 | public readonly usages = new Array(); 14 | public readonly declarationInterval: Interval; 15 | public readonly summary: MarkdownString; 16 | public readonly stage: ShaderStage; 17 | public readonly functionPrototypeParameter: boolean; 18 | public readonly functionDefinitionParameter: boolean; 19 | public readonly extension: string; 20 | 21 | public constructor( 22 | name: string, 23 | nameInterval: Interval, 24 | scope: Scope, 25 | builtIn: boolean, 26 | declarationInterval: Interval, 27 | type: TypeUsage, 28 | fpp: boolean, 29 | fdp: boolean, 30 | summary?: MarkdownString, 31 | stage = ShaderStage.DEFAULT, 32 | extension = '' 33 | ) { 34 | super(name, nameInterval, scope); 35 | this.builtin = builtIn; 36 | this.type = type; 37 | this.declarationInterval = declarationInterval; 38 | this.functionPrototypeParameter = fpp; 39 | this.functionDefinitionParameter = fdp; 40 | this.summary = summary; 41 | this.stage = stage; 42 | this.extension = extension; 43 | } 44 | 45 | public isColorVariable(): boolean { 46 | return ( 47 | (this.type?.declaration?.name === Constants.VEC3 || this.type?.declaration?.name === Constants.VEC4) && 48 | (this.name?.toLowerCase().includes(Constants.COLOR) || this.name?.toLowerCase().includes(Constants.COLOUR)) 49 | ); 50 | } 51 | 52 | public toString(): string { 53 | const name = this.name ? Constants.SPACE + this.name : Constants.EMPTY; 54 | return this.type.toString() + name; 55 | } 56 | 57 | public toStringDocumentation(): string { 58 | return `\t${this.toString()};`; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/scope/variable/variable-usage.ts: -------------------------------------------------------------------------------- 1 | import { Element } from '../element'; 2 | import { Interval } from '../interval'; 3 | import { Scope } from '../scope'; 4 | import { VariableDeclaration } from './variable-declaration'; 5 | 6 | export class VariableUsage extends Element { 7 | public readonly declaration: VariableDeclaration; 8 | 9 | public constructor(name: string, scope: Scope, interval: Interval, declaration: VariableDeclaration) { 10 | super(name, interval, scope); 11 | this.declaration = declaration; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /syntaxes/html-injected-glsl.language.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", 3 | "name": "GLSL", 4 | "scopeName": "source.html.injected.glsl", 5 | "injectionSelector": "R:text.html", 6 | "patterns": [ 7 | { 8 | "begin": "(?<=)", 9 | "end": "(?=)", 10 | "patterns": [ 11 | { 12 | "include": "source.glsl" 13 | } 14 | ] 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /syntaxes/js-injected-glsl.language.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", 3 | "name": "GLSL", 4 | "scopeName": "source.js.injected.glsl", 5 | "injectionSelector": "L:source.js", 6 | "patterns": [ 7 | { 8 | "begin": "((\\/\\*)\\s*glsl\\s*(\\*\\/))\\s*(`)", 9 | "beginCaptures": { 10 | "1": { 11 | "name": "comment.block.js" 12 | }, 13 | "2": { 14 | "name": "punctuation.definition.comment.js" 15 | }, 16 | "3": { 17 | "name": "punctuation.definition.comment.js" 18 | }, 19 | "4": { 20 | "name": "punctuation.definition.string.template.begin.js string.template.js" 21 | } 22 | }, 23 | "end": "`", 24 | "endCaptures": { 25 | "0": { 26 | "name": "punctuation.definition.string.template.end.js string.template.js" 27 | } 28 | }, 29 | "patterns": [ 30 | { 31 | "include": "source.glsl" 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /syntaxes/ts-injected-glsl.language.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", 3 | "name": "GLSL", 4 | "scopeName": "source.ts.injected.glsl", 5 | "injectionSelector": "L:source.ts, L:source.tsx", 6 | "patterns": [ 7 | { 8 | "begin": "((\\/\\*)\\s*glsl\\s*(\\*\\/))\\s*(`)", 9 | "beginCaptures": { 10 | "1": { 11 | "name": "comment.block.ts" 12 | }, 13 | "2": { 14 | "name": "punctuation.definition.comment.ts" 15 | }, 16 | "3": { 17 | "name": "punctuation.definition.comment.ts" 18 | }, 19 | "4": { 20 | "name": "punctuation.definition.string.template.begin.ts string.template.ts" 21 | } 22 | }, 23 | "end": "`", 24 | "endCaptures": { 25 | "0": { 26 | "name": "punctuation.definition.string.template.end.ts string.template.ts" 27 | } 28 | }, 29 | "patterns": [ 30 | { 31 | "include": "source.glsl" 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "out", 6 | "lib": ["es6", "WebWorker"], 7 | "sourceMap": true, 8 | "rootDir": "src", 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "exclude": ["node_modules", ".vscode-test", ".vscode-test-web"] 13 | } 14 | -------------------------------------------------------------------------------- /vscodeignore/linux.vscodeignore: -------------------------------------------------------------------------------- 1 | # folder 2 | .github 3 | .husky 4 | .vscode 5 | .vscode-test 6 | .vscode-test-web 7 | node_modules 8 | private 9 | res/gif 10 | res/png/screenshots 11 | src 12 | syntaxes/.antlr 13 | 14 | # file 15 | .editorconfig 16 | .eslintrc.js 17 | .gitattributes 18 | .gitignore 19 | .markdownlint.json 20 | .prettierignore 21 | .prettierrc.json 22 | BUILD.md 23 | package-lock.json 24 | tsconfig.json 25 | webpack.config.js 26 | 27 | # file type 28 | **/*.ps1 29 | **/*.sh 30 | **/*.vscodeignore 31 | **/*.g4 32 | **/*.map 33 | 34 | # linux specific ignore 35 | res/bin/glslangValidatorWindows.exe 36 | res/bin/glslangValidatorMac 37 | -------------------------------------------------------------------------------- /vscodeignore/mac.vscodeignore: -------------------------------------------------------------------------------- 1 | # folder 2 | .github 3 | .husky 4 | .vscode 5 | .vscode-test 6 | .vscode-test-web 7 | node_modules 8 | private 9 | res/gif 10 | res/png/screenshots 11 | src 12 | syntaxes/.antlr 13 | 14 | # file 15 | .editorconfig 16 | .eslintrc.js 17 | .gitattributes 18 | .gitignore 19 | .markdownlint.json 20 | .prettierignore 21 | .prettierrc.json 22 | BUILD.md 23 | package-lock.json 24 | tsconfig.json 25 | webpack.config.js 26 | 27 | # file type 28 | **/*.ps1 29 | **/*.sh 30 | **/*.vscodeignore 31 | **/*.g4 32 | **/*.map 33 | 34 | # mac specific ignore 35 | res/bin/glslangValidatorLinux 36 | res/bin/glslangValidatorWindows.exe 37 | -------------------------------------------------------------------------------- /vscodeignore/universal.vscodeignore: -------------------------------------------------------------------------------- 1 | # folder 2 | .github 3 | .husky 4 | .vscode 5 | .vscode-test 6 | .vscode-test-web 7 | node_modules 8 | private 9 | res/gif 10 | res/png/screenshots 11 | src 12 | syntaxes/.antlr 13 | 14 | # file 15 | .editorconfig 16 | .eslintrc.js 17 | .gitattributes 18 | .gitignore 19 | .markdownlint.json 20 | .prettierignore 21 | .prettierrc.json 22 | BUILD.md 23 | package-lock.json 24 | tsconfig.json 25 | webpack.config.js 26 | 27 | # file type 28 | **/*.ps1 29 | **/*.sh 30 | **/*.vscodeignore 31 | **/*.g4 32 | **/*.map 33 | 34 | # universal ignore 35 | res/bin 36 | -------------------------------------------------------------------------------- /vscodeignore/web.vscodeignore: -------------------------------------------------------------------------------- 1 | # folder 2 | .github 3 | .husky 4 | .vscode 5 | .vscode-test 6 | .vscode-test-web 7 | node_modules 8 | private 9 | res/gif 10 | res/png/screenshots 11 | src 12 | syntaxes/.antlr 13 | 14 | # file 15 | .editorconfig 16 | .eslintrc.js 17 | .gitattributes 18 | .gitignore 19 | .markdownlint.json 20 | .prettierignore 21 | .prettierrc.json 22 | BUILD.md 23 | package-lock.json 24 | tsconfig.json 25 | webpack.config.js 26 | 27 | # file type 28 | **/*.ps1 29 | **/*.sh 30 | **/*.vscodeignore 31 | **/*.g4 32 | **/*.map 33 | 34 | # web specific ignore 35 | res/bin 36 | res/js 37 | res/xhtml 38 | -------------------------------------------------------------------------------- /vscodeignore/windows.vscodeignore: -------------------------------------------------------------------------------- 1 | # folder 2 | .github 3 | .husky 4 | .vscode 5 | .vscode-test 6 | .vscode-test-web 7 | node_modules 8 | private 9 | res/gif 10 | res/png/screenshots 11 | src 12 | syntaxes/.antlr 13 | 14 | # file 15 | .editorconfig 16 | .eslintrc.js 17 | .gitattributes 18 | .gitignore 19 | .markdownlint.json 20 | .prettierignore 21 | .prettierrc.json 22 | BUILD.md 23 | package-lock.json 24 | tsconfig.json 25 | webpack.config.js 26 | 27 | # file type 28 | **/*.ps1 29 | **/*.sh 30 | **/*.vscodeignore 31 | **/*.g4 32 | **/*.map 33 | 34 | # windows specific ignore 35 | res/bin/glslangValidatorLinux 36 | res/bin/glslangValidatorMac 37 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | /* eslint-disable no-undef */ 3 | //@ts-check 4 | 'use strict'; 5 | /** @typedef {import('webpack').Configuration} WebpackConfig **/ 6 | 7 | const path = require('path'); 8 | const webpack = require('webpack'); 9 | 10 | /**@type {import('webpack').Configuration}*/ 11 | const desktopExtensionConfig = { 12 | target: 'node', 13 | mode: 'development', 14 | entry: './src/extension-desktop.ts', 15 | output: { 16 | path: path.resolve(__dirname, 'dist'), 17 | filename: 'extension-desktop.js', 18 | libraryTarget: 'commonjs2', 19 | devtoolModuleFilenameTemplate: '../[resource-path]', 20 | }, 21 | devtool: 'source-map', 22 | externals: { 23 | vscode: 'commonjs vscode', 24 | }, 25 | resolve: { 26 | extensions: ['.ts', '.js'], 27 | }, 28 | module: { 29 | rules: [ 30 | { 31 | test: /\.ts$/, 32 | exclude: /node_modules/, 33 | use: [ 34 | { 35 | loader: 'ts-loader', 36 | }, 37 | ], 38 | }, 39 | ], 40 | }, 41 | }; 42 | 43 | /** @type WebpackConfig */ 44 | const webExtensionConfig = { 45 | target: 'webworker', 46 | mode: 'none', 47 | entry: './src/extension-web.ts', 48 | output: { 49 | path: path.join(__dirname, './dist'), 50 | filename: 'extension-web.js', 51 | libraryTarget: 'commonjs', 52 | devtoolModuleFilenameTemplate: '../../[resource-path]', 53 | }, 54 | devtool: 'source-map', 55 | externals: { 56 | vscode: 'commonjs vscode', 57 | }, 58 | resolve: { 59 | mainFields: ['module', 'main'], 60 | extensions: ['.ts', '.js'], 61 | fallback: { 62 | assert: require.resolve('assert'), 63 | }, 64 | }, 65 | module: { 66 | rules: [ 67 | { 68 | test: /\.ts$/, 69 | exclude: /node_modules/, 70 | use: [ 71 | { 72 | loader: 'ts-loader', 73 | }, 74 | ], 75 | }, 76 | ], 77 | }, 78 | plugins: [ 79 | new webpack.ProvidePlugin({ 80 | process: 'process/browser', 81 | }), 82 | ], 83 | performance: { 84 | hints: false, 85 | }, 86 | }; 87 | 88 | module.exports = [desktopExtensionConfig, webExtensionConfig]; 89 | --------------------------------------------------------------------------------