Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>CODESYS Structured TextNew to Visual Studio Code? Get it now.
CODESYS Structured Text

CODESYS Structured Text

livingforjesus

|
3 installs
| (0) | Free
Typed Structured Text tooling for CODESYS and codesys-build source projects.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

CODESYS Structured Text for VS Code

Language tooling for authored CODESYS Structured Text, including the split-file layouts used by codesys-build. The extension understands the relationship between a POU declaration, its implementation, methods, actions and property accessors.

Install

Build an installable extension:

bun install --frozen-lockfile
bun run package

In VS Code, run Extensions: Install from VSIX… and select artifacts/codesys-st.vsix. Open your PLC folder and a .st file. The default language mode is CODESYS Structured Text. Existing ST extensions may select Structured Text (st) instead; hover, completion and type checking also attach to .st and .iecst files in that mode. Other formats claimed by those extensions, such as .scl and .TcPOU, are excluded.

Use Ctrl+Space to request suggestions, or type . after an instance for its members. If multiple language servers produce duplicate suggestions or conflicting diagnostics, disable the other server for this workspace. CODESYS ST: Restart Language Server restarts this extension; its logs appear in Output → CODESYS Structured Text. After updating the extension, use Developer: Reload Window if VS Code requests it.

No Bun installation or CODESYS installation is needed to use the packaged extension. It runs on VS Code's Node runtime. It does not execute project configuration, start a build, or connect to a PLC. No telemetry is collected by this extension.

Editing features

  • Member completion through structs, function-block instances, properties, arrays, pointers, references, aliases and inherited members. For example: pConveyor^.Cards[CardIndex].Output..
  • Scoped identifier and type completion, named input/output argument suggestions, signature help and comment documentation on hover.
  • Go to definition/type definition, find references, document outline, workspace symbols and rename for variables, fields, enum members and parameters. Rename checks identity and collisions; it does not replace text in comments or strings.
  • Diagnostics for unresolved names/types, incompatible assignments, invalid calls, parameter directions, duplicate/missing arguments, by-reference type/storage mismatches, constant writes, visibility, invalid conditions/indexes, literal ranges, array sizes/bounds and cyclic definitions.
  • Inheritance, interface signature checks, method overrides and getter/setter access checks. Method bodies inherit their enclosing POU's scope; getter and setter locals remain separate.
  • TextMate and semantic highlighting, nested comments, folding, CODESYS snippets, brackets, indentation, and light/dark .st file icons. Language icons appear when the active file-icon theme permits language-specific icons.
  • CODESYS ST: Open Declaration / Implementation cycles between an object's source parts. CODESYS ST: Restart Language Server restarts indexing.

Potentially lossy numeric conversions are warnings. Use an explicit conversion after checking the range. Out-of-range integer constants and incompatible types are errors. Enum checking is deliberately conservative: enum identity is preserved and numeric enum arithmetic is rejected, including enums without strict.

Source layouts

All of these share the same semantic index:

src/
  Main.st                         # PROGRAM … END_PROGRAM
  types/ST_Item.st                # TYPE … END_TYPE
  globals/LineIO.st               # VAR_GLOBAL … END_VAR
  PRG_Update.declaration.st
  PRG_Update.implementation.st
  FB_Conveyor/
    FB_Conveyor.declaration.st    # or declaration.st
    FB_Conveyor.implementation.st # or implementation.st
    methods/
      Run.st                     # complete method
      Reset/
        declaration.st
        implementation.st
    properties/
      Enabled/
        declaration.st
        get.st
        set.st
    actions/
      Clear.st                   # body only

source.st is also supported for complete directory-owned POUs. Generic and named declaration/implementation parts can be mixed. Interfaces use source.st plus method/property signature files. Global-list names come from filenames. Identifiers are case-insensitive; ordinary folders organize code without creating namespaces. Separate source roots have separate IEC namespaces.

The editor tolerates incomplete source and declaration-only method signatures. It does not replace codesys-build's stricter filename/header, prefix, terminator and import-layout validation.

Workspace configuration

By default, the server discovers codesys-build.config.ts (also JS/MJS/CJS/MTS/CTS) and indexes each adjacent src/ as a separate PLC project. Without a config, it indexes the workspace folder. It ignores hidden folders, build outputs and dependency folders, and does not follow source symlinks. Unsaved buffers override disk content. Changes to dependencies refresh diagnostics and completion across the project.

For a custom build sourceDir, configure the same location explicitly; the server never imports or evaluates your TypeScript configuration:

{
  "codesysST.sourceRoots": ["plc"],
  "codesysST.libraryPaths": ["library-signatures"]
}

Each sourceRoots entry is an independent project, relative to the workspace folder. libraryPaths supplies additional ST declarations to every project in that folder. Keep these signatures outside the build source tree. Use .declaration.st for POU signatures that omit executable bodies. Standard timers, counters, edge triggers, common functions and explicit conversions have bundled signatures. Go to definition on a bundled symbol opens a read-only signature document.

Library signatures currently share the application's namespace. Arbitrary vendor namespaces and compiled .library / .compiled-library metadata are not imported. Missing vendor APIs produce unresolved-symbol/type diagnostics instead of silently becoming untyped.

Scope and limits

This is source-level language assistance, not the proprietary CODESYS compiler or a guarantee of PLC correctness. Run your normal CODESYS build before deployment.

  • Conditional compilation is not evaluated: all branches are indexed and a warning marks conditional directives. Generic specializations also emit a compiler-validation warning.
  • Graphical languages, native .project/XML object serialization, target/device configuration, online monitoring, PLC debugging, library resolution and hardware-specific semantics are outside this extension.
  • The checker covers the tested source-language subset; it does not perform control-flow proofs, definite initialization, pointer lifetime/nullability analysis, runtime bounds checks or complete IEC operator-overload validation. Date/time literal payload validation and vendor extensions still require the compiler.
  • Object names are tied to build-tool filenames. Symbol-only rename of POUs/types/methods/properties is refused; rename their files and declarations together. Variable/field/parameter rename is supported.
  • Analysis is conservative about enum conversions and string/reference compatibility. Default/vendor encodings and target-dependent numeric behavior require compiler validation.
  • Files larger than 2 MiB are skipped during disk discovery with an output-channel message. Pathological nesting is bounded and diagnostics are capped at 200 per file. Large-project validation rebuilds the semantic snapshot after changes; parsing is reused for unchanged files within that snapshot's service.

Development and validation

bun run typecheck
bun run check
bun test tests --timeout 20000
bun run test:host
bun run package

Press F5 to launch an isolated Extension Development Host with the portable conveyor fixture. test:host runs both codesys-st and legacy st language modes with a competing language extension, isolated profiles and temporary monorepo workspaces. It verifies automatic activation without explicitly activating the extension, including Inbound hover and completion in the PLC blueprint. Set VSCODE_EXECUTABLE_PATH to use an installed VS Code; otherwise the runner can download VS Code. It never edits the original PLC workspace.

Tests include the 27-file authored PLC and the 51-file codesys-build example, deterministic mutation/property testing, every-prefix edits, Node/V8 stack-stress cases, real Oniguruma highlighting, workspace transactions, real JSON-RPC and actual VS Code providers. The independent adversarial audit is recorded in docs/adversarial-results.md. Passing tests demonstrate the covered behavior; they do not establish that no bugs remain.

The code uses strict TypeScript, named exports, tabs and Biome. src/language/ owns parsing, indexing, semantic analysis and editor responses; src/server/ owns disk/buffer synchronization and LSP; src/extension.ts owns the VS Code client. There are no native parser binaries or runtime dependencies outside the bundled JavaScript.

See the research and implementation plan for the parser decision and CODESYS references.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft