diff --git a/.gitignore b/.gitignore
index 8e69b92f..fa82a3db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -410,3 +410,6 @@ temp/
# Apax packages
*.apax.tgz
+
+
+scripts/reports/
\ No newline at end of file
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 88beacaf..f71420e8 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -68,4 +68,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/_deps-common.ps1 b/scripts/_deps-common.ps1
new file mode 100644
index 00000000..6db927c9
--- /dev/null
+++ b/scripts/_deps-common.ps1
@@ -0,0 +1,153 @@
+#!/usr/bin/env pwsh
+<#
+.SYNOPSIS
+Shared helpers for dependency-management scripts (dot-source this file).
+
+.DESCRIPTION
+Common logging, file IO, semver comparison, NuGet v3 feed access, token discovery and
+severity utilities used by scripts/update-vulnerable-deps.ps1 (and reusable by
+scripts/update_axsharp_versions.ps1). Several functions here originated in
+update_axsharp_versions.ps1 and were factored out so the two scripts share one source of truth.
+
+Dot-source it from a script:
+ . "$PSScriptRoot/_deps-common.ps1"
+#>
+
+# ---------------------------------------------------------------------------
+# Logging
+# ---------------------------------------------------------------------------
+function Write-Info($msg){ Write-Host "[INFO ] $msg" -ForegroundColor Cyan }
+function Write-Warn($msg){ Write-Host "[WARN ] $msg" -ForegroundColor Yellow }
+function Write-Err ($msg){ Write-Host "[ERROR] $msg" -ForegroundColor Red }
+
+# ---------------------------------------------------------------------------
+# File IO
+# ---------------------------------------------------------------------------
+function Write-Utf8NoBom-LF {
+ # Writes text as UTF-8 (no BOM) with LF line endings to preserve repo conventions.
+ param([string]$Path, [string]$Content)
+ $lf = ($Content -replace "`r`n", "`n") -replace "`r", "`n"
+ [System.IO.File]::WriteAllText($Path, $lf, [System.Text.UTF8Encoding]::new($false))
+}
+
+# ---------------------------------------------------------------------------
+# Token discovery
+# ---------------------------------------------------------------------------
+function Resolve-FeedToken {
+ # Returns the first non-empty token from the supplied value or the candidate env vars.
+ param(
+ [string]$Token,
+ [string[]]$EnvCandidates = @('NUGET_TOKEN','GITHUB_PACKAGES_TOKEN','GITHUB_TOKEN','GH_TOKEN'),
+ [switch]$Detailed
+ )
+ if($Token){ return $Token }
+ foreach($c in $EnvCandidates){
+ $candidate = [Environment]::GetEnvironmentVariable($c)
+ if($candidate){
+ if($Detailed){ Write-Info "Using token from environment variable $c" }
+ return $candidate
+ }
+ }
+ return $null
+}
+
+# ---------------------------------------------------------------------------
+# Semver parsing / comparison (build metadata ignored for ordering)
+# ---------------------------------------------------------------------------
+function ConvertTo-VersionRecord {
+ param([string]$v)
+ $core = $v
+ $pre = ''
+ $buildSplit = $core.Split('+',2)
+ if($buildSplit.Count -gt 1){ $core = $buildSplit[0] }
+ $dashIdx = $core.IndexOf('-')
+ if($dashIdx -ge 0){
+ $pre = $core.Substring($dashIdx + 1)
+ $core = $core.Substring(0,$dashIdx)
+ }
+ $parts = $core.Split('.')
+ [int]$maj = if($parts.Count -gt 0){ $parts[0] } else { 0 }
+ [int]$min = if($parts.Count -gt 1){ $parts[1] } else { 0 }
+ [int]$pat = if($parts.Count -gt 2){ $parts[2] } else { 0 }
+ $preSegs = @()
+ if($pre){ $preSegs = $pre.Split('.') }
+ [PSCustomObject]@{ Original=$v; Major=$maj; Minor=$min; Patch=$pat; Pre=$pre; PreSegs=$preSegs }
+}
+
+function Compare-VersionRecord {
+ param($a,$b)
+ if($a.Major -ne $b.Major){ return [Math]::Sign($a.Major - $b.Major) }
+ if($a.Minor -ne $b.Minor){ return [Math]::Sign($a.Minor - $b.Minor) }
+ if($a.Patch -ne $b.Patch){ return [Math]::Sign($a.Patch - $b.Patch) }
+ $aHasPre = [string]::IsNullOrEmpty($a.Pre) -ne $true
+ $bHasPre = [string]::IsNullOrEmpty($b.Pre) -ne $true
+ if($aHasPre -and -not $bHasPre){ return -1 }
+ if($bHasPre -and -not $aHasPre){ return 1 }
+ if(-not $aHasPre -and -not $bHasPre){ return 0 }
+ $len = [Math]::Max($a.PreSegs.Count,$b.PreSegs.Count)
+ for($i=0;$i -lt $len;$i++){
+ if($i -ge $a.PreSegs.Count){ return -1 }
+ if($i -ge $b.PreSegs.Count){ return 1 }
+ $as = $a.PreSegs[$i]; $bs = $b.PreSegs[$i]
+ $aNum = $as -as [int]; $bNum = $bs -as [int]
+ $aIsNum = $aNum -ne $null; $bIsNum = $bNum -ne $null
+ if($aIsNum -and $bIsNum){ if($aNum -ne $bNum){ return [Math]::Sign($aNum - $bNum) } }
+ elseif($aIsNum -and -not $bIsNum){ return -1 }
+ elseif($bIsNum -and -not $aIsNum){ return 1 }
+ else { $cmp = [string]::Compare($as,$bs,$true); if($cmp -ne 0){ return [Math]::Sign($cmp) } }
+ }
+ return 0
+}
+
+function Test-VersionGreater {
+ # Returns $true when semver-ish version $A is strictly greater than $B.
+ param([string]$A,[string]$B)
+ if([string]::IsNullOrWhiteSpace($B)){ return $true }
+ if([string]::IsNullOrWhiteSpace($A)){ return $false }
+ return ( (Compare-VersionRecord (ConvertTo-VersionRecord $A) (ConvertTo-VersionRecord $B)) -gt 0 )
+}
+
+function Test-IsPrerelease {
+ param([string]$v)
+ if([string]::IsNullOrWhiteSpace($v)){ return $false }
+ return -not [string]::IsNullOrEmpty((ConvertTo-VersionRecord $v).Pre)
+}
+
+# ---------------------------------------------------------------------------
+# NuGet v3 feed access
+# ---------------------------------------------------------------------------
+function Get-FeedContext {
+ # Resolves the service index once and returns the PackageBaseAddress + auth headers
+ # for reuse across multiple package requests.
+ param([string]$Feed,[string]$User,[string]$Tok)
+ $serviceIndexUrl = if($Feed.ToLower().EndsWith('index.json')) { $Feed } else { ($Feed.TrimEnd('/')) + '/index.json' }
+ $headers = @{}
+ if($Tok){
+ $u = if($User){$User}else{'USERNAME'}
+ $basic = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $u,$Tok)))
+ $headers['Authorization'] = "Basic $basic"
+ }
+ $si = Invoke-RestMethod -Uri $serviceIndexUrl -Headers $headers -TimeoutSec 30
+ if(-not $si.resources){ throw "Service index missing resources at $serviceIndexUrl" }
+ $pkgBase = ($si.resources | Where-Object { $_.'@type' -eq 'PackageBaseAddress/3.0.0' } | Select-Object -First 1).'@id'
+ if(-not $pkgBase){ throw 'PackageBaseAddress/3.0.0 resource not found in service index.' }
+ if($pkgBase[-1] -ne '/') { $pkgBase += '/' }
+ [PSCustomObject]@{ PkgBase=$pkgBase; Headers=$headers }
+}
+
+function Get-PackageVersionsFromFeed {
+ # Returns the raw list of available version strings for a package id on a v3 feed.
+ param([string]$PkgBase,[hashtable]$Headers,[string]$PackageId)
+ $lowerId = $PackageId.ToLower()
+ $indexUrl = "$PkgBase$lowerId/index.json"
+ try {
+ $idx = Invoke-RestMethod -Uri $indexUrl -Headers $Headers -TimeoutSec 30
+ } catch {
+ $code = $null
+ if($_.Exception.Response){ $code = [int]$_.Exception.Response.StatusCode }
+ if($code -eq 404){ return @() } # package id unknown on this feed
+ throw "Failed to fetch version index ($indexUrl): $($_.Exception.Message)"
+ }
+ if(-not $idx.versions){ return @() }
+ return $idx.versions
+}
diff --git a/scripts/update-latest-deps.ps1 b/scripts/update-latest-deps.ps1
new file mode 100644
index 00000000..19180289
--- /dev/null
+++ b/scripts/update-latest-deps.ps1
@@ -0,0 +1,692 @@
+#!/usr/bin/env pwsh
+<#
+.SYNOPSIS
+Updates all (non-AXSharp) dependencies to their latest STABLE versions across NuGet, npm and dotnet tools.
+
+.DESCRIPTION
+One command to bring the repo up to the latest stable third-party versions. It complements - and never
+overlaps with - the two narrower updaters:
+
+ * scripts/update_axsharp_versions.ps1 - owns AXSharp.*/Inxton.Operon.* (always skipped here)
+ * scripts/update-vulnerable-deps.ps1 - owns the "Security pins" ItemGroup (always skipped here)
+
+Scope:
+
+ NuGet - rewrites entries (and the GitVersion.MsBuild ) in
+ Directory.Packages.props to the latest STABLE version from nuget.org. AXSharp/Operon/AXOpen
+ packages, the security-pin entries, and framework-tied packages (Microsoft.AspNetCore.*,
+ Microsoft.EntityFrameworkCore.*, Microsoft.Extensions.*, System.*, Microsoft.NET.ILLink.Tasks,
+ Microsoft.VisualStudio.Web.CodeGeneration.Design) are FROZEN to stay aligned with net10.0.
+
+ npm - for the source package.json projects, rewrites declared ranges (preserving the ^/~ prefix) to
+ the latest stable from `npm outdated`, then runs `npm install` to refresh package-lock.json.
+
+ tools - rewrites .config/dotnet-tools.json tool versions to latest stable (AXSharp.ix* skipped).
+
+GitVersion.MsBuild and gitversion.tool are resolved together and pinned to the SAME latest stable.
+
+"Latest" means latest STABLE: alpha/beta/rc are skipped. Major-version bumps ARE applied but flagged
+prominently in the report (use -SkipMajor to exclude them).
+
+Default action is a DRY RUN - pass -Apply to write changes. With -Apply (and unless -SkipBuild) the full
+cake build runs as verification; on failure the offending bump(s) are bisected out and only the green
+remainder is kept. A timestamped Markdown + JSON report is written to scripts/reports/. With -CreatePR the
+changes are committed to branch 'chore/update-latest-deps' off origin/dev and a PR is opened against dev.
+
+.PARAMETER Apply
+Write changes. Without it the script previews only (dry run) and touches nothing.
+
+.PARAMETER NuGetOnly
+Process NuGet (Directory.Packages.props) only.
+
+.PARAMETER NpmOnly
+Process npm only.
+
+.PARAMETER ToolsOnly
+Process dotnet tools only.
+
+.PARAMETER SkipMajor
+Exclude major-version bumps (default: apply them and flag them in the report).
+
+.PARAMETER SkipBuild
+Skip the cake build verification step (fast path; relies on manual review).
+
+.PARAMETER RollbackAllOnFailure
+On build failure, revert every change instead of bisecting for a green subset.
+
+.PARAMETER MaxBisectBuilds
+Cap on the number of full cake builds spent bisecting after an initial failure. Default 6.
+
+.PARAMETER CreatePR
+Commit changes to branch 'chore/update-latest-deps' off origin/dev and open a PR against dev. Implies -Apply.
+
+.PARAMETER NpmProjects
+Explicit list of package.json paths to process (relative to repo root or absolute). When omitted,
+projects are discovered automatically under src/ (skipping bin/obj/ctrl/.apax/node_modules/wwwroot/dist).
+
+.PARAMETER Source
+NuGet v3 feed used to look up available versions. Default nuget.org.
+
+.PARAMETER Token
+Token for the NuGet feed (private feeds). Falls back to NUGET_TOKEN / GITHUB_PACKAGES_TOKEN /
+GITHUB_TOKEN / GH_TOKEN.
+
+.PARAMETER Detailed
+Verbose logging.
+
+.EXAMPLE
+./update-latest-deps.ps1 # dry run, all ecosystems
+
+.EXAMPLE
+./update-latest-deps.ps1 -NuGetOnly # dry run, NuGet only
+
+.EXAMPLE
+./update-latest-deps.ps1 -Apply -SkipBuild # write changes, skip the (slow) cake build
+
+.EXAMPLE
+./update-latest-deps.ps1 -CreatePR # apply, build-verify, open PR against dev
+#>
+
+[CmdletBinding()]
+param(
+ [switch]$Apply,
+ [switch]$NuGetOnly,
+ [switch]$NpmOnly,
+ [switch]$ToolsOnly,
+ [switch]$SkipMajor,
+ [switch]$SkipBuild,
+ [switch]$RollbackAllOnFailure,
+ [int]$MaxBisectBuilds = 6,
+ [switch]$CreatePR,
+ [string[]]$NpmProjects,
+ [string]$Source = 'https://api.nuget.org/v3/index.json',
+ [string]$Token,
+ [switch]$Detailed
+)
+
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+
+$scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
+. "$scriptRoot/_deps-common.ps1"
+
+$repoRoot = Split-Path -Parent $scriptRoot
+$propsPath = Join-Path $repoRoot 'Directory.Packages.props'
+$toolsPath = Join-Path $repoRoot '.config/dotnet-tools.json'
+$cakeProj = Join-Path $repoRoot 'cake/Build.csproj'
+
+# ---------------------------------------------------------------------------
+# Validation & constants
+# ---------------------------------------------------------------------------
+if($CreatePR){ $Apply = $true } # -CreatePR implies writing changes
+$DryRun = -not $Apply
+
+$onlyCount = @($NuGetOnly,$NpmOnly,$ToolsOnly | Where-Object { $_ }).Count
+if($onlyCount -gt 1){ Write-Err '-NuGetOnly / -NpmOnly / -ToolsOnly are mutually exclusive.'; exit 1 }
+
+$doNuget = (-not $NpmOnly) -and (-not $ToolsOnly)
+$doNpm = (-not $NuGetOnly) -and (-not $ToolsOnly)
+$doTools = (-not $NuGetOnly) -and (-not $NpmOnly)
+
+# Feed auth: never send a token to the public nuget.org CDN (it 403s on authed cached responses).
+# Resolve a token only for an explicitly-provided private -Source (or explicit -Token).
+$IsPublicNuGet = ($Source -match 'api\.nuget\.org')
+$feedToken = if($Token){ $Token } elseif(-not $IsPublicNuGet){ Resolve-FeedToken -Token $Token -Detailed:$Detailed } else { $null }
+
+# Owned by update_axsharp_versions.ps1 - never touched.
+$AxSharpSkipPattern = '^(AXSharp|Inxton\.Operon|AXOpen)\b'
+# Owned by update-vulnerable-deps.ps1 ("Security pins" ItemGroup) - never touched.
+$SecurityPinIds = @('') #@('Snappier','System.Security.Cryptography.Xml')
+# Frozen to stay aligned with net10.0 (see plan / interview).
+$FrameworkFreezeExact = @('Microsoft.NET.ILLink.Tasks','Microsoft.VisualStudio.Web.CodeGeneration.Design')
+$FrameworkFreezePrefixes = @('Microsoft.AspNetCore.','Microsoft.EntityFrameworkCore.','Microsoft.Extensions.','System.')
+# GitVersion packages/tool are kept in sync with one another.
+$GitVersionNuGetId = 'GitVersion.MsBuild'
+$GitVersionToolId = 'gitversion.tool'
+
+# Source npm projects - discovered dynamically under src/, skipping generated/dependency
+# copies (bin/obj/ctrl/.apax/node_modules/wwwroot). Override with -NpmProjects to be explicit.
+function Get-NpmProjects {
+ $srcRoot = Join-Path $repoRoot 'src'
+ if(-not (Test-Path -LiteralPath $srcRoot)){ return @() }
+ $excludeRx = '[\\/](bin|obj|ctrl|\.apax|node_modules|wwwroot|dist|\.git)[\\/]'
+ Get-ChildItem -LiteralPath $srcRoot -Recurse -File -Filter 'package.json' -ErrorAction SilentlyContinue |
+ Where-Object { $_.FullName -notmatch $excludeRx } |
+ Select-Object -ExpandProperty FullName |
+ Sort-Object
+}
+
+$NpmProjects = if($NpmProjects){ $NpmProjects | ForEach-Object { if([System.IO.Path]::IsPathRooted($_)){ $_ } else { Join-Path $repoRoot $_ } } }
+ else { Get-NpmProjects }
+
+# Accumulators for the report.
+$Changes = New-Object System.Collections.ArrayList # applied/previewed bumps
+$Frozen = New-Object System.Collections.ArrayList # id + reason
+$Reverted = New-Object System.Collections.ArrayList # bumps removed by bisection
+$ScanErrors = New-Object System.Collections.ArrayList
+$BuildResult = 'not-run'
+
+# Captured original file contents (for bisection replay). file path -> original raw text.
+$OriginalContent = @{}
+
+# ---------------------------------------------------------------------------
+# Helpers
+# ---------------------------------------------------------------------------
+function Test-CommandAvailable { param([string]$Name) $null -ne (Get-Command $Name -ErrorAction SilentlyContinue) }
+
+function Test-IsMajorBump {
+ param([string]$From,[string]$To)
+ $f = ConvertTo-VersionRecord $From
+ $t = ConvertTo-VersionRecord $To
+ return ($t.Major -gt $f.Major)
+}
+
+function Get-LatestStableVersion {
+ # Highest non-prerelease version of $PackageId on the feed, or $null.
+ param([string]$PackageId,$FeedCtx)
+ $versions = @()
+ try { $versions = Get-PackageVersionsFromFeed -PkgBase $FeedCtx.PkgBase -Headers $FeedCtx.Headers -PackageId $PackageId }
+ catch { if($Detailed){ Write-Warn "feed lookup failed for ${PackageId}: $($_.Exception.Message)" }; return $null }
+ if(-not $versions -or @($versions).Count -eq 0){ return $null }
+ $stable = @($versions | Where-Object { -not (Test-IsPrerelease $_) })
+ if($stable.Count -eq 0){ return $null }
+ $best = $stable[0]
+ foreach($v in $stable){ if(Test-VersionGreater $v $best){ $best = $v } }
+ return $best
+}
+
+function Get-NuGetDisposition {
+ # Returns 'update' or a 'freeze-*' / 'skip-*' reason for a package id.
+ param([string]$Id)
+ if($Id -match $AxSharpSkipPattern){ return 'skip-axsharp (owned by update_axsharp_versions.ps1)' }
+ if($SecurityPinIds -contains $Id){ return 'skip-security-pin (owned by update-vulnerable-deps.ps1)' }
+ if($FrameworkFreezeExact -contains $Id){ return 'freeze-framework (net10.0-tied)' }
+ foreach($p in $FrameworkFreezePrefixes){ if($Id.StartsWith($p)){ return 'freeze-framework (net10.0-tied)' } }
+ return 'update'
+}
+
+# ---------------------------------------------------------------------------
+# Change application (replayable from captured original content)
+# ---------------------------------------------------------------------------
+function Apply-ChangeToContent {
+ # Applies a single change to the supplied file content and returns the new content.
+ param([string]$Content,$Change)
+ $idEsc = [regex]::Escape($Change.Id)
+ switch($Change.Kind){
+ 'props-packageversion' {
+ $rx = "(]*\bInclude=`"$idEsc`"[^>]*\bVersion=`")[^`"]*(`")"
+ return [regex]::Replace($Content,$rx,"`${1}$($Change.To)`${2}",1)
+ }
+ 'props-globalref' {
+ $rx = "(]*\bInclude=`"$idEsc`"[^>]*\bVersion=`")[^`"]*(`")"
+ return [regex]::Replace($Content,$rx,"`${1}$($Change.To)`${2}",1)
+ }
+ 'tool' {
+ $rx = "(`"$idEsc`"\s*:\s*\{[^{}]*?`"version`"\s*:\s*`")[^`"]+(`")"
+ return [System.Text.RegularExpressions.Regex]::Replace(
+ $Content,$rx,"`${1}$($Change.To)`${2}",
+ [System.Text.RegularExpressions.RegexOptions]::Singleline)
+ }
+ 'npm' {
+ # Preserve any leading range operator (^, ~, >=, etc.) on the declared range.
+ $rx = "(`"$idEsc`"\s*:\s*`")([^`"]*)(`")"
+ return [regex]::Replace($Content,$rx,{
+ param($m)
+ $old = $m.Groups[2].Value
+ $prefix = ''
+ if($old -match '^([\^~>=<\s]*)'){ $prefix = $Matches[1] }
+ $m.Groups[1].Value + $prefix + $Change.To + $m.Groups[3].Value
+ },1)
+ }
+ default { return $Content }
+ }
+}
+
+function Write-FileSet {
+ # Rebuilds every affected file from its captured ORIGINAL content, applying only $ActiveChanges.
+ # Returns the list of npm directories whose package.json changed (caller refreshes their lock).
+ param($ActiveChanges)
+ $byFile = $ActiveChanges | Group-Object -Property File
+ $npmDirs = New-Object System.Collections.ArrayList
+ foreach($g in $byFile){
+ $file = $g.Name
+ if(-not $OriginalContent.ContainsKey($file)){ continue }
+ $content = $OriginalContent[$file]
+ foreach($c in $g.Group){
+ $content = Apply-ChangeToContent -Content $content -Change $c
+ if($c.Ecosystem -eq 'npm'){ $dir = Split-Path -Parent $file; if(-not $npmDirs.Contains($dir)){ [void]$npmDirs.Add($dir) } }
+ }
+ Write-Utf8NoBom-LF -Path $file -Content $content
+ }
+ # Files that had ALL their changes removed must be restored to original too.
+ foreach($file in $OriginalContent.Keys){
+ if(-not ($byFile | Where-Object { $_.Name -eq $file })){
+ Write-Utf8NoBom-LF -Path $file -Content $OriginalContent[$file]
+ }
+ }
+ return $npmDirs
+}
+
+function Update-NpmLockfiles {
+ param($NpmDirs)
+ foreach($dir in $NpmDirs){
+ if($Detailed){ Write-Info " npm install (refresh lockfile): $dir" }
+ Push-Location $dir
+ try { & npm install --no-audit --no-fund *> $null }
+ catch { [void]$ScanErrors.Add("npm install failed in ${dir}: $($_.Exception.Message)") }
+ finally { Pop-Location }
+ }
+}
+
+# ---------------------------------------------------------------------------
+# Scanners (populate $Changes / $Frozen; capture originals)
+# ---------------------------------------------------------------------------
+function Invoke-NuGetScan {
+ param($FeedCtx)
+ Write-Info 'Scanning NuGet (Directory.Packages.props)...'
+ if(-not (Test-Path $propsPath)){ [void]$ScanErrors.Add('Directory.Packages.props not found'); return }
+ $content = Get-Content -LiteralPath $propsPath -Raw
+ $OriginalContent[$propsPath] = $content
+
+ $pvMatches = [regex]::Matches($content,']*\bInclude="([^"]+)"[^>]*\bVersion="([^"]+)"')
+ $grMatches = [regex]::Matches($content,']*\bInclude="([^"]+)"[^>]*\bVersion="([^"]+)"')
+
+ foreach($m in @($pvMatches) + @($grMatches)){
+ $id = $m.Groups[1].Value
+ $cur = $m.Groups[2].Value
+ $kind = if($m.Value -like '*GlobalPackageReference*'){ 'props-globalref' } else { 'props-packageversion' }
+
+ # GitVersion handled together below.
+ if($id -eq $GitVersionNuGetId){ continue }
+
+ $disp = Get-NuGetDisposition $id
+ if($disp -ne 'update'){ [void]$Frozen.Add([PSCustomObject]@{ Ecosystem='nuget'; Id=$id; Current=$cur; Reason=$disp }); continue }
+
+ $latest = Get-LatestStableVersion -PackageId $id -FeedCtx $FeedCtx
+ if(-not $latest){ [void]$Frozen.Add([PSCustomObject]@{ Ecosystem='nuget'; Id=$id; Current=$cur; Reason='no stable version on feed' }); continue }
+ if(-not (Test-VersionGreater $latest $cur)){ if($Detailed){ Write-Info " $id already latest ($cur)" }; continue }
+
+ $isMajor = Test-IsMajorBump $cur $latest
+ if($isMajor -and $SkipMajor){ [void]$Frozen.Add([PSCustomObject]@{ Ecosystem='nuget'; Id=$id; Current=$cur; Reason="major bump to $latest skipped (-SkipMajor)" }); continue }
+
+ [void]$Changes.Add([PSCustomObject]@{ Ecosystem='nuget'; Id=$id; From=$cur; To=$latest; IsMajor=$isMajor; Kind=$kind; File=$propsPath })
+ Write-Info (" {0}: {1} -> {2}{3}" -f $id,$cur,$latest,$(if($isMajor){' [MAJOR]'}else{''}))
+ }
+}
+
+function Resolve-GitVersionSync {
+ # Resolves one latest-stable GitVersion across MsBuild pkg + dotnet tool and queues both bumps.
+ param($FeedCtx)
+ if(-not (Test-Path $propsPath)){ return }
+ $propsRaw = $OriginalContent[$propsPath]
+ if(-not $propsRaw){ $propsRaw = Get-Content -LiteralPath $propsPath -Raw; $OriginalContent[$propsPath] = $propsRaw }
+
+ $curMsb = $null
+ $m = [regex]::Match($propsRaw,"]*\bInclude=`"$([regex]::Escape($GitVersionNuGetId))`"[^>]*\bVersion=`"([^`"]+)`"")
+ if($m.Success){ $curMsb = $m.Groups[1].Value }
+
+ $curTool = $null
+ if(Test-Path $toolsPath){
+ $toolsRaw = $OriginalContent[$toolsPath]
+ if(-not $toolsRaw){ $toolsRaw = Get-Content -LiteralPath $toolsPath -Raw; $OriginalContent[$toolsPath] = $toolsRaw }
+ $tm = [regex]::Match($toolsRaw,"`"$([regex]::Escape($GitVersionToolId))`"\s*:\s*\{[^{}]*?`"version`"\s*:\s*`"([^`"]+)`"",[System.Text.RegularExpressions.RegexOptions]::Singleline)
+ if($tm.Success){ $curTool = $tm.Groups[1].Value }
+ }
+
+ $latestMsb = Get-LatestStableVersion -PackageId $GitVersionNuGetId -FeedCtx $FeedCtx
+ $latestTool = Get-LatestStableVersion -PackageId $GitVersionToolId -FeedCtx $FeedCtx
+ $synced = $latestMsb
+ if($latestTool -and (Test-VersionGreater $latestTool $synced)){ $synced = $latestTool }
+ if(-not $synced){ Write-Warn 'Could not resolve a latest stable GitVersion; leaving as-is.'; return }
+
+ if($doNuget -and $curMsb -and (Test-VersionGreater $synced $curMsb)){
+ $isMajor = Test-IsMajorBump $curMsb $synced
+ if(-not ($isMajor -and $SkipMajor)){
+ [void]$Changes.Add([PSCustomObject]@{ Ecosystem='nuget'; Id=$GitVersionNuGetId; From=$curMsb; To=$synced; IsMajor=$isMajor; Kind='props-globalref'; File=$propsPath })
+ Write-Info (" {0}: {1} -> {2} (GitVersion sync){3}" -f $GitVersionNuGetId,$curMsb,$synced,$(if($isMajor){' [MAJOR]'}else{''}))
+ } else { [void]$Frozen.Add([PSCustomObject]@{ Ecosystem='nuget'; Id=$GitVersionNuGetId; Current=$curMsb; Reason="major bump to $synced skipped (-SkipMajor)" }) }
+ }
+ if($doTools -and $curTool -and (Test-VersionGreater $synced $curTool)){
+ $isMajor = Test-IsMajorBump $curTool $synced
+ if(-not ($isMajor -and $SkipMajor)){
+ [void]$Changes.Add([PSCustomObject]@{ Ecosystem='tool'; Id=$GitVersionToolId; From=$curTool; To=$synced; IsMajor=$isMajor; Kind='tool'; File=$toolsPath })
+ Write-Info (" {0}: {1} -> {2} (GitVersion sync){3}" -f $GitVersionToolId,$curTool,$synced,$(if($isMajor){' [MAJOR]'}else{''}))
+ } else { [void]$Frozen.Add([PSCustomObject]@{ Ecosystem='tool'; Id=$GitVersionToolId; Current=$curTool; Reason="major bump to $synced skipped (-SkipMajor)" }) }
+ }
+}
+
+function Invoke-ToolsScan {
+ param($FeedCtx)
+ Write-Info 'Scanning dotnet tools (.config/dotnet-tools.json)...'
+ if(-not (Test-Path $toolsPath)){ [void]$ScanErrors.Add('.config/dotnet-tools.json not found'); return }
+ $raw = $OriginalContent[$toolsPath]
+ if(-not $raw){ $raw = Get-Content -LiteralPath $toolsPath -Raw; $OriginalContent[$toolsPath] = $raw }
+ try { $obj = $raw | ConvertFrom-Json -ErrorAction Stop } catch { [void]$ScanErrors.Add('tools JSON parse failed'); return }
+ if(-not $obj.tools){ [void]$ScanErrors.Add("tools JSON missing 'tools'"); return }
+
+ foreach($name in $obj.tools.PSObject.Properties.Name){
+ if($name -like 'AXSharp.*' -or $name -like 'Inxton.Operon.*'){ [void]$Frozen.Add([PSCustomObject]@{ Ecosystem='tool'; Id=$name; Current=$obj.tools.$name.version; Reason='skip-axsharp (owned by update_axsharp_versions.ps1)' }); continue }
+ if($name -eq $GitVersionToolId){ continue } # handled by Resolve-GitVersionSync
+ $cur = $obj.tools.$name.version
+ $latest = Get-LatestStableVersion -PackageId $name -FeedCtx $FeedCtx
+ if(-not $latest){ [void]$Frozen.Add([PSCustomObject]@{ Ecosystem='tool'; Id=$name; Current=$cur; Reason='no stable version on feed' }); continue }
+ if(-not (Test-VersionGreater $latest $cur)){ if($Detailed){ Write-Info " $name already latest ($cur)" }; continue }
+ $isMajor = Test-IsMajorBump $cur $latest
+ if($isMajor -and $SkipMajor){ [void]$Frozen.Add([PSCustomObject]@{ Ecosystem='tool'; Id=$name; Current=$cur; Reason="major bump to $latest skipped (-SkipMajor)" }); continue }
+ [void]$Changes.Add([PSCustomObject]@{ Ecosystem='tool'; Id=$name; From=$cur; To=$latest; IsMajor=$isMajor; Kind='tool'; File=$toolsPath })
+ Write-Info (" {0}: {1} -> {2}{3}" -f $name,$cur,$latest,$(if($isMajor){' [MAJOR]'}else{''}))
+ }
+}
+
+function Invoke-NpmScan {
+ Write-Info 'Scanning npm projects...'
+ if(-not (Test-CommandAvailable 'npm')){ Write-Err 'npm not found on PATH.'; [void]$ScanErrors.Add('npm not found'); return }
+ foreach($pkgJson in $NpmProjects){
+ if(-not (Test-Path -LiteralPath $pkgJson)){ if($Detailed){ Write-Warn "missing: $pkgJson" }; continue }
+ $dir = Split-Path -Parent $pkgJson
+ $name = (Resolve-Path -LiteralPath $dir).Path.Replace((Resolve-Path $repoRoot).Path,'').TrimStart('\','/')
+ Write-Info " $name"
+ $OriginalContent[$pkgJson] = Get-Content -LiteralPath $pkgJson -Raw
+ Push-Location $dir
+ try {
+ if(-not (Test-Path 'node_modules')){
+ if($Detailed){ Write-Info " npm install (no node_modules)" }
+ & npm install --no-audit --no-fund *> $null
+ }
+ $raw = & npm outdated --json 2>$null | Out-String
+ if(-not $raw.Trim()){ if($Detailed){ Write-Info " up to date" }; Pop-Location; continue }
+ $parsed = $null; try { $parsed = $raw | ConvertFrom-Json } catch { [void]$ScanErrors.Add("npm outdated unparseable: $name"); Pop-Location; continue }
+ if(-not $parsed){ Pop-Location; continue }
+ foreach($p in $parsed.PSObject.Properties){
+ $pkgName = $p.Name
+ $info = $p.Value
+ if($info -is [System.Object[]]){ $info = $info[0] } # multiple entries -> take first
+ $cur = if($info.PSObject.Properties.Name -contains 'current'){ $info.current } else { $null }
+ $latest = if($info.PSObject.Properties.Name -contains 'latest'){ $info.latest } else { $null }
+ if(-not $cur -or -not $latest){ continue } # not installed / no candidate
+ if(Test-IsPrerelease $latest){ continue } # stable only
+ if(-not (Test-VersionGreater $latest $cur)){ continue }
+ $isMajor = Test-IsMajorBump $cur $latest
+ if($isMajor -and $SkipMajor){ [void]$Frozen.Add([PSCustomObject]@{ Ecosystem='npm'; Id="$name/$pkgName"; Current=$cur; Reason="major bump to $latest skipped (-SkipMajor)" }); continue }
+ [void]$Changes.Add([PSCustomObject]@{ Ecosystem='npm'; Id=$pkgName; Project=$name; From=$cur; To=$latest; IsMajor=$isMajor; Kind='npm'; File=$pkgJson })
+ Write-Info (" {0}: {1} -> {2}{3}" -f $pkgName,$cur,$latest,$(if($isMajor){' [MAJOR]'}else{''}))
+ }
+ } catch { [void]$ScanErrors.Add("npm scan error in ${name}: $($_.Exception.Message)") }
+ finally { Pop-Location }
+ }
+}
+
+# ---------------------------------------------------------------------------
+# Build verification + bisection
+# ---------------------------------------------------------------------------
+function Invoke-CakeBuild {
+ if(-not (Test-CommandAvailable 'dotnet')){ Write-Err 'dotnet CLI not found; cannot build.'; return $false }
+ Write-Info 'Running full cake build (dotnet run --project cake/Build.csproj) ...'
+ & dotnet run --project $cakeProj
+ return ($LASTEXITCODE -eq 0)
+}
+
+function Invoke-BisectGreenSubset {
+ # ddmin-style: remove minimal change subsets until the build is green, bounded by $MaxBisectBuilds.
+ # Mutates the working tree to the green subset; records removed changes in $script:Reverted.
+ $builds = 0
+ $active = @($Changes)
+ $n = 2
+ Write-Warn "Build failed with all $($active.Count) change(s). Bisecting for a green subset (max $MaxBisectBuilds builds)..."
+ while($builds -lt $MaxBisectBuilds -and $active.Count -gt 1){
+ $chunkSize = [Math]::Ceiling($active.Count / $n)
+ $removedSomething = $false
+ for($i=0; $i -lt $active.Count; $i += $chunkSize){
+ $chunk = $active[$i..([Math]::Min($i+$chunkSize-1,$active.Count-1))]
+ $trial = $active | Where-Object { $chunk -notcontains $_ }
+ if(@($trial).Count -eq 0){ continue }
+ $dirs = Write-FileSet -ActiveChanges $trial
+ Update-NpmLockfiles -NpmDirs $dirs
+ $builds++
+ Write-Info " bisect build $builds/$MaxBisectBuilds : trying $((@($trial)).Count) of $($active.Count) changes"
+ if(Invoke-CakeBuild){ $active = @($trial); $n = [Math]::Max($n-1,2); $removedSomething = $true; break }
+ if($builds -ge $MaxBisectBuilds){ break }
+ }
+ if(-not $removedSomething){
+ if($n -ge $active.Count){ break }
+ $n = [Math]::Min($n*2,$active.Count)
+ }
+ }
+ # Record what got dropped and lock in the surviving subset.
+ $kept = @($active)
+ foreach($c in $Changes){ if($kept -notcontains $c){ [void]$Reverted.Add($c) } }
+ $dirs = Write-FileSet -ActiveChanges $kept
+ Update-NpmLockfiles -NpmDirs $dirs
+ if($kept.Count -gt 0 -and $builds -lt $MaxBisectBuilds){
+ $builds++
+ Write-Info " bisect build $builds : confirming surviving subset ($($kept.Count) change(s))"
+ $script:BuildResult = if(Invoke-CakeBuild){ 'pass (after bisection)' } else { 'FAIL (bisection exhausted - manual review)' }
+ } else {
+ $script:BuildResult = "indeterminate (bisection hit -MaxBisectBuilds=$MaxBisectBuilds)"
+ }
+}
+
+# ---------------------------------------------------------------------------
+# Report
+# ---------------------------------------------------------------------------
+function Write-Report {
+ param([string]$Stamp)
+ $reportsDir = Join-Path $scriptRoot 'reports'
+ if(-not (Test-Path $reportsDir)){ New-Item -ItemType Directory -Path $reportsDir -Force | Out-Null }
+ $mdPath = Join-Path $reportsDir "latest-deps-report-$Stamp.md"
+ $jsonPath = Join-Path $reportsDir "latest-deps-report-$Stamp.json"
+
+ $applied = @($Changes | Where-Object { $Reverted -notcontains $_ })
+ $majors = @($applied | Where-Object { $_.IsMajor })
+
+ $payload = [PSCustomObject]@{
+ timestamp = $Stamp
+ dryRun = [bool]$DryRun
+ skipMajor = [bool]$SkipMajor
+ ecosystems = @{ nuget=[bool]$doNuget; npm=[bool]$doNpm; tools=[bool]$doTools }
+ build = $BuildResult
+ applied = $applied
+ reverted = $Reverted
+ frozen = $Frozen
+ majors = $majors
+ scanErrors = $ScanErrors
+ }
+ Write-Utf8NoBom-LF -Path $jsonPath -Content ($payload | ConvertTo-Json -Depth 8)
+
+ $sb = New-Object System.Text.StringBuilder
+ [void]$sb.AppendLine('# Latest-dependency update report')
+ [void]$sb.AppendLine('')
+ [void]$sb.AppendLine("- Generated: $Stamp")
+ [void]$sb.AppendLine("- Dry run: $([bool]$DryRun)")
+ [void]$sb.AppendLine("- Skip major: $([bool]$SkipMajor)")
+ [void]$sb.AppendLine("- Ecosystems: NuGet=$doNuget, npm=$doNpm, tools=$doTools")
+ [void]$sb.AppendLine("- Build result: **$BuildResult**")
+ [void]$sb.AppendLine('')
+
+ if($majors.Count -gt 0){
+ [void]$sb.AppendLine("## [!] Major-version bumps ($($majors.Count)) - review carefully")
+ [void]$sb.AppendLine('| Ecosystem | Package | From | To |')
+ [void]$sb.AppendLine('|---|---|---|---|')
+ foreach($c in $majors){ [void]$sb.AppendLine("| $($c.Ecosystem) | $($c.Id) | $($c.From) | $($c.To) |") }
+ [void]$sb.AppendLine('')
+ }
+
+ [void]$sb.AppendLine("## NuGet bumped ($(@($applied | Where-Object { $_.Ecosystem -eq 'nuget' }).Count))")
+ [void]$sb.AppendLine('| Package | From | To | Major? |')
+ [void]$sb.AppendLine('|---|---|---|---|')
+ foreach($c in ($applied | Where-Object { $_.Ecosystem -eq 'nuget' })){ [void]$sb.AppendLine("| $($c.Id) | $($c.From) | $($c.To) | $(if($c.IsMajor){'YES'}else{''}) |") }
+ [void]$sb.AppendLine('')
+
+ [void]$sb.AppendLine("## npm bumped ($(@($applied | Where-Object { $_.Ecosystem -eq 'npm' }).Count))")
+ [void]$sb.AppendLine('| Project | Package | From | To | Major? |')
+ [void]$sb.AppendLine('|---|---|---|---|---|')
+ foreach($c in ($applied | Where-Object { $_.Ecosystem -eq 'npm' })){ [void]$sb.AppendLine("| $($c.Project) | $($c.Id) | $($c.From) | $($c.To) | $(if($c.IsMajor){'YES'}else{''}) |") }
+ [void]$sb.AppendLine('')
+
+ [void]$sb.AppendLine("## Tools bumped ($(@($applied | Where-Object { $_.Ecosystem -eq 'tool' }).Count))")
+ [void]$sb.AppendLine('| Tool | From | To |')
+ [void]$sb.AppendLine('|---|---|---|')
+ foreach($c in ($applied | Where-Object { $_.Ecosystem -eq 'tool' })){ [void]$sb.AppendLine("| $($c.Id) | $($c.From) | $($c.To) |") }
+ [void]$sb.AppendLine('')
+
+ if($Reverted.Count -gt 0){
+ [void]$sb.AppendLine("## Reverted by build bisection ($($Reverted.Count))")
+ [void]$sb.AppendLine('| Ecosystem | Package | From | To |')
+ [void]$sb.AppendLine('|---|---|---|---|')
+ foreach($c in $Reverted){ [void]$sb.AppendLine("| $($c.Ecosystem) | $($c.Id) | $($c.From) | $($c.To) |") }
+ [void]$sb.AppendLine('')
+ }
+
+ [void]$sb.AppendLine("## Frozen / skipped ($($Frozen.Count))")
+ [void]$sb.AppendLine('| Ecosystem | Package | Current | Reason |')
+ [void]$sb.AppendLine('|---|---|---|---|')
+ foreach($f in $Frozen){ [void]$sb.AppendLine("| $($f.Ecosystem) | $($f.Id) | $($f.Current) | $($f.Reason) |") }
+ [void]$sb.AppendLine('')
+
+ if($ScanErrors.Count -gt 0){
+ [void]$sb.AppendLine('## Scan errors')
+ foreach($e in $ScanErrors){ [void]$sb.AppendLine("- $e") }
+ }
+ Write-Utf8NoBom-LF -Path $mdPath -Content $sb.ToString()
+ Write-Info "Report: $mdPath"
+ return $mdPath
+}
+
+# ---------------------------------------------------------------------------
+# Commit + PR
+# ---------------------------------------------------------------------------
+function Invoke-CreatePR {
+ param([string]$ReportPath)
+ if(-not (Test-CommandAvailable 'git')){ Write-Err 'git not found; cannot create PR.'; return }
+ if(-not (Test-CommandAvailable 'gh')){ Write-Err 'gh CLI not found; cannot open PR.'; return }
+
+ $branch = 'chore/update-latest-deps'
+ Write-Info "Creating branch '$branch' off origin/dev and opening PR..."
+
+ & git -C $repoRoot fetch origin dev --quiet
+ & git -C $repoRoot stash push -u -m 'latest-deps-wip' *> $null
+ $stashed = ($LASTEXITCODE -eq 0)
+ & git -C $repoRoot switch -C $branch origin/dev
+ if($LASTEXITCODE -ne 0){ Write-Err "Failed to create branch $branch."; if($stashed){ & git -C $repoRoot stash pop *> $null }; return }
+ if($stashed){
+ & git -C $repoRoot stash pop
+ if($LASTEXITCODE -ne 0){ Write-Err 'Stash pop conflicted; resolve manually. Aborting PR.'; return }
+ }
+
+ & git -C $repoRoot add -- 'Directory.Packages.props' '.config/dotnet-tools.json' '**/package.json' '**/package-lock.json'
+ & git -C $repoRoot commit -m @'
+chore(deps): update dependencies to latest stable
+
+Automated by scripts/update-latest-deps.ps1.
+
+Co-Authored-By: Claude Opus 4.8 (1M context)
+'@
+ if($LASTEXITCODE -ne 0){ Write-Warn 'Nothing to commit (no changes staged). Skipping PR.'; return }
+
+ & git -C $repoRoot push -u origin $branch
+ if($LASTEXITCODE -ne 0){ Write-Err 'git push failed.'; return }
+
+ $applied = @($Changes | Where-Object { $Reverted -notcontains $_ })
+ $bumpLines = ($applied | ForEach-Object { "- $($_.Ecosystem) $($_.Id): $($_.From) -> $($_.To)$(if($_.IsMajor){' (MAJOR)'}else{''})" }) -join "`n"
+ $majorList = ($applied | Where-Object { $_.IsMajor } | ForEach-Object { "- $($_.Ecosystem) $($_.Id): $($_.From) -> $($_.To)" }) -join "`n"
+ $revLines = ($Reverted | ForEach-Object { "- $($_.Ecosystem) $($_.Id): $($_.From) -> $($_.To)" }) -join "`n"
+ $body = @"
+Automated update of (non-AXSharp) dependencies to their latest stable versions.
+
+Build verification: $BuildResult
+
+## Bumped ($($applied.Count))
+$bumpLines
+
+## [!] Major-version bumps
+$(if($majorList){ $majorList } else { '_none_' })
+
+## Reverted by build bisection
+$(if($revLines){ $revLines } else { '_none_' })
+
+See the attached report ($([System.IO.Path]::GetFileName($ReportPath))) for frozen/skipped detail.
+
+🤖 Generated with [Claude Code](https://claude.com/claude-code)
+"@
+ & gh pr create --base dev --head $branch --title 'chore(deps): update dependencies to latest stable' --body $body
+ if($LASTEXITCODE -ne 0){ Write-Err 'gh pr create failed.' } else { Write-Info 'PR opened against dev.' }
+}
+
+# ---------------------------------------------------------------------------
+# Main
+# ---------------------------------------------------------------------------
+$stamp = (Get-Date).ToString('yyyy-MM-dd-HHmmss')
+Write-Info "update-latest-deps (apply=$Apply, dryRun=$DryRun, nuget=$doNuget, npm=$doNpm, tools=$doTools, skipMajor=$SkipMajor)"
+if($DryRun){ Write-Warn 'DRY RUN - no files will be changed. Pass -Apply to write.' }
+
+$feedCtx = $null
+if($doNuget -or $doTools){
+ try { $feedCtx = Get-FeedContext -Feed $Source -User $null -Tok $feedToken } catch { Write-Err "Could not initialise NuGet feed: $($_.Exception.Message)"; exit 2 }
+}
+
+if($doNuget){ Invoke-NuGetScan -FeedCtx $feedCtx }
+if($doTools){ Invoke-ToolsScan -FeedCtx $feedCtx }
+if($doNuget -or $doTools){ Resolve-GitVersionSync -FeedCtx $feedCtx }
+if($doNpm){ Invoke-NpmScan }
+
+Write-Host ''
+Write-Host '================ PLAN ================' -ForegroundColor Cyan
+Write-Host (" Changes : {0}" -f $Changes.Count)
+Write-Host (" Major : {0}" -f @($Changes | Where-Object { $_.IsMajor }).Count)
+Write-Host (" Frozen : {0}" -f $Frozen.Count)
+Write-Host (" Errors : {0}" -f $ScanErrors.Count)
+Write-Host '=====================================' -ForegroundColor Cyan
+
+if($DryRun){
+ Write-Warn '[DRY RUN] No changes written. Review the report below.'
+ $reportPath = Write-Report -Stamp $stamp
+ if($ScanErrors.Count -gt 0){ Write-Warn "$($ScanErrors.Count) scan error(s) - see report." }
+ exit 0
+}
+
+if($Changes.Count -eq 0){
+ Write-Info 'Nothing to update; everything already at latest stable.'
+ Write-Report -Stamp $stamp | Out-Null
+ exit 0
+}
+
+# Apply everything, then verify.
+$dirs = Write-FileSet -ActiveChanges @($Changes)
+Update-NpmLockfiles -NpmDirs $dirs
+Write-Info "Applied $($Changes.Count) change(s) to the working tree."
+
+if(-not $SkipBuild){
+ if(Invoke-CakeBuild){
+ $BuildResult = 'pass'
+ Write-Info 'Build passed with all changes.'
+ } elseif($RollbackAllOnFailure){
+ Write-Warn 'Build failed; -RollbackAllOnFailure set, reverting everything.'
+ foreach($c in $Changes){ [void]$Reverted.Add($c) }
+ Write-FileSet -ActiveChanges @() | Out-Null
+ $BuildResult = 'FAIL (all changes rolled back)'
+ } else {
+ Invoke-BisectGreenSubset
+ }
+} else {
+ $BuildResult = 'skipped (-SkipBuild)'
+ Write-Warn 'Build verification skipped (-SkipBuild).'
+}
+
+$reportPath = Write-Report -Stamp $stamp
+
+Write-Host ''
+Write-Host '================ SUMMARY ================' -ForegroundColor Cyan
+Write-Host (" Applied : {0}" -f @($Changes | Where-Object { $Reverted -notcontains $_ }).Count)
+Write-Host (" Reverted : {0}" -f $Reverted.Count)
+Write-Host (" Frozen : {0}" -f $Frozen.Count)
+Write-Host (" Build : {0}" -f $BuildResult)
+Write-Host (" Errors : {0}" -f $ScanErrors.Count)
+Write-Host '========================================' -ForegroundColor Cyan
+
+if($CreatePR){
+ if(@($Changes | Where-Object { $Reverted -notcontains $_ }).Count -gt 0){ Invoke-CreatePR -ReportPath $reportPath }
+ else { Write-Warn 'No surviving changes; skipping PR creation.' }
+}
+
+if($BuildResult -like 'FAIL*'){ exit 1 }
+exit 0
diff --git a/scripts/update-vulnerable-deps.ps1 b/scripts/update-vulnerable-deps.ps1
new file mode 100644
index 00000000..477b2833
--- /dev/null
+++ b/scripts/update-vulnerable-deps.ps1
@@ -0,0 +1,593 @@
+#!/usr/bin/env pwsh
+<#
+.SYNOPSIS
+Scans the whole repository for vulnerable npm and NuGet dependencies and applies safe fixes.
+
+.DESCRIPTION
+One command to remediate moderate-and-above security advisories across both ecosystems:
+
+ NuGet - iterates every .csproj, restores it, runs `dotnet list package --vulnerable
+ --include-transitive`, dedupes advisories, SKIPS AXSharp.*/Inxton.Operon.* (those are
+ owned by scripts/update_axsharp_versions.ps1), resolves the minimum safe version from
+ the GitHub Advisory Database, and writes the bump to Directory.Packages.props
+ (direct = bump in place, transitive = add a new pinned ).
+
+ npm - audits the 6 source package.json projects (installing node_modules when missing) and
+ runs `npm audit fix` (safe, no --force). Advisories that would need a breaking major
+ bump are reported as unfixed.
+
+A timestamped Markdown + JSON report is written to scripts/reports/. With -CreatePR the changes
+are committed to branch 'fix/vulnerable-dependencies' off dev and a PR is opened against dev.
+
+Exit code is non-zero when vulnerabilities at/above -MinSeverity remain unfixed, so CI can gate on
+it.
+
+.PARAMETER DryRun
+Preview everything; make no file changes, no commits, no PR. (Still exits non-zero if vulns found.)
+
+.PARAMETER NpmOnly
+Scan/fix npm only.
+
+.PARAMETER NuGetOnly
+Scan/fix NuGet only.
+
+.PARAMETER CreatePR
+Commit fixes to branch 'fix/vulnerable-dependencies' off origin/dev and open a PR against dev.
+Cannot be combined with -DryRun.
+
+.PARAMETER MinSeverity
+Lowest severity to act on: low | moderate | high | critical. Default: moderate.
+
+.PARAMETER Source
+NuGet v3 feed used to look up available versions (public packages). Default nuget.org.
+
+.PARAMETER Token
+Token for the GitHub Advisory API (avoids rate limits). Falls back to NUGET_TOKEN /
+GITHUB_PACKAGES_TOKEN / GITHUB_TOKEN / GH_TOKEN.
+
+.PARAMETER Detailed
+Verbose logging.
+
+.EXAMPLE
+./update-vulnerable-deps.ps1 -DryRun -Detailed
+
+.EXAMPLE
+./update-vulnerable-deps.ps1 -NuGetOnly
+
+.EXAMPLE
+./update-vulnerable-deps.ps1 -CreatePR
+#>
+
+[CmdletBinding()]
+param(
+ [switch]$DryRun,
+ [switch]$NpmOnly,
+ [switch]$NuGetOnly,
+ [switch]$CreatePR,
+ [ValidateSet('low','moderate','high','critical')]
+ [string]$MinSeverity = 'low',
+ [string]$Source = 'https://api.nuget.org/v3/index.json',
+ [string]$Token,
+ [switch]$Detailed
+)
+
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+
+$scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
+. "$scriptRoot/_deps-common.ps1"
+
+$repoRoot = Split-Path -Parent $scriptRoot
+$propsPath = Join-Path $repoRoot 'Directory.Packages.props'
+
+# ---------------------------------------------------------------------------
+# Validation & constants
+# ---------------------------------------------------------------------------
+if($DryRun -and $CreatePR){ Write-Err '-DryRun and -CreatePR cannot be combined.'; exit 1 }
+if($NpmOnly -and $NuGetOnly){ Write-Err '-NpmOnly and -NuGetOnly cannot be combined.'; exit 1 }
+
+$doNuget = -not $NpmOnly
+$doNpm = -not $NuGetOnly
+
+$SeverityRank = @{ low = 1; moderate = 2; high = 3; critical = 4 }
+$minRank = $SeverityRank[$MinSeverity]
+
+# Packages owned by update_axsharp_versions.ps1 - never touched here.
+$SkipPattern = '^(AXSharp|Inxton\.Operon|AXOpen)\b'
+
+$Token = Resolve-FeedToken -Token $Token -Detailed:$Detailed
+
+# Source npm projects - discovered dynamically under src/ (skips node_modules and
+# bin/obj/ctrl generated copies so only first-party source manifests are audited).
+$NpmProjects = @(
+ Get-ChildItem -Path (Join-Path $repoRoot 'src') -Recurse -File -Filter 'package.json' -ErrorAction SilentlyContinue |
+ Where-Object { $_.FullName -notmatch '[\\/](node_modules|bin|obj|ctrl)[\\/]' } |
+ ForEach-Object { $_.FullName } |
+ Sort-Object
+)
+
+# Accumulators for the report.
+$NuGetFixed = New-Object System.Collections.ArrayList
+$NuGetSkipped = New-Object System.Collections.ArrayList
+$NuGetUnfixed = New-Object System.Collections.ArrayList
+$NpmResults = New-Object System.Collections.ArrayList
+$ScanErrors = New-Object System.Collections.ArrayList
+
+# ---------------------------------------------------------------------------
+# Helpers
+# ---------------------------------------------------------------------------
+function Test-CommandAvailable {
+ param([string]$Name)
+ $null -ne (Get-Command $Name -ErrorAction SilentlyContinue)
+}
+
+function Get-GhsaIdFromUrl {
+ param([string]$Url)
+ if($Url -and ($Url -match '(GHSA-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4})')){ return $Matches[1] }
+ return $null
+}
+
+$script:AdvisoryCache = @{}
+function Get-AdvisoryPatchedVersion {
+ # Queries the GitHub Advisory Database for the first patched version of $PackageId.
+ # Returns the patched version string, or $null when it cannot be determined.
+ param([string]$GhsaId,[string]$PackageId)
+ if(-not $GhsaId){ return $null }
+ if(-not $script:AdvisoryCache.ContainsKey($GhsaId)){
+ $headers = @{ 'User-Agent' = 'axopen-update-vulnerable-deps'; 'Accept' = 'application/vnd.github+json' }
+ if($Token){ $headers['Authorization'] = "Bearer $Token" }
+ try {
+ $script:AdvisoryCache[$GhsaId] = Invoke-RestMethod -Uri "https://api.github.com/advisories/$GhsaId" -Headers $headers -TimeoutSec 30
+ } catch {
+ if($Detailed){ Write-Warn "Advisory lookup failed for ${GhsaId}: $($_.Exception.Message)" }
+ $script:AdvisoryCache[$GhsaId] = $null
+ }
+ }
+ $adv = $script:AdvisoryCache[$GhsaId]
+ if(-not $adv -or -not $adv.vulnerabilities){ return $null }
+ foreach($v in $adv.vulnerabilities){
+ if($v.package -and $v.package.ecosystem -eq 'nuget' -and $v.package.name -and ($v.package.name.ToLower() -eq $PackageId.ToLower())){
+ $fpv = $v.first_patched_version
+ if($null -eq $fpv){ return $null }
+ if($fpv -is [string]){ return $fpv }
+ if($fpv.PSObject.Properties.Name -contains 'identifier'){ return $fpv.identifier }
+ }
+ }
+ return $null
+}
+
+function Resolve-SafeNuGetVersion {
+ # Determines the minimum safe version for a vulnerable package:
+ # 1. the highest 'first patched version' across the package's advisories, then
+ # 2. snapped up to the lowest version actually available on the feed that is >= that patch
+ # and strictly greater than the current resolved version.
+ # Returns $null (=> report as unfixed) when no safe version can be determined.
+ param([string]$PackageId,[string]$CurrentVersion,[string[]]$GhsaIds,$FeedCtx)
+ $patched = $null
+ foreach($g in $GhsaIds){
+ $p = Get-AdvisoryPatchedVersion -GhsaId $g -PackageId $PackageId
+ if($p -and (Test-VersionGreater $p $patched)){ $patched = $p }
+ }
+ if(-not $patched){ return $null }
+
+ $available = @()
+ try { $available = Get-PackageVersionsFromFeed -PkgBase $FeedCtx.PkgBase -Headers $FeedCtx.Headers -PackageId $PackageId } catch { $available = @() }
+ if(-not $available -or $available.Count -eq 0){
+ # Feed gave us nothing; trust the advisory's patched version if it improves on current.
+ if(Test-VersionGreater $patched $CurrentVersion){ return $patched } else { return $null }
+ }
+
+ $currentIsPre = Test-IsPrerelease $CurrentVersion
+ $candidates = $available |
+ Where-Object { ($currentIsPre) -or (-not (Test-IsPrerelease $_)) } | # stable only unless current is pre
+ Where-Object { (Test-VersionGreater $_ $CurrentVersion) -and -not (Test-VersionGreater $patched $_) } # > current AND >= patched
+
+ if(-not $candidates -or @($candidates).Count -eq 0){ return $null }
+
+ # lowest such candidate = minimum safe bump
+ $best = @($candidates)[0]
+ foreach($c in $candidates){ if(Test-VersionGreater $best $c){ $best = $c } }
+ return $best
+}
+
+# ---------------------------------------------------------------------------
+# Directory.Packages.props editing
+# ---------------------------------------------------------------------------
+function Update-PropsDirect {
+ # Bumps an existing in place.
+ # Returns updated content, or $null if the package id was not found.
+ param([string]$Content,[string]$PackageId,[string]$NewVersion)
+ $idEsc = [regex]::Escape($PackageId)
+ # Include before Version (repo convention)
+ $rx1 = "(]*\bInclude=`"$idEsc`"[^>]*\bVersion=`")[^`"]*(`")"
+ if([regex]::IsMatch($Content,$rx1)){
+ return [regex]::Replace($Content,$rx1,"`${1}$NewVersion`${2}",1)
+ }
+ # Version before Include (defensive)
+ $rx2 = "(]*\bVersion=`")[^`"]*(`"[^>]*\bInclude=`"$idEsc`")"
+ if([regex]::IsMatch($Content,$rx2)){
+ return [regex]::Replace($Content,$rx2,"`${1}$NewVersion`${2}",1)
+ }
+ return $null
+}
+
+function Test-PropsHasPackage {
+ param([string]$Content,[string]$PackageId)
+ $idEsc = [regex]::Escape($PackageId)
+ return [regex]::IsMatch($Content,"]*\bInclude=`"$idEsc`"")
+}
+
+function Add-PropsTransitivePin {
+ # Adds a into a managed "security pins" ItemGroup, creating it before
+ # if absent. Returns updated content.
+ param([string]$Content,[string]$PackageId,[string]$NewVersion)
+ $marker = ''
+ $entry = " "
+ if($Content.Contains($marker)){
+ # Insert as the first entry inside the existing managed ItemGroup.
+ $rx = [regex]::Escape($marker) + "(\r?\n\s*)"
+ return [regex]::Replace($Content,$rx,"`$0`r`n$entry",1)
+ }
+ $block = " $marker`r`n `r`n$entry`r`n `r`n"
+ return ($Content -replace '\s*$',$block)
+}
+
+# ---------------------------------------------------------------------------
+# NuGet scan & fix
+# ---------------------------------------------------------------------------
+function Invoke-NuGetScan {
+ Write-Info 'Scanning NuGet dependencies...'
+ if(-not (Test-CommandAvailable 'dotnet')){ Write-Err 'dotnet CLI not found on PATH.'; [void]$ScanErrors.Add('dotnet CLI not found'); return }
+
+ $csprojFiles = Get-ChildItem -Path (Join-Path $repoRoot 'src') -Recurse -Filter '*.csproj' -ErrorAction SilentlyContinue |
+ Where-Object { $_.FullName -notmatch '[\\/](bin|obj)[\\/]' }
+ # Include the cake build project (ships in the repo).
+ $cakeProj = Get-ChildItem -Path (Join-Path $repoRoot 'cake') -Recurse -Filter '*.csproj' -ErrorAction SilentlyContinue |
+ Where-Object { $_.FullName -notmatch '[\\/](bin|obj)[\\/]' }
+ $csprojFiles = @($csprojFiles) + @($cakeProj)
+
+ Write-Info "Found $($csprojFiles.Count) project(s) to scan."
+
+ # packageId -> aggregated advisory record
+ $vuln = @{}
+ $total = $csprojFiles.Count
+ $i = 0
+ foreach($proj in $csprojFiles){
+ $i++
+ $pct = if($total -gt 0){ [int](($i-1) / $total * 100) } else { 0 }
+ Write-Progress -Activity 'Scanning NuGet projects' `
+ -Status ("[$i/$total] $($proj.Name) - $($vuln.Count) vulnerable package(s) so far") `
+ -CurrentOperation 'restoring...' -PercentComplete $pct
+ if($Detailed){ Write-Info "[$i/$total] $($proj.FullName)" }
+ try {
+ & dotnet restore $proj.FullName --nologo *> $null
+ } catch {
+ [void]$ScanErrors.Add("restore failed: $($proj.FullName)")
+ if($Detailed){ Write-Warn "restore failed: $($proj.Name)" }
+ continue
+ }
+ Write-Progress -Activity 'Scanning NuGet projects' `
+ -Status ("[$i/$total] $($proj.Name) - $($vuln.Count) vulnerable package(s) so far") `
+ -CurrentOperation 'listing vulnerabilities...' -PercentComplete $pct
+ $raw = & dotnet list $proj.FullName package --vulnerable --include-transitive --format json 2>$null | Out-String
+ if(-not $raw.Trim()){ continue }
+ try { $parsed = $raw | ConvertFrom-Json } catch { [void]$ScanErrors.Add("unparseable output: $($proj.FullName)"); continue }
+ if(-not ($parsed.PSObject.Properties.Name -contains 'projects')){ continue }
+ foreach($p in $parsed.projects){
+ if(-not ($p.PSObject.Properties.Name -contains 'frameworks') -or -not $p.frameworks){ continue }
+ foreach($fw in $p.frameworks){
+ foreach($kind in @('topLevelPackages','transitivePackages')){
+ if(-not ($fw.PSObject.Properties.Name -contains $kind) -or -not $fw.$kind){ continue }
+ $isDirect = ($kind -eq 'topLevelPackages')
+ foreach($pkg in $fw.$kind){
+ if(-not ($pkg.PSObject.Properties.Name -contains 'vulnerabilities') -or -not $pkg.vulnerabilities){ continue }
+ $id = $pkg.id
+ $resolved = $pkg.resolvedVersion
+ foreach($adv in $pkg.vulnerabilities){
+ $sev = ("$($adv.severity)").ToLower()
+ $rank = if($SeverityRank.ContainsKey($sev)){ $SeverityRank[$sev] } else { 0 }
+ if($rank -lt $minRank){ continue }
+ $url = if($adv.PSObject.Properties.Name -contains 'advisoryurl'){ $adv.advisoryurl } else { '' }
+ if(-not $vuln.ContainsKey($id)){
+ $vuln[$id] = [PSCustomObject]@{
+ Id=$id; Resolved=$resolved; IsDirect=$isDirect; MaxRank=$rank;
+ Severity=$sev; Urls=(New-Object System.Collections.ArrayList); Projects=(New-Object System.Collections.ArrayList)
+ }
+ }
+ $rec = $vuln[$id]
+ if($isDirect){ $rec.IsDirect = $true }
+ if($rank -gt $rec.MaxRank){ $rec.MaxRank = $rank; $rec.Severity = $sev }
+ if($url -and -not $rec.Urls.Contains($url)){ [void]$rec.Urls.Add($url) }
+ if(-not $rec.Projects.Contains($proj.Name)){ [void]$rec.Projects.Add($proj.Name) }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Write-Progress -Activity 'Scanning NuGet projects' -Completed
+
+ if($vuln.Count -eq 0){ Write-Info 'No NuGet vulnerabilities at/above the threshold.'; return }
+ Write-Info "Found $($vuln.Count) vulnerable NuGet package(s) at/above '$MinSeverity'."
+
+ # Resolve safe versions & apply.
+ $feedCtx = $null
+ try { $feedCtx = Get-FeedContext -Feed $Source -Tok $null } catch { Write-Warn "Could not initialise NuGet feed context: $($_.Exception.Message)" }
+
+ $content = Get-Content -LiteralPath $propsPath -Raw
+ $changed = $false
+
+ foreach($id in ($vuln.Keys | Sort-Object)){
+ $rec = $vuln[$id]
+ if($id -match $SkipPattern){
+ [void]$NuGetSkipped.Add([PSCustomObject]@{ Id=$id; Current=$rec.Resolved; Severity=$rec.Severity; Reason='skipped-AXSharp (owned by update_axsharp_versions.ps1)' })
+ continue
+ }
+ $ghsaIds = @($rec.Urls | ForEach-Object { Get-GhsaIdFromUrl $_ } | Where-Object { $_ })
+ $safe = $null
+ if($feedCtx){ $safe = Resolve-SafeNuGetVersion -PackageId $id -CurrentVersion $rec.Resolved -GhsaIds $ghsaIds -FeedCtx $feedCtx }
+
+ if(-not $safe){
+ [void]$NuGetUnfixed.Add([PSCustomObject]@{ Id=$id; Current=$rec.Resolved; Severity=$rec.Severity; Direct=$rec.IsDirect; Advisories=($rec.Urls -join ' '); Reason='no safe version determined (manual review)' })
+ continue
+ }
+
+ $action = $null
+ if(Test-PropsHasPackage -Content $content -PackageId $id){
+ $updated = Update-PropsDirect -Content $content -PackageId $id -NewVersion $safe
+ if($updated){ $content = $updated; $action = 'bumped (direct)' }
+ } else {
+ $content = Add-PropsTransitivePin -Content $content -PackageId $id -NewVersion $safe
+ $action = 'pinned (transitive)'
+ }
+ if($action){
+ $changed = $true
+ [void]$NuGetFixed.Add([PSCustomObject]@{ Id=$id; From=$rec.Resolved; To=$safe; Severity=$rec.Severity; Direct=$rec.IsDirect; Action=$action; Advisories=($rec.Urls -join ' ') })
+ Write-Info (" {0}: {1} -> {2} [{3}]" -f $id,$rec.Resolved,$safe,$action)
+ } else {
+ [void]$NuGetUnfixed.Add([PSCustomObject]@{ Id=$id; Current=$rec.Resolved; Severity=$rec.Severity; Direct=$rec.IsDirect; Advisories=($rec.Urls -join ' '); Reason='could not edit Directory.Packages.props' })
+ }
+ }
+
+ if($changed){
+ if($DryRun){
+ Write-Warn '[DRY RUN] Directory.Packages.props would be updated (not written).'
+ } else {
+ Write-Utf8NoBom-LF -Path $propsPath -Content $content
+ Write-Info 'Directory.Packages.props updated.'
+ }
+ }
+}
+
+# ---------------------------------------------------------------------------
+# npm scan & fix
+# ---------------------------------------------------------------------------
+function Get-NpmCountsAtOrAbove {
+ param($AuditObj)
+ $total = 0
+ if($AuditObj -and $AuditObj.PSObject.Properties.Name -contains 'metadata' -and $AuditObj.metadata.PSObject.Properties.Name -contains 'vulnerabilities'){
+ $v = $AuditObj.metadata.vulnerabilities
+ foreach($sev in @('moderate','high','critical')){
+ if($SeverityRank[$sev] -ge $minRank -and ($v.PSObject.Properties.Name -contains $sev)){ $total += [int]$v.$sev }
+ }
+ if($minRank -le 1 -and ($v.PSObject.Properties.Name -contains 'low')){ $total += [int]$v.low }
+ }
+ return $total
+}
+
+function Invoke-NpmScan {
+ Write-Info 'Scanning npm dependencies...'
+ if(-not (Test-CommandAvailable 'npm')){ Write-Err 'npm not found on PATH.'; [void]$ScanErrors.Add('npm not found'); return }
+
+ $npmTotal = $NpmProjects.Count
+ $npmIdx = 0
+ foreach($pkgJson in $NpmProjects){
+ $npmIdx++
+ if(-not (Test-Path -LiteralPath $pkgJson)){ if($Detailed){ Write-Warn "missing: $pkgJson" }; continue }
+ $dir = Split-Path -Parent $pkgJson
+ $name = (Resolve-Path -LiteralPath $dir).Path.Replace((Resolve-Path $repoRoot).Path,'').TrimStart('\','/')
+ Write-Progress -Activity 'Scanning npm projects' -Status "[$npmIdx/$npmTotal] $name" `
+ -PercentComplete ([int](($npmIdx-1) / $npmTotal * 100))
+ Write-Info " $name"
+ Push-Location $dir
+ try {
+ if(-not (Test-Path 'node_modules')){
+ if($DryRun){ Write-Warn " [DRY RUN] would run: npm install" }
+ else { & npm install --no-audit --no-fund *> $null }
+ }
+
+ $beforeRaw = & npm audit --json 2>$null | Out-String
+ $before = $null; try { $before = $beforeRaw | ConvertFrom-Json } catch {}
+ $beforeCount = Get-NpmCountsAtOrAbove $before
+
+ if($beforeCount -le 0){
+ [void]$NpmResults.Add([PSCustomObject]@{ Project=$name; Before=0; After=0; Fixed=0; Note='clean' })
+ Pop-Location; continue
+ }
+
+ if($DryRun){
+ Write-Warn " [DRY RUN] would run: npm audit fix ($beforeCount vuln >= $MinSeverity)"
+ [void]$NpmResults.Add([PSCustomObject]@{ Project=$name; Before=$beforeCount; After=$beforeCount; Fixed=0; Note='dry-run (not fixed)' })
+ Pop-Location; continue
+ }
+
+ & npm audit fix *> $null
+ $afterRaw = & npm audit --json 2>$null | Out-String
+ $after = $null; try { $after = $afterRaw | ConvertFrom-Json } catch {}
+ $afterCount = Get-NpmCountsAtOrAbove $after
+ $note = if($afterCount -gt 0){ "$afterCount remain (need --force / breaking major)" } else { 'all fixed' }
+ [void]$NpmResults.Add([PSCustomObject]@{ Project=$name; Before=$beforeCount; After=$afterCount; Fixed=($beforeCount-$afterCount); Note=$note })
+ Write-Info (" before={0} after={1} ({2})" -f $beforeCount,$afterCount,$note)
+ } catch {
+ [void]$ScanErrors.Add("npm error in ${name}: $($_.Exception.Message)")
+ Write-Warn " error: $($_.Exception.Message)"
+ } finally {
+ Pop-Location
+ }
+ }
+ Write-Progress -Activity 'Scanning npm projects' -Completed
+}
+
+# ---------------------------------------------------------------------------
+# Report
+# ---------------------------------------------------------------------------
+function Write-Report {
+ param([string]$Stamp)
+ $reportsDir = Join-Path $scriptRoot 'reports'
+ if(-not (Test-Path $reportsDir)){ New-Item -ItemType Directory -Path $reportsDir -Force | Out-Null }
+ $mdPath = Join-Path $reportsDir "vuln-report-$Stamp.md"
+ $jsonPath = Join-Path $reportsDir "vuln-report-$Stamp.json"
+
+ $payload = [PSCustomObject]@{
+ timestamp = $Stamp
+ minSeverity = $MinSeverity
+ dryRun = [bool]$DryRun
+ ecosystems = @{ nuget = [bool]$doNuget; npm = [bool]$doNpm }
+ nuget = @{ fixed = $NuGetFixed; skipped = $NuGetSkipped; unfixed = $NuGetUnfixed }
+ npm = $NpmResults
+ scanErrors = $ScanErrors
+ }
+ Write-Utf8NoBom-LF -Path $jsonPath -Content ($payload | ConvertTo-Json -Depth 8)
+
+ $sb = New-Object System.Text.StringBuilder
+ [void]$sb.AppendLine("# Vulnerable dependency report")
+ [void]$sb.AppendLine("")
+ [void]$sb.AppendLine("- Generated: $Stamp")
+ [void]$sb.AppendLine("- Min severity: **$MinSeverity**")
+ [void]$sb.AppendLine("- Dry run: $([bool]$DryRun)")
+ [void]$sb.AppendLine("- Ecosystems: NuGet=$doNuget, npm=$doNpm")
+ [void]$sb.AppendLine("")
+ if($doNuget){
+ [void]$sb.AppendLine("## NuGet")
+ [void]$sb.AppendLine("")
+ [void]$sb.AppendLine("### Fixed ($($NuGetFixed.Count))")
+ [void]$sb.AppendLine("| Package | From | To | Severity | Kind | Action |")
+ [void]$sb.AppendLine("|---|---|---|---|---|---|")
+ foreach($f in $NuGetFixed){ [void]$sb.AppendLine("| $($f.Id) | $($f.From) | $($f.To) | $($f.Severity) | $(if($f.Direct){'direct'}else{'transitive'}) | $($f.Action) |") }
+ [void]$sb.AppendLine("")
+ [void]$sb.AppendLine("### Unfixed - manual review ($($NuGetUnfixed.Count))")
+ [void]$sb.AppendLine("| Package | Current | Severity | Reason | Advisories |")
+ [void]$sb.AppendLine("|---|---|---|---|---|")
+ foreach($u in $NuGetUnfixed){ [void]$sb.AppendLine("| $($u.Id) | $($u.Current) | $($u.Severity) | $($u.Reason) | $($u.Advisories) |") }
+ [void]$sb.AppendLine("")
+ [void]$sb.AppendLine("### Skipped ($($NuGetSkipped.Count))")
+ foreach($s in $NuGetSkipped){ [void]$sb.AppendLine("- $($s.Id) ($($s.Current), $($s.Severity)) - $($s.Reason)") }
+ [void]$sb.AppendLine("")
+ }
+ if($doNpm){
+ [void]$sb.AppendLine("## npm")
+ [void]$sb.AppendLine("")
+ [void]$sb.AppendLine("| Project | Before | After | Fixed | Note |")
+ [void]$sb.AppendLine("|---|---|---|---|---|")
+ foreach($n in $NpmResults){ [void]$sb.AppendLine("| $($n.Project) | $($n.Before) | $($n.After) | $($n.Fixed) | $($n.Note) |") }
+ [void]$sb.AppendLine("")
+ }
+ if($ScanErrors.Count -gt 0){
+ [void]$sb.AppendLine("## Scan errors")
+ foreach($e in $ScanErrors){ [void]$sb.AppendLine("- $e") }
+ }
+ Write-Utf8NoBom-LF -Path $mdPath -Content $sb.ToString()
+
+ Write-Info "Report: $mdPath"
+ return $mdPath
+}
+
+# ---------------------------------------------------------------------------
+# Commit + PR
+# ---------------------------------------------------------------------------
+function Invoke-CreatePR {
+ param([string]$ReportPath)
+ if(-not (Test-CommandAvailable 'git')){ Write-Err 'git not found; cannot create PR.'; return }
+ if(-not (Test-CommandAvailable 'gh')){ Write-Err 'gh CLI not found; cannot open PR.'; return }
+
+ $branch = 'fix/vulnerable-dependencies'
+ Write-Info "Creating branch '$branch' off origin/dev and opening PR..."
+
+ & git -C $repoRoot fetch origin dev --quiet
+ # Carry working-tree fixes onto a fresh branch from origin/dev.
+ & git -C $repoRoot stash push -u -m 'vuln-fix-wip' *> $null
+ $stashed = ($LASTEXITCODE -eq 0)
+ & git -C $repoRoot switch -C $branch origin/dev
+ if($LASTEXITCODE -ne 0){ Write-Err "Failed to create branch $branch."; if($stashed){ & git -C $repoRoot stash pop *> $null }; return }
+ if($stashed){
+ & git -C $repoRoot stash pop
+ if($LASTEXITCODE -ne 0){ Write-Err 'Stash pop conflicted; resolve manually. Aborting PR.'; return }
+ }
+
+ & git -C $repoRoot add -- 'Directory.Packages.props' '**/package.json' '**/package-lock.json'
+ & git -C $repoRoot commit -m @'
+fix(deps): remediate moderate+ npm & NuGet vulnerabilities
+
+Automated by scripts/update-vulnerable-deps.ps1.
+
+Co-Authored-By: Claude Opus 4.8 (1M context)
+'@
+ if($LASTEXITCODE -ne 0){ Write-Warn 'Nothing to commit (no changes staged). Skipping PR.'; return }
+
+ & git -C $repoRoot push -u origin $branch
+ if($LASTEXITCODE -ne 0){ Write-Err 'git push failed.'; return }
+
+ $fixedLines = ($NuGetFixed | ForEach-Object { "- NuGet $($_.Id): $($_.From) -> $($_.To) ($($_.Severity))" }) -join "`n"
+ $npmLines = ($NpmResults | Where-Object { $_.Fixed -gt 0 } | ForEach-Object { "- npm $($_.Project): fixed $($_.Fixed)" }) -join "`n"
+ $unfixed = ($NuGetUnfixed | ForEach-Object { "- $($_.Id) ($($_.Severity)): $($_.Reason)" }) -join "`n"
+ $body = @"
+Automated remediation of moderate-and-above npm & NuGet vulnerabilities.
+
+## Fixed
+$fixedLines
+$npmLines
+
+## Needs manual review
+$unfixed
+
+See the attached report ($([System.IO.Path]::GetFileName($ReportPath))) for full detail.
+
+🤖 Generated with [Claude Code](https://claude.com/claude-code)
+"@
+ & gh pr create --base dev --head $branch --title 'fix(deps): remediate moderate+ npm & NuGet vulnerabilities' --body $body
+ if($LASTEXITCODE -ne 0){ Write-Err 'gh pr create failed.' } else { Write-Info 'PR opened against dev.' }
+}
+
+# ---------------------------------------------------------------------------
+# Main
+# ---------------------------------------------------------------------------
+$stamp = (Get-Date).ToString('yyyy-MM-dd-HHmmss')
+Write-Info "update-vulnerable-deps (minSeverity=$MinSeverity, dryRun=$DryRun, npm=$doNpm, nuget=$doNuget)"
+
+if($doNuget){ Invoke-NuGetScan }
+if($doNpm){ Invoke-NpmScan }
+
+$reportPath = Write-Report -Stamp $stamp
+
+# Determine unfixed count for exit code.
+$npmRemaining = ($NpmResults | Measure-Object -Property After -Sum).Sum
+if($null -eq $npmRemaining){ $npmRemaining = 0 }
+$unfixedCount = $NuGetUnfixed.Count + [int]$npmRemaining
+
+Write-Host ''
+Write-Host '================ SUMMARY ================' -ForegroundColor Cyan
+Write-Host (" NuGet fixed : {0}" -f $NuGetFixed.Count)
+Write-Host (" NuGet skipped : {0}" -f $NuGetSkipped.Count)
+Write-Host (" NuGet unfixed : {0}" -f $NuGetUnfixed.Count)
+Write-Host (" npm projects : {0}" -f $NpmResults.Count)
+Write-Host (" npm remaining : {0}" -f $npmRemaining)
+Write-Host (" scan errors : {0}" -f $ScanErrors.Count)
+Write-Host '========================================' -ForegroundColor Cyan
+
+if($CreatePR -and -not $DryRun){
+ if($NuGetFixed.Count -gt 0 -or ($NpmResults | Where-Object { $_.Fixed -gt 0 })){
+ Invoke-CreatePR -ReportPath $reportPath
+ } else {
+ Write-Warn 'No fixes applied; skipping PR creation.'
+ }
+}
+
+if($ScanErrors.Count -gt 0){ Write-Warn "$($ScanErrors.Count) scan error(s) - see report." }
+
+if($unfixedCount -gt 0){
+ Write-Warn "$unfixedCount vulnerability/vulnerabilities remain unfixed."
+ exit 1
+}
+Write-Info 'No outstanding vulnerabilities at/above threshold.'
+exit 0
diff --git a/src/AXSharp.blazor/src/AXSharp.Presentation.Blazor.Controls/package-lock.json b/src/AXSharp.blazor/src/AXSharp.Presentation.Blazor.Controls/package-lock.json
index eaf7cbe6..f175487f 100644
--- a/src/AXSharp.blazor/src/AXSharp.Presentation.Blazor.Controls/package-lock.json
+++ b/src/AXSharp.blazor/src/AXSharp.Presentation.Blazor.Controls/package-lock.json
@@ -4,6 +4,7 @@
"requires": true,
"packages": {
"": {
+ "name": "AXSharp.Presentation.Blazor.Controls",
"dependencies": {
"@tailwindcss/cli": "^4.1.18",
"tailwindcss": "^4.1.18"
@@ -1006,9 +1007,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"license": "MIT",
"engines": {
"node": ">=8.6"
diff --git a/src/AXSharp.blazor/tests/sandbox/IxBlazor.App/package-lock.json b/src/AXSharp.blazor/tests/sandbox/IxBlazor.App/package-lock.json
index b989b096..82f2b1ba 100644
--- a/src/AXSharp.blazor/tests/sandbox/IxBlazor.App/package-lock.json
+++ b/src/AXSharp.blazor/tests/sandbox/IxBlazor.App/package-lock.json
@@ -4,6 +4,7 @@
"requires": true,
"packages": {
"": {
+ "name": "IxBlazor.App",
"dependencies": {
"@tailwindcss/cli": "^4.1.17",
"tailwindcss": "^4.1.17"
@@ -1006,9 +1007,9 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"license": "MIT",
"engines": {
"node": ">=8.6"
diff --git a/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/Helpers/SourceFileAttributeHelper.cs b/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/Helpers/SourceFileAttributeHelper.cs
new file mode 100644
index 00000000..4283dcc6
--- /dev/null
+++ b/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/Helpers/SourceFileAttributeHelper.cs
@@ -0,0 +1,36 @@
+// AXSharp.Compiler.Cs
+// Copyright (c) 2023 MTS spol. s r.o., and Contributors. All Rights Reserved.
+// Contributors: https://github.com/inxton/axsharp/graphs/contributors
+// See the LICENSE file in the repository root for more information.
+// https://github.com/inxton/axsharp/blob/dev/LICENSE
+// Third party licenses: https://github.com/inxton/axsharp/blob/master/notices.md
+
+using System.IO;
+using AX.ST.Semantic;
+using AX.ST.Semantic.Model;
+using AX.ST.Semantic.Model.Declarations;
+using AX.ST.Semantic.Model.Declarations.Types;
+
+namespace AXSharp.Compiler.Cs.Helpers;
+
+///
+/// Helpers for emitting the AXSharp.Connector.SourceFileAttribute onto generated types.
+///
+public static class SourceFileAttributeHelper
+{
+ ///
+ /// Produces the [AXSharp.Connector.SourceFileAttribute(...)] declaration for the given type,
+ /// carrying the source file path relative to the project src folder (forward-slash separated).
+ /// Returns an empty string when the declaration has no source location (e.g. types parsed from
+ /// dependency metadata), making emission a safe no-op.
+ ///
+ public static string GetSourceFileAttribute(this ITypeDeclaration declaration, AxProject axProject)
+ {
+ var filename = declaration.Location?.GetLineSpan().Filename;
+ if (string.IsNullOrEmpty(filename))
+ return string.Empty;
+
+ var relative = Path.GetRelativePath(axProject.SrcFolder, filename).Replace('\\', '/');
+ return $"[AXSharp.Connector.SourceFileAttribute(@\"{relative}\")]\n";
+ }
+}
diff --git a/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/Onliner/CsOnlinerSourceBuilder.cs b/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/Onliner/CsOnlinerSourceBuilder.cs
index 61ca236f..516a090a 100644
--- a/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/Onliner/CsOnlinerSourceBuilder.cs
+++ b/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/Onliner/CsOnlinerSourceBuilder.cs
@@ -151,6 +151,7 @@ public void CreateClassDeclaration(IClassDeclarationSyntax classDeclarationSynta
classDeclarationSyntax.UsingDirectives.ToList().ForEach(p => p.Visit(visitor, this));
var generic = classDeclaration.GetGenericAttributes();
+ AddToSource(classDeclaration.GetSourceFileAttribute(Project.AxProject));
AddToSource(classDeclaration.Pragmas.AddAttributes());
AddToSource($"{classDeclaration.AccessModifier.Transform()}partial class {classDeclaration.Name}{generic?.Product}");
AddToSource(":");
@@ -287,6 +288,7 @@ public void CreateEnumTypeDeclaration(IEnumTypeDeclarationSyntax enumTypeDeclara
{
TypeCommAccessibility = eCommAccessibility.None;
+ AddToSource(typeDeclaration.GetSourceFileAttribute(Project.AxProject));
AddToSource($"public enum {enumTypeDeclarationSyntax.Name.Text} {{");
AddToSource(string.Join("\n,", enumTypeDeclarationSyntax.EnumValueList.EnumValues.Select(p => p.Name.Text)));
AddToSource("}");
@@ -298,6 +300,7 @@ public void CreateNamedValueTypeDeclaration(INamedValueTypeDeclarationSyntax nam
{
TypeCommAccessibility = eCommAccessibility.None;
+ AddToSource(namedValueTypeDeclaration.GetSourceFileAttribute(Project.AxProject));
AddToSource(
$"public enum {namedValueTypeDeclarationSyntax.Name.Text} : {namedValueTypeDeclarationSyntax.BaseType.TransformType()} {{");
@@ -349,6 +352,7 @@ public void CreateInterfaceDeclaration(IInterfaceDeclarationSyntax interfaceDecl
{
TypeCommAccessibility = eCommAccessibility.None;
+ AddToSource(interfaceDeclaration.GetSourceFileAttribute(Project.AxProject));
AddToSource($"{interfaceDeclaration.AccessModifier.Transform()} partial interface {interfaceDeclaration.Name} {{}}");
}
@@ -365,6 +369,7 @@ public void CreateStructuredType(IStructTypeDeclarationSyntax structTypeDeclarat
{
TypeCommAccessibility = structuredTypeDeclaration.GetCommAccessibility(this);
+ AddToSource(structuredTypeDeclaration.GetSourceFileAttribute(Project.AxProject));
AddToSource(structuredTypeDeclaration.Pragmas.AddAttributes());
AddToSource(
$"{structuredTypeDeclaration.AccessModifier.Transform()}partial class {structTypeDeclarationSyntax.Name.Text}");
diff --git a/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/Plain/CsPlainSourceBuilder.cs b/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/Plain/CsPlainSourceBuilder.cs
index 7b8c3886..3d05bffc 100644
--- a/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/Plain/CsPlainSourceBuilder.cs
+++ b/src/AXSharp.compiler/src/AXSharp.Cs.Compiler/Plain/CsPlainSourceBuilder.cs
@@ -71,8 +71,9 @@ public void CreateClassDeclaration(IClassDeclarationSyntax classDeclarationSynta
var classDeclarations = this.Compilation.GetSemanticTree().Classes
.Where(p => p.FullyQualifiedName == classDeclaration.GetQualifiedName());
+ AddToSource(classDeclaration.GetSourceFileAttribute(Project.AxProject));
AddToSource(classDeclaration.Pragmas.AddedPropertiesAsAttributes());
-
+
AddToSource($"{classDeclaration.AccessModifier.Transform()}partial class {classDeclaration.Name}");
var isExtended = false;
@@ -268,6 +269,7 @@ public void CreateInterfaceDeclaration(IInterfaceDeclarationSyntax interfaceDecl
IInterfaceDeclaration interfaceDeclaration,
IxNodeVisitor visitor)
{
+ AddToSource(interfaceDeclaration.GetSourceFileAttribute(Project.AxProject));
AddToSource($"{interfaceDeclaration.AccessModifier.Transform()} partial interface {interfaceDeclaration.Name} {{}}");
}
@@ -348,7 +350,8 @@ public void CreateStructuredType(IStructTypeDeclarationSyntax structTypeDeclarat
IxNodeVisitor visitor)
{
TypeCommAccessibility = structuredTypeDeclaration.GetCommAccessibility(this);
-
+
+ AddToSource(structuredTypeDeclaration.GetSourceFileAttribute(Project.AxProject));
AddToSource(
$"{structuredTypeDeclaration.AccessModifier.Transform()}partial class {structTypeDeclarationSyntax.Name.Text} : AXSharp.Connector.IPlain");
AddToSource("{");
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/SourceFileAttributeTests.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/SourceFileAttributeTests.cs
new file mode 100644
index 00000000..d8e0386d
--- /dev/null
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/SourceFileAttributeTests.cs
@@ -0,0 +1,118 @@
+// AXSharp.Compiler.CsTests
+// Copyright (c) 2023 MTS spol. s r.o., and Contributors. All Rights Reserved.
+// Contributors: https://github.com/inxton/axsharp/graphs/contributors
+// See the LICENSE file in the repository root for more information.
+// https://github.com/inxton/axsharp/blob/dev/LICENSE
+// Third party licenses: https://github.com/inxton/axsharp/blob/master/notices.md
+
+using System;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using AXSharp.Compiler;
+using AXSharp.Compiler.Cs;
+using AXSharp.Compiler.Cs.Onliner;
+using AXSharp.Compiler.Cs.Plain;
+using Polly;
+using Xunit;
+
+namespace AXSharp.Compiler.CsTests;
+
+public class SourceFileAttributeTests
+{
+ // sample under samples/sourcefile/src/sub/widget.st declares a CLASS, a STRUCT, an ENUM and an INTERFACE.
+ private const string ExpectedAttribute = "[AXSharp.Connector.SourceFileAttribute(@\"sub/widget.st\")]";
+
+ private readonly string testFolder;
+
+ public SourceFileAttributeTests()
+ {
+#pragma warning disable CS8604 // Possible null reference argument.
+ var executingAssemblyFileInfo = new FileInfo(Assembly.GetExecutingAssembly().FullName);
+#pragma warning restore CS8604 // Possible null reference argument.
+ testFolder = executingAssemblyFileInfo.Directory!.FullName;
+ }
+
+ // The source file lives in a sub-folder of `src`, so the emitted path must be relativized
+ // against the project `src` folder AND forward-slash normalized (a flat sample would not
+ // catch the separator normalization).
+ [Theory]
+ [InlineData(typeof(CsOnlinerSourceBuilder))]
+ [InlineData(typeof(CsPlainSourceBuilder))]
+ public void emits_forward_slash_relative_source_path(Type builder)
+ {
+ var content = Generate(builder);
+
+ Assert.Contains(ExpectedAttribute, content);
+ Assert.DoesNotContain("sub\\widget.st", content);
+ }
+
+ // Placement invariant: every emitted source-file attribute is immediately followed by a
+ // type declaration — never stranded on a using/namespace/member line. (The reverse is not
+ // asserted: builders also emit nested helper partial classes that are intentionally
+ // undecorated.) This is robust to how many types a given builder emits.
+ [Theory]
+ [InlineData(typeof(CsOnlinerSourceBuilder))]
+ [InlineData(typeof(CsPlainSourceBuilder))]
+ public void every_attribute_directly_precedes_a_type_declaration(Type builder)
+ {
+ var lines = Generate(builder)
+ .Replace("\r", string.Empty)
+ .Split('\n')
+ .Select(l => l.Trim())
+ .ToArray();
+
+ var attributeLineIndexes = Enumerable.Range(0, lines.Length)
+ .Where(i => lines[i] == ExpectedAttribute)
+ .ToArray();
+
+ Assert.NotEmpty(attributeLineIndexes);
+
+ foreach (var i in attributeLineIndexes)
+ {
+ var next = NextNonEmpty(lines, i + 1);
+ Assert.True(next != null && IsTypeDeclaration(next),
+ $"SourceFileAttribute at line {i} is not directly followed by a type declaration but by: '{next}'");
+ }
+ }
+
+ private static bool IsTypeDeclaration(string line) =>
+ line.Contains("partial class ") ||
+ line.Contains("partial interface ") ||
+ line.StartsWith("public enum ");
+
+ private static string? NextNonEmpty(string[] lines, int start)
+ {
+ for (var i = start; i < lines.Length; i++)
+ if (lines[i].Length > 0) return lines[i];
+ return null;
+ }
+
+ private string Generate(Type builder)
+ {
+ var projectFolder = Path.Combine(testFolder, "samples", "sourcefile");
+ var options = new CompilerTestOptions
+ {
+ TargetPlatfromMoniker = "ax",
+ OutputProjectFolder = Path.Combine("samples", "sourcefile", "ix", builder.Name)
+ };
+
+ var sourceFile = Path.Combine(projectFolder, "src", "sub", "widget.st");
+ var project = new AXSharpProject(new AxProject(projectFolder, new[] { sourceFile }), new[] { builder }, typeof(CsProject), options);
+
+ Policy
+ .Handle()
+ .WaitAndRetry(10, a => TimeSpan.FromSeconds(2))
+ .Execute(() =>
+ {
+ if (Directory.Exists(project.OutputFolder)) Directory.Delete(project.OutputFolder, true);
+ });
+
+ project.Generate();
+
+ var generated = Directory
+ .EnumerateFiles(project.OutputFolder, "widget.g.cs", SearchOption.AllDirectories)
+ .Single();
+ return File.ReadAllText(generated);
+ }
+}
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/sourcefile/apax.yml b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/sourcefile/apax.yml
new file mode 100644
index 00000000..924ded26
--- /dev/null
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/sourcefile/apax.yml
@@ -0,0 +1,7 @@
+name: "@ax/sourcefile"
+version: 0.0.0
+type: app
+authors:
+ - peter
+devDependencies:
+ "@ax/sdk": 2503.1.0
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/sourcefile/src/sub/widget.st b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/sourcefile/src/sub/widget.st
new file mode 100644
index 00000000..e75fc1d0
--- /dev/null
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/sourcefile/src/sub/widget.st
@@ -0,0 +1,17 @@
+CLASS widget
+
+END_CLASS
+
+TYPE
+ Gadget : STRUCT
+ running : BOOL;
+ END_STRUCT;
+END_TYPE
+
+TYPE
+ Shade : (Light, Dark) := Light;
+END_TYPE
+
+INTERFACE PUBLIC IWidget
+
+END_INTERFACE
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Configurations.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Configurations.g.cs
index c8759fe4..7a2c6e39 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Configurations.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Configurations.g.cs
@@ -69,8 +69,8 @@ public partial class unitsTwinController : ITwinController
public Colorsss Colorsss2Enum { get => (Colorsss)Colorsss2.LastValue; }
public OnlinerBool MotorOn { get; }
public OnlinerInt MotorState { get; }
- public Motor Motor1 { get; }
- public Motor Motor2 { get; }
+ public MixedAccessMotor Motor1 { get; }
+ public MixedAccessMotor Motor2 { get; }
public struct1 s1 { get; }
public struct4 s4 { get; }
public SpecificMotorA mot1 { get; }
@@ -123,8 +123,8 @@ public unitsTwinController(AXSharp.Connector.ConnectorAdapter adapter, object[]
Colorsss2 = @Connector.ConnectorAdapter.AdapterFactory.CreateULINT(this, "Colorsss2", "Colorsss2");
MotorOn = @Connector.ConnectorAdapter.AdapterFactory.CreateBOOL(this.Connector, "", "MotorOn");
MotorState = @Connector.ConnectorAdapter.AdapterFactory.CreateINT(this.Connector, "", "MotorState");
- Motor1 = new Motor(this.Connector, "", "Motor1");
- Motor2 = new Motor(this.Connector, "", "Motor2");
+ Motor1 = new MixedAccessMotor(this.Connector, "", "Motor1");
+ Motor2 = new MixedAccessMotor(this.Connector, "", "Motor2");
s1 = new struct1(this.Connector, "", "s1");
s4 = new struct4(this.Connector, "", "s4");
mot1 = new SpecificMotorA(this.Connector, "", "mot1");
@@ -176,8 +176,8 @@ public unitsTwinController(AXSharp.Connector.ConnectorAdapter adapter)
Colorsss2 = @Connector.ConnectorAdapter.AdapterFactory.CreateULINT(this, "Colorsss2", "Colorsss2");
MotorOn = @Connector.ConnectorAdapter.AdapterFactory.CreateBOOL(this.Connector, "", "MotorOn");
MotorState = @Connector.ConnectorAdapter.AdapterFactory.CreateINT(this.Connector, "", "MotorState");
- Motor1 = new Motor(this.Connector, "", "Motor1");
- Motor2 = new Motor(this.Connector, "", "Motor2");
+ Motor1 = new MixedAccessMotor(this.Connector, "", "Motor1");
+ Motor2 = new MixedAccessMotor(this.Connector, "", "Motor2");
s1 = new struct1(this.Connector, "", "s1");
s4 = new struct4(this.Connector, "", "s4");
mot1 = new SpecificMotorA(this.Connector, "", "mot1");
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/abstract_members.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/abstract_members.g.cs
index 0e57b992..a7499813 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/abstract_members.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/abstract_members.g.cs
@@ -5,14 +5,15 @@
using AXSharp.Connector.Localizations;
using AXSharp.Abstractions.Presentation;
-public partial class AbstractMotor : AXSharp.Connector.ITwinObject
+[AXSharp.Connector.SourceFileAttribute(@"abstract_members.st")]
+public partial class AbstractMembersMotor : AXSharp.Connector.ITwinObject
{
public OnlinerBool Run { get; }
public OnlinerBool ReverseDirection { get; }
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
partial void PostConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
- public AbstractMotor(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail)
+ public AbstractMembersMotor(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail)
{
Symbol = AXSharp.Connector.Connector.CreateSymbol(parent.Symbol, symbolTail);
this.@SymbolTail = symbolTail;
@@ -32,9 +33,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
return await (dynamic)this.OnlineToPlainAsync(priority);
}
- public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
+ public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
{
- global::Pocos.AbstractMotor plain = new global::Pocos.AbstractMotor();
+ global::Pocos.AbstractMembersMotor plain = new global::Pocos.AbstractMembersMotor();
await this.ReadAsync(priority);
plain.Run = Run.LastValue;
plain.ReverseDirection = ReverseDirection.LastValue;
@@ -43,9 +44,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _OnlineToPlainNoacAsync()
+ public async Task _OnlineToPlainNoacAsync()
{
- global::Pocos.AbstractMotor plain = new global::Pocos.AbstractMotor();
+ global::Pocos.AbstractMembersMotor plain = new global::Pocos.AbstractMembersMotor();
plain.Run = Run.LastValue;
plain.ReverseDirection = ReverseDirection.LastValue;
return plain;
@@ -53,7 +54,7 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- protected async Task _OnlineToPlainNoacAsync(global::Pocos.AbstractMotor plain)
+ protected async Task _OnlineToPlainNoacAsync(global::Pocos.AbstractMembersMotor plain)
{
plain.Run = Run.LastValue;
plain.ReverseDirection = ReverseDirection.LastValue;
@@ -65,7 +66,7 @@ public async virtual Task PlainToOnline(T plain, eAccessPriority priority = e
await this.PlainToOnlineAsync((dynamic)plain, priority);
}
- public async Task> PlainToOnlineAsync(global::Pocos.AbstractMotor plain, eAccessPriority priority = eAccessPriority.Normal)
+ public async Task> PlainToOnlineAsync(global::Pocos.AbstractMembersMotor plain, eAccessPriority priority = eAccessPriority.Normal)
{
#pragma warning disable CS0612
Run.LethargicWrite(plain.Run);
@@ -78,7 +79,7 @@ public async Task> PlainToOnlineAsync(global::Pocos.
[Obsolete("This method should not be used if you indent to access the controllers data. Use `PlainToOnline` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _PlainToOnlineNoacAsync(global::Pocos.AbstractMotor plain)
+ public async Task _PlainToOnlineNoacAsync(global::Pocos.AbstractMembersMotor plain)
{
#pragma warning disable CS0612
Run.LethargicWrite(plain.Run);
@@ -93,15 +94,15 @@ public async virtual Task ShadowToPlain()
return await (dynamic)this.ShadowToPlainAsync();
}
- public async Task ShadowToPlainAsync()
+ public async Task ShadowToPlainAsync()
{
- global::Pocos.AbstractMotor plain = new global::Pocos.AbstractMotor();
+ global::Pocos.AbstractMembersMotor plain = new global::Pocos.AbstractMembersMotor();
plain.Run = Run.Shadow;
plain.ReverseDirection = ReverseDirection.Shadow;
return plain;
}
- protected async Task ShadowToPlainAsync(global::Pocos.AbstractMotor plain)
+ protected async Task ShadowToPlainAsync(global::Pocos.AbstractMembersMotor plain)
{
plain.Run = Run.Shadow;
plain.ReverseDirection = ReverseDirection.Shadow;
@@ -113,7 +114,7 @@ public async virtual Task PlainToShadow(T plain)
await this.PlainToShadowAsync((dynamic)plain);
}
- public async Task> PlainToShadowAsync(global::Pocos.AbstractMotor plain)
+ public async Task> PlainToShadowAsync(global::Pocos.AbstractMembersMotor plain)
{
Run.Shadow = plain.Run;
ReverseDirection.Shadow = plain.ReverseDirection;
@@ -130,7 +131,7 @@ public async virtual Task AnyChangeAsync(T plain)
///Compares if the current plain object has changed from the previous object.This method is used by the framework to determine if the object has changed and needs to be updated.
///[!NOTE] Any member in the hierarchy that is ignored by the compilers (e.g. when CompilerOmitAttribute is used) will not be compared, and therefore will not be detected as changed.
///
- public async Task DetectsAnyChangeAsync(global::Pocos.AbstractMotor plain, global::Pocos.AbstractMotor latest = null)
+ public async Task DetectsAnyChangeAsync(global::Pocos.AbstractMembersMotor plain, global::Pocos.AbstractMembersMotor latest = null)
{
if (latest == null)
latest = await this._OnlineToPlainNoacAsync();
@@ -151,9 +152,9 @@ public void Poll()
this.RetrievePrimitives().ToList().ForEach(x => x.Poll());
}
- public global::Pocos.AbstractMotor CreateEmptyPoco()
+ public global::Pocos.AbstractMembersMotor CreateEmptyPoco()
{
- return new global::Pocos.AbstractMotor();
+ return new global::Pocos.AbstractMembersMotor();
}
private IList Children { get; } = new List();
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/array_declaration.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/array_declaration.g.cs
index 49415da1..9878f8a6 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/array_declaration.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/array_declaration.g.cs
@@ -7,6 +7,7 @@
namespace ArrayDeclarationSimpleNamespace
{
+ [AXSharp.Connector.SourceFileAttribute(@"array_declaration.st")]
public partial class array_declaration_class : AXSharp.Connector.ITwinObject
{
public OnlinerInt[] primitive { get; }
@@ -261,6 +262,7 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+ [AXSharp.Connector.SourceFileAttribute(@"array_declaration.st")]
public partial class some_complex_type : AXSharp.Connector.ITwinObject
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_all_primitives.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_all_primitives.g.cs
index 36c26531..8f9de570 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_all_primitives.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_all_primitives.g.cs
@@ -5,6 +5,7 @@
using AXSharp.Connector.Localizations;
using AXSharp.Abstractions.Presentation;
+[AXSharp.Connector.SourceFileAttribute(@"class_all_primitives.st")]
public partial class class_all_primitives : AXSharp.Connector.ITwinObject
{
public OnlinerBool myBOOL { get; }
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extended_by_known_type.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extended_by_known_type.g.cs
index 41bd6829..3ae289c7 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extended_by_known_type.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extended_by_known_type.g.cs
@@ -7,6 +7,7 @@
namespace Simatic.Ax.StateFramework
{
+ [AXSharp.Connector.SourceFileAttribute(@"class_extended_by_known_type.st")]
public partial class State1Transition : Simatic.Ax.StateFramework.AbstractState
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
@@ -139,6 +140,7 @@ public async override Task AnyChangeAsync(T plain)
namespace Simatic.Ax.StateFramework
{
+ [AXSharp.Connector.SourceFileAttribute(@"class_extended_by_known_type.st")]
public partial class AbstractState : AXSharp.Connector.ITwinObject, IState, IStateMuteable
{
public OnlinerInt StateID { get; }
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extends.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extends.g.cs
index ae98b0e0..84f3c673 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extends.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extends.g.cs
@@ -5,6 +5,7 @@
using AXSharp.Connector.Localizations;
using AXSharp.Abstractions.Presentation;
+[AXSharp.Connector.SourceFileAttribute(@"class_extends.st")]
public partial class Extended : Extendee
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
@@ -134,6 +135,7 @@ public async override Task AnyChangeAsync(T plain)
}
}
+[AXSharp.Connector.SourceFileAttribute(@"class_extends.st")]
public partial class Extendee : AXSharp.Connector.ITwinObject
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extends_and_implements.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extends_and_implements.g.cs
index 2f519df4..6d664c21 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extends_and_implements.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_extends_and_implements.g.cs
@@ -5,6 +5,7 @@
using AXSharp.Connector.Localizations;
using AXSharp.Abstractions.Presentation;
+[AXSharp.Connector.SourceFileAttribute(@"class_extends_and_implements.st")]
public partial class ExtendsAndImplements : ExtendeeExtendsAndImplements, IImplementation1, IImplementation2
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
@@ -134,6 +135,7 @@ public async override Task AnyChangeAsync(T plain)
}
}
+[AXSharp.Connector.SourceFileAttribute(@"class_extends_and_implements.st")]
public partial class ExtendeeExtendsAndImplements : AXSharp.Connector.ITwinObject
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
@@ -333,10 +335,12 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+[AXSharp.Connector.SourceFileAttribute(@"class_extends_and_implements.st")]
public partial interface IImplementation1
{
}
+[AXSharp.Connector.SourceFileAttribute(@"class_extends_and_implements.st")]
public partial interface IImplementation2
{
}
\ No newline at end of file
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_generic_extension.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_generic_extension.g.cs
index 6f1bf375..0c5bc584 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_generic_extension.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_generic_extension.g.cs
@@ -7,6 +7,7 @@
namespace Generics
{
+ [AXSharp.Connector.SourceFileAttribute(@"class_generic_extension.st")]
public partial class Extender : AXSharp.Connector.ITwinObject where TOnline : ITwinObject
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
@@ -206,6 +207,7 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+ [AXSharp.Connector.SourceFileAttribute(@"class_generic_extension.st")]
public partial class Extendee : Generics.Extender
{
public Generics.SomeType SomeType { get; }
@@ -380,6 +382,7 @@ public async override Task AnyChangeAsync(T plain)
}
}
+ [AXSharp.Connector.SourceFileAttribute(@"class_generic_extension.st")]
public partial class Extendee2 : Generics.Extender
{
public Generics.SomeType SomeType { get; }
@@ -532,6 +535,7 @@ public async override Task AnyChangeAsync(T plain)
}
}
+ [AXSharp.Connector.SourceFileAttribute(@"class_generic_extension.st")]
public partial class SomeType : AXSharp.Connector.ITwinObject
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_implements.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_implements.g.cs
index ee0cb2ce..76773fed 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_implements.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_implements.g.cs
@@ -5,6 +5,7 @@
using AXSharp.Connector.Localizations;
using AXSharp.Abstractions.Presentation;
+[AXSharp.Connector.SourceFileAttribute(@"class_implements.st")]
public partial class _NULL_CONTEXT : AXSharp.Connector.ITwinObject, IContext
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
@@ -204,6 +205,7 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+[AXSharp.Connector.SourceFileAttribute(@"class_implements.st")]
public partial interface IContext
{
}
\ No newline at end of file
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_implements_multiple.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_implements_multiple.g.cs
index 95d287ca..7f11388e 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_implements_multiple.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_implements_multiple.g.cs
@@ -5,6 +5,7 @@
using AXSharp.Connector.Localizations;
using AXSharp.Abstractions.Presentation;
+[AXSharp.Connector.SourceFileAttribute(@"class_implements_multiple.st")]
public partial class _NULL_CONTEXT_MULTIPLE : AXSharp.Connector.ITwinObject, IContext_Multiple, IObject_Multiple
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
@@ -204,10 +205,12 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+[AXSharp.Connector.SourceFileAttribute(@"class_implements_multiple.st")]
public partial interface IContext_Multiple
{
}
+[AXSharp.Connector.SourceFileAttribute(@"class_implements_multiple.st")]
public partial interface IObject_Multiple
{
}
\ No newline at end of file
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_internal.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_internal.g.cs
index 4125361e..daf48d58 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_internal.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_internal.g.cs
@@ -5,6 +5,7 @@
using AXSharp.Connector.Localizations;
using AXSharp.Abstractions.Presentation;
+[AXSharp.Connector.SourceFileAttribute(@"class_internal.st")]
internal partial class ClassWithComplexTypes : AXSharp.Connector.ITwinObject
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_no_access_modifier.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_no_access_modifier.g.cs
index 2d2272b1..f1cd6d99 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_no_access_modifier.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_no_access_modifier.g.cs
@@ -5,6 +5,7 @@
using AXSharp.Connector.Localizations;
using AXSharp.Abstractions.Presentation;
+[AXSharp.Connector.SourceFileAttribute(@"class_no_access_modifier.st")]
public partial class NoAccessModifierClass : AXSharp.Connector.ITwinObject
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_complex_members.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_complex_members.g.cs
index d423ae31..7ead6d88 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_complex_members.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_complex_members.g.cs
@@ -7,6 +7,7 @@
namespace ClassWithComplexTypesNamespace
{
+ [AXSharp.Connector.SourceFileAttribute(@"class_with_complex_members.st")]
public partial class ClassWithComplexTypes : AXSharp.Connector.ITwinObject
{
public ClassWithComplexTypesNamespace.ComplexType1 myComplexType { get; }
@@ -229,6 +230,7 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+ [AXSharp.Connector.SourceFileAttribute(@"class_with_complex_members.st")]
public partial class ComplexType1 : AXSharp.Connector.ITwinObject
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_constant_members.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_constant_members.g.cs
index a6a023f8..6799e7d9 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_constant_members.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_constant_members.g.cs
@@ -7,6 +7,7 @@
namespace ClassWithConstantMembersNamespace
{
+ [AXSharp.Connector.SourceFileAttribute(@"class_with_constant_members.st")]
public partial class ClassWithConstantMembers : AXSharp.Connector.ITwinObject
{
public OnlinerInt myNonConstant { get; }
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_non_public_members.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_non_public_members.g.cs
index dedb4802..1dcdea75 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_non_public_members.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_non_public_members.g.cs
@@ -7,6 +7,7 @@
namespace ClassWithNonTraspilableMemberssNamespace
{
+ [AXSharp.Connector.SourceFileAttribute(@"class_with_non_public_members.st")]
public partial class ClassWithNonTraspilableMembers : AXSharp.Connector.ITwinObject
{
public ClassWithNonTraspilableMemberssNamespace.ComplexType1 myComplexType { get; }
@@ -237,6 +238,7 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+ [AXSharp.Connector.SourceFileAttribute(@"class_with_non_public_members.st")]
public partial class ComplexType1 : AXSharp.Connector.ITwinObject
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_pragmas.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_pragmas.g.cs
index 383d092d..fad09a9f 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_pragmas.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_pragmas.g.cs
@@ -7,6 +7,7 @@
namespace ClassWithPragmasNamespace
{
+ [AXSharp.Connector.SourceFileAttribute(@"class_with_pragmas.st")]
[Container(Layout.Stack)]
public partial class ClassWithPragmas : AXSharp.Connector.ITwinObject
{
@@ -231,6 +232,7 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+ [AXSharp.Connector.SourceFileAttribute(@"class_with_pragmas.st")]
public partial class ComplexType1 : AXSharp.Connector.ITwinObject
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_primitive_members.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_primitive_members.g.cs
index 279c7fb4..f75b0c93 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_primitive_members.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_primitive_members.g.cs
@@ -7,6 +7,7 @@
namespace ClassWithPrimitiveTypesNamespace
{
+ [AXSharp.Connector.SourceFileAttribute(@"class_with_primitive_members.st")]
public partial class ClassWithPrimitiveTypes : AXSharp.Connector.ITwinObject
{
public OnlinerBool myBOOL { get; }
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_using_directives.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_using_directives.g.cs
index 41fa3c4c..b019a873 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_using_directives.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/class_with_using_directives.g.cs
@@ -8,6 +8,7 @@
using SimpleQualifiedNamespace.Qualified;
using HelloLevelOne.HelloLevelTwo;
+[AXSharp.Connector.SourceFileAttribute(@"class_with_using_directives.st")]
internal partial class ClassWithUsingDirectives : AXSharp.Connector.ITwinObject
{
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
diff --git a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/compileromitsattribute.g.cs b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/compileromitsattribute.g.cs
index 056e16e0..f0136fc7 100644
--- a/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/compileromitsattribute.g.cs
+++ b/src/AXSharp.compiler/tests/AXSharp.Compiler.CsTests/samples/units/expected/ax/.g/Onliners/compileromitsattribute.g.cs
@@ -7,6 +7,7 @@
namespace CompilerOmmits
{
+ [AXSharp.Connector.SourceFileAttribute(@"compileromitsattribute.st")]
public partial class ClassWithArrays : AXSharp.Connector.ITwinObject
{
[CompilerOmitsAttribute("POCO")]
@@ -234,6 +235,7 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+ [AXSharp.Connector.SourceFileAttribute(@"compileromitsattribute.st")]
public partial class Complex : AXSharp.Connector.ITwinObject
{
public OnlinerString HelloString { get; }
@@ -467,15 +469,16 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
}
}
-namespace Enums
+namespace CompilerOmmitsEnums
{
+ [AXSharp.Connector.SourceFileAttribute(@"compileromitsattribute.st")]
public partial class ClassWithEnums : AXSharp.Connector.ITwinObject
{
- [AXSharp.Connector.EnumeratorDiscriminatorAttribute(typeof(Enums.Colors))]
+ [AXSharp.Connector.EnumeratorDiscriminatorAttribute(typeof(CompilerOmmitsEnums.Colors))]
public OnlinerInt colors { get; }
- public Enums.Colors colorsEnum { get => (Enums.Colors)colors.LastValue; }
+ public CompilerOmmitsEnums.Colors colorsEnum { get => (CompilerOmmitsEnums.Colors)colors.LastValue; }
- [AXSharp.Connector.EnumeratorDiscriminatorAttribute(typeof(Enums.NamedValuesColors))]
+ [AXSharp.Connector.EnumeratorDiscriminatorAttribute(typeof(CompilerOmmitsEnums.NamedValuesColors))]
public OnlinerString NamedValuesColors { get; }
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
@@ -500,30 +503,30 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
return await (dynamic)this.OnlineToPlainAsync(priority);
}
- public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
+ public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
{
- global::Pocos.Enums.ClassWithEnums plain = new global::Pocos.Enums.ClassWithEnums();
+ global::Pocos.CompilerOmmitsEnums.ClassWithEnums plain = new global::Pocos.CompilerOmmitsEnums.ClassWithEnums();
await this.ReadAsync(priority);
- plain.colors = (Enums.Colors)colors.LastValue;
+ plain.colors = (CompilerOmmitsEnums.Colors)colors.LastValue;
plain.NamedValuesColors = NamedValuesColors.LastValue;
return plain;
}
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _OnlineToPlainNoacAsync()
+ public async Task _OnlineToPlainNoacAsync()
{
- global::Pocos.Enums.ClassWithEnums plain = new global::Pocos.Enums.ClassWithEnums();
- plain.colors = (Enums.Colors)colors.LastValue;
+ global::Pocos.CompilerOmmitsEnums.ClassWithEnums plain = new global::Pocos.CompilerOmmitsEnums.ClassWithEnums();
+ plain.colors = (CompilerOmmitsEnums.Colors)colors.LastValue;
plain.NamedValuesColors = NamedValuesColors.LastValue;
return plain;
}
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- protected async Task _OnlineToPlainNoacAsync(global::Pocos.Enums.ClassWithEnums plain)
+ protected async Task _OnlineToPlainNoacAsync(global::Pocos.CompilerOmmitsEnums.ClassWithEnums plain)
{
- plain.colors = (Enums.Colors)colors.LastValue;
+ plain.colors = (CompilerOmmitsEnums.Colors)colors.LastValue;
plain.NamedValuesColors = NamedValuesColors.LastValue;
return plain;
}
@@ -533,7 +536,7 @@ public async virtual Task PlainToOnline(T plain, eAccessPriority priority = e
await this.PlainToOnlineAsync((dynamic)plain, priority);
}
- public async Task> PlainToOnlineAsync(global::Pocos.Enums.ClassWithEnums plain, eAccessPriority priority = eAccessPriority.Normal)
+ public async Task> PlainToOnlineAsync(global::Pocos.CompilerOmmitsEnums.ClassWithEnums plain, eAccessPriority priority = eAccessPriority.Normal)
{
#pragma warning disable CS0612
colors.LethargicWrite((short)plain.colors);
@@ -546,7 +549,7 @@ public async Task> PlainToOnlineAsync(global::Pocos.
[Obsolete("This method should not be used if you indent to access the controllers data. Use `PlainToOnline` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _PlainToOnlineNoacAsync(global::Pocos.Enums.ClassWithEnums plain)
+ public async Task _PlainToOnlineNoacAsync(global::Pocos.CompilerOmmitsEnums.ClassWithEnums plain)
{
#pragma warning disable CS0612
colors.LethargicWrite((short)plain.colors);
@@ -561,17 +564,17 @@ public async virtual Task ShadowToPlain()
return await (dynamic)this.ShadowToPlainAsync();
}
- public async Task ShadowToPlainAsync()
+ public async Task ShadowToPlainAsync()
{
- global::Pocos.Enums.ClassWithEnums plain = new global::Pocos.Enums.ClassWithEnums();
- plain.colors = (Enums.Colors)colors.Shadow;
+ global::Pocos.CompilerOmmitsEnums.ClassWithEnums plain = new global::Pocos.CompilerOmmitsEnums.ClassWithEnums();
+ plain.colors = (CompilerOmmitsEnums.Colors)colors.Shadow;
plain.NamedValuesColors = NamedValuesColors.Shadow;
return plain;
}
- protected async Task ShadowToPlainAsync(global::Pocos.Enums.ClassWithEnums plain)
+ protected async Task ShadowToPlainAsync(global::Pocos.CompilerOmmitsEnums.ClassWithEnums plain)
{
- plain.colors = (Enums.Colors)colors.Shadow;
+ plain.colors = (CompilerOmmitsEnums.Colors)colors.Shadow;
plain.NamedValuesColors = NamedValuesColors.Shadow;
return plain;
}
@@ -581,7 +584,7 @@ public async virtual Task PlainToShadow(T plain)
await this.PlainToShadowAsync((dynamic)plain);
}
- public async Task> PlainToShadowAsync(global::Pocos.Enums.ClassWithEnums plain)
+ public async Task> PlainToShadowAsync(global::Pocos.CompilerOmmitsEnums.ClassWithEnums plain)
{
colors.Shadow = (short)plain.colors;
NamedValuesColors.Shadow = plain.NamedValuesColors;
@@ -598,14 +601,14 @@ public async virtual Task AnyChangeAsync(T plain)
///Compares if the current plain object has changed from the previous object.This method is used by the framework to determine if the object has changed and needs to be updated.
///[!NOTE] Any member in the hierarchy that is ignored by the compilers (e.g. when CompilerOmitAttribute is used) will not be compared, and therefore will not be detected as changed.
///
- public async Task DetectsAnyChangeAsync(global::Pocos.Enums.ClassWithEnums plain, global::Pocos.Enums.ClassWithEnums latest = null)
+ public async Task DetectsAnyChangeAsync(global::Pocos.CompilerOmmitsEnums.ClassWithEnums plain, global::Pocos.CompilerOmmitsEnums.ClassWithEnums latest = null)
{
if (latest == null)
latest = await this._OnlineToPlainNoacAsync();
var somethingChanged = false;
return await Task.Run(async () =>
{
- if (plain.colors != (Enums.Colors)latest.colors)
+ if (plain.colors != (CompilerOmmitsEnums.Colors)latest.colors)
somethingChanged = true;
if (plain.NamedValuesColors != NamedValuesColors.LastValue)
somethingChanged = true;
@@ -619,9 +622,9 @@ public void Poll()
this.RetrievePrimitives().ToList().ForEach(x => x.Poll());
}
- public global::Pocos.Enums.ClassWithEnums CreateEmptyPoco()
+ public global::Pocos.CompilerOmmitsEnums.ClassWithEnums CreateEmptyPoco()
{
- return new global::Pocos.Enums.ClassWithEnums();
+ return new global::Pocos.CompilerOmmitsEnums.ClassWithEnums();
}
private IList Children { get; } = new List();
@@ -705,6 +708,7 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+ [AXSharp.Connector.SourceFileAttribute(@"compileromitsattribute.st")]
public enum Colors
{
Red,
@@ -712,6 +716,7 @@ public enum Colors
Blue
}
+ [AXSharp.Connector.SourceFileAttribute(@"compileromitsattribute.st")]
public enum NamedValuesColors : String
{
Red = 49,
@@ -720,12 +725,13 @@ public enum NamedValuesColors : String
}
}
-namespace misc
+namespace CompilerOmmitsMisc
{
+ [AXSharp.Connector.SourceFileAttribute(@"compileromitsattribute.st")]
public partial class VariousMembers : AXSharp.Connector.ITwinObject
{
- public misc.SomeClass _SomeClass { get; }
- public misc.Motor _Motor { get; }
+ public CompilerOmmitsMisc.SomeClass _SomeClass { get; }
+ public CompilerOmmitsMisc.ComersMotor _Motor { get; }
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
partial void PostConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
@@ -737,8 +743,8 @@ public VariousMembers(AXSharp.Connector.ITwinObject parent, string readableTail,
this.@Parent = parent;
HumanReadable = AXSharp.Connector.Connector.CreateHumanReadable(parent.HumanReadable, readableTail);
PreConstruct(parent, readableTail, symbolTail);
- _SomeClass = new misc.SomeClass(this, "_SomeClass", "_SomeClass");
- _Motor = new misc.Motor(this, "_Motor", "_Motor");
+ _SomeClass = new CompilerOmmitsMisc.SomeClass(this, "_SomeClass", "_SomeClass");
+ _Motor = new CompilerOmmitsMisc.ComersMotor(this, "_Motor", "_Motor");
parent.AddChild(this);
parent.AddKid(this);
PostConstruct(parent, readableTail, symbolTail);
@@ -749,9 +755,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
return await (dynamic)this.OnlineToPlainAsync(priority);
}
- public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
+ public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
{
- global::Pocos.misc.VariousMembers plain = new global::Pocos.misc.VariousMembers();
+ global::Pocos.CompilerOmmitsMisc.VariousMembers plain = new global::Pocos.CompilerOmmitsMisc.VariousMembers();
await this.ReadAsync(priority);
#pragma warning disable CS0612
plain._SomeClass = await _SomeClass._OnlineToPlainNoacAsync();
@@ -764,9 +770,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _OnlineToPlainNoacAsync()
+ public async Task _OnlineToPlainNoacAsync()
{
- global::Pocos.misc.VariousMembers plain = new global::Pocos.misc.VariousMembers();
+ global::Pocos.CompilerOmmitsMisc.VariousMembers plain = new global::Pocos.CompilerOmmitsMisc.VariousMembers();
#pragma warning disable CS0612
plain._SomeClass = await _SomeClass._OnlineToPlainNoacAsync();
#pragma warning restore CS0612
@@ -778,7 +784,7 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- protected async Task _OnlineToPlainNoacAsync(global::Pocos.misc.VariousMembers plain)
+ protected async Task _OnlineToPlainNoacAsync(global::Pocos.CompilerOmmitsMisc.VariousMembers plain)
{
#pragma warning disable CS0612
plain._SomeClass = await _SomeClass._OnlineToPlainNoacAsync();
@@ -794,7 +800,7 @@ public async virtual Task PlainToOnline(T plain, eAccessPriority priority = e
await this.PlainToOnlineAsync((dynamic)plain, priority);
}
- public async Task> PlainToOnlineAsync(global::Pocos.misc.VariousMembers plain, eAccessPriority priority = eAccessPriority.Normal)
+ public async Task> PlainToOnlineAsync(global::Pocos.CompilerOmmitsMisc.VariousMembers plain, eAccessPriority priority = eAccessPriority.Normal)
{
#pragma warning disable CS0612
await this._SomeClass._PlainToOnlineNoacAsync(plain._SomeClass);
@@ -807,7 +813,7 @@ public async Task> PlainToOnlineAsync(global::Pocos.
[Obsolete("This method should not be used if you indent to access the controllers data. Use `PlainToOnline` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _PlainToOnlineNoacAsync(global::Pocos.misc.VariousMembers plain)
+ public async Task _PlainToOnlineNoacAsync(global::Pocos.CompilerOmmitsMisc.VariousMembers plain)
{
#pragma warning disable CS0612
await this._SomeClass._PlainToOnlineNoacAsync(plain._SomeClass);
@@ -822,15 +828,15 @@ public async virtual Task ShadowToPlain()
return await (dynamic)this.ShadowToPlainAsync();
}
- public async Task ShadowToPlainAsync()
+ public async Task ShadowToPlainAsync()
{
- global::Pocos.misc.VariousMembers plain = new global::Pocos.misc.VariousMembers();
+ global::Pocos.CompilerOmmitsMisc.VariousMembers plain = new global::Pocos.CompilerOmmitsMisc.VariousMembers();
plain._SomeClass = await _SomeClass.ShadowToPlainAsync();
plain._Motor = await _Motor.ShadowToPlainAsync();
return plain;
}
- protected async Task ShadowToPlainAsync(global::Pocos.misc.VariousMembers plain)
+ protected async Task ShadowToPlainAsync(global::Pocos.CompilerOmmitsMisc.VariousMembers plain)
{
plain._SomeClass = await _SomeClass.ShadowToPlainAsync();
plain._Motor = await _Motor.ShadowToPlainAsync();
@@ -842,7 +848,7 @@ public async virtual Task PlainToShadow(T plain)
await this.PlainToShadowAsync((dynamic)plain);
}
- public async Task> PlainToShadowAsync(global::Pocos.misc.VariousMembers plain)
+ public async Task> PlainToShadowAsync(global::Pocos.CompilerOmmitsMisc.VariousMembers plain)
{
await this._SomeClass.PlainToShadowAsync(plain._SomeClass);
await this._Motor.PlainToShadowAsync(plain._Motor);
@@ -859,7 +865,7 @@ public async virtual Task AnyChangeAsync(T plain)
///Compares if the current plain object has changed from the previous object.This method is used by the framework to determine if the object has changed and needs to be updated.
///[!NOTE] Any member in the hierarchy that is ignored by the compilers (e.g. when CompilerOmitAttribute is used) will not be compared, and therefore will not be detected as changed.
///
- public async Task DetectsAnyChangeAsync(global::Pocos.misc.VariousMembers plain, global::Pocos.misc.VariousMembers latest = null)
+ public async Task DetectsAnyChangeAsync(global::Pocos.CompilerOmmitsMisc.VariousMembers plain, global::Pocos.CompilerOmmitsMisc.VariousMembers latest = null)
{
if (latest == null)
latest = await this._OnlineToPlainNoacAsync();
@@ -880,9 +886,9 @@ public void Poll()
this.RetrievePrimitives().ToList().ForEach(x => x.Poll());
}
- public global::Pocos.misc.VariousMembers CreateEmptyPoco()
+ public global::Pocos.CompilerOmmitsMisc.VariousMembers CreateEmptyPoco()
{
- return new global::Pocos.misc.VariousMembers();
+ return new global::Pocos.CompilerOmmitsMisc.VariousMembers();
}
private IList Children { get; } = new List();
@@ -966,6 +972,7 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+ [AXSharp.Connector.SourceFileAttribute(@"compileromitsattribute.st")]
public partial class SomeClass : AXSharp.Connector.ITwinObject
{
public OnlinerString SomeClassVariable { get; }
@@ -991,9 +998,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
return await (dynamic)this.OnlineToPlainAsync(priority);
}
- public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
+ public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
{
- global::Pocos.misc.SomeClass plain = new global::Pocos.misc.SomeClass();
+ global::Pocos.CompilerOmmitsMisc.SomeClass plain = new global::Pocos.CompilerOmmitsMisc.SomeClass();
await this.ReadAsync(priority);
plain.SomeClassVariable = SomeClassVariable.LastValue;
return plain;
@@ -1001,16 +1008,16 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _OnlineToPlainNoacAsync()
+ public async Task _OnlineToPlainNoacAsync()
{
- global::Pocos.misc.SomeClass plain = new global::Pocos.misc.SomeClass();
+ global::Pocos.CompilerOmmitsMisc.SomeClass plain = new global::Pocos.CompilerOmmitsMisc.SomeClass();
plain.SomeClassVariable = SomeClassVariable.LastValue;
return plain;
}
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- protected async Task _OnlineToPlainNoacAsync(global::Pocos.misc.SomeClass plain)
+ protected async Task _OnlineToPlainNoacAsync(global::Pocos.CompilerOmmitsMisc.SomeClass plain)
{
plain.SomeClassVariable = SomeClassVariable.LastValue;
return plain;
@@ -1021,7 +1028,7 @@ public async virtual Task PlainToOnline(T plain, eAccessPriority priority = e
await this.PlainToOnlineAsync((dynamic)plain, priority);
}
- public async Task> PlainToOnlineAsync(global::Pocos.misc.SomeClass plain, eAccessPriority priority = eAccessPriority.Normal)
+ public async Task> PlainToOnlineAsync(global::Pocos.CompilerOmmitsMisc.SomeClass plain, eAccessPriority priority = eAccessPriority.Normal)
{
#pragma warning disable CS0612
SomeClassVariable.LethargicWrite(plain.SomeClassVariable);
@@ -1031,7 +1038,7 @@ public async Task> PlainToOnlineAsync(global::Pocos.
[Obsolete("This method should not be used if you indent to access the controllers data. Use `PlainToOnline` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _PlainToOnlineNoacAsync(global::Pocos.misc.SomeClass plain)
+ public async Task _PlainToOnlineNoacAsync(global::Pocos.CompilerOmmitsMisc.SomeClass plain)
{
#pragma warning disable CS0612
SomeClassVariable.LethargicWrite(plain.SomeClassVariable);
@@ -1043,14 +1050,14 @@ public async virtual Task ShadowToPlain()
return await (dynamic)this.ShadowToPlainAsync();
}
- public async Task ShadowToPlainAsync()
+ public async Task ShadowToPlainAsync()
{
- global::Pocos.misc.SomeClass plain = new global::Pocos.misc.SomeClass();
+ global::Pocos.CompilerOmmitsMisc.SomeClass plain = new global::Pocos.CompilerOmmitsMisc.SomeClass();
plain.SomeClassVariable = SomeClassVariable.Shadow;
return plain;
}
- protected async Task ShadowToPlainAsync(global::Pocos.misc.SomeClass plain)
+ protected async Task ShadowToPlainAsync(global::Pocos.CompilerOmmitsMisc.SomeClass plain)
{
plain.SomeClassVariable = SomeClassVariable.Shadow;
return plain;
@@ -1061,7 +1068,7 @@ public async virtual Task PlainToShadow(T plain)
await this.PlainToShadowAsync((dynamic)plain);
}
- public async Task> PlainToShadowAsync(global::Pocos.misc.SomeClass plain)
+ public async Task> PlainToShadowAsync(global::Pocos.CompilerOmmitsMisc.SomeClass plain)
{
SomeClassVariable.Shadow = plain.SomeClassVariable;
return this.RetrievePrimitives();
@@ -1077,7 +1084,7 @@ public async virtual Task AnyChangeAsync(T plain)
///Compares if the current plain object has changed from the previous object.This method is used by the framework to determine if the object has changed and needs to be updated.
///[!NOTE] Any member in the hierarchy that is ignored by the compilers (e.g. when CompilerOmitAttribute is used) will not be compared, and therefore will not be detected as changed.
///
- public async Task DetectsAnyChangeAsync(global::Pocos.misc.SomeClass plain, global::Pocos.misc.SomeClass latest = null)
+ public async Task DetectsAnyChangeAsync(global::Pocos.CompilerOmmitsMisc.SomeClass plain, global::Pocos.CompilerOmmitsMisc.SomeClass latest = null)
{
if (latest == null)
latest = await this._OnlineToPlainNoacAsync();
@@ -1096,9 +1103,9 @@ public void Poll()
this.RetrievePrimitives().ToList().ForEach(x => x.Poll());
}
- public global::Pocos.misc.SomeClass CreateEmptyPoco()
+ public global::Pocos.CompilerOmmitsMisc.SomeClass CreateEmptyPoco()
{
- return new global::Pocos.misc.SomeClass();
+ return new global::Pocos.CompilerOmmitsMisc.SomeClass();
}
private IList Children { get; } = new List();
@@ -1182,13 +1189,14 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
- public partial class Motor : AXSharp.Connector.ITwinObject
+ [AXSharp.Connector.SourceFileAttribute(@"compileromitsattribute.st")]
+ public partial class ComersMotor : AXSharp.Connector.ITwinObject
{
public OnlinerBool isRunning { get; }
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
partial void PostConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
- public Motor(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail)
+ public ComersMotor(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail)
{
this.@SymbolTail = symbolTail;
this.@Connector = parent.GetConnector();
@@ -1207,9 +1215,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
return await (dynamic)this.OnlineToPlainAsync(priority);
}
- public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
+ public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
{
- global::Pocos.misc.Motor plain = new global::Pocos.misc.Motor();
+ global::Pocos.CompilerOmmitsMisc.ComersMotor plain = new global::Pocos.CompilerOmmitsMisc.ComersMotor();
await this.ReadAsync(priority);
plain.isRunning = isRunning.LastValue;
return plain;
@@ -1217,14 +1225,14 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _OnlineToPlainNoacAsync()
+ public async Task _OnlineToPlainNoacAsync()
{
- global::Pocos.misc.Motor plain = new global::Pocos.misc.Motor();
+ global::Pocos.CompilerOmmitsMisc.ComersMotor plain = new global::Pocos.CompilerOmmitsMisc.ComersMotor();
plain.isRunning = isRunning.LastValue;
return plain;
}
- protected async Task OnlineToPlainAsync(global::Pocos.misc.Motor plain)
+ protected async Task OnlineToPlainAsync(global::Pocos.CompilerOmmitsMisc.ComersMotor plain)
{
plain.isRunning = isRunning.LastValue;
return plain;
@@ -1235,7 +1243,7 @@ public async virtual Task PlainToOnline(T plain, eAccessPriority priority = e
await this.PlainToOnlineAsync((dynamic)plain, priority);
}
- public async Task> PlainToOnlineAsync(global::Pocos.misc.Motor plain, eAccessPriority priority = eAccessPriority.Normal)
+ public async Task> PlainToOnlineAsync(global::Pocos.CompilerOmmitsMisc.ComersMotor plain, eAccessPriority priority = eAccessPriority.Normal)
{
#pragma warning disable CS0612
isRunning.LethargicWrite(plain.isRunning);
@@ -1245,7 +1253,7 @@ public async Task> PlainToOnlineAsync(global::Pocos.
[Obsolete("This method should not be used if you indent to access the controllers data. Use `PlainToOnline` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _PlainToOnlineNoacAsync(global::Pocos.misc.Motor plain)
+ public async Task _PlainToOnlineNoacAsync(global::Pocos.CompilerOmmitsMisc.ComersMotor plain)
{
#pragma warning disable CS0612
isRunning.LethargicWrite(plain.isRunning);
@@ -1257,14 +1265,14 @@ public async virtual Task ShadowToPlain()
return await (dynamic)this.ShadowToPlainAsync();
}
- public async Task ShadowToPlainAsync()
+ public async Task ShadowToPlainAsync()
{
- global::Pocos.misc.Motor plain = new global::Pocos.misc.Motor();
+ global::Pocos.CompilerOmmitsMisc.ComersMotor plain = new global::Pocos.CompilerOmmitsMisc.ComersMotor();
plain.isRunning = isRunning.Shadow;
return plain;
}
- protected async Task ShadowToPlainAsync(global::Pocos.misc.Motor plain)
+ protected async Task ShadowToPlainAsync(global::Pocos.CompilerOmmitsMisc.ComersMotor plain)
{
plain.isRunning = isRunning.Shadow;
return plain;
@@ -1275,7 +1283,7 @@ public async virtual Task PlainToShadow(T plain)
await this.PlainToShadowAsync((dynamic)plain);
}
- public async Task> PlainToShadowAsync(global::Pocos.misc.Motor plain)
+ public async Task> PlainToShadowAsync(global::Pocos.CompilerOmmitsMisc.ComersMotor plain)
{
isRunning.Shadow = plain.isRunning;
return this.RetrievePrimitives();
@@ -1291,7 +1299,7 @@ public async virtual Task AnyChangeAsync(T plain)
///Compares if the current plain object has changed from the previous object.This method is used by the framework to determine if the object has changed and needs to be updated.
///[!NOTE] Any member in the hierarchy that is ignored by the compilers (e.g. when CompilerOmitAttribute is used) will not be compared, and therefore will not be detected as changed.
///
- public async Task DetectsAnyChangeAsync(global::Pocos.misc.Motor plain, global::Pocos.misc.Motor latest = null)
+ public async Task DetectsAnyChangeAsync(global::Pocos.CompilerOmmitsMisc.ComersMotor plain, global::Pocos.CompilerOmmitsMisc.ComersMotor latest = null)
{
var somethingChanged = false;
if (latest == null)
@@ -1310,9 +1318,9 @@ public void Poll()
this.RetrievePrimitives().ToList().ForEach(x => x.Poll());
}
- public global::Pocos.misc.Motor CreateEmptyPoco()
+ public global::Pocos.CompilerOmmitsMisc.ComersMotor CreateEmptyPoco()
{
- return new global::Pocos.misc.Motor();
+ return new global::Pocos.CompilerOmmitsMisc.ComersMotor();
}
private IList Children { get; } = new List();
@@ -1396,14 +1404,15 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
- public partial class Vehicle : AXSharp.Connector.ITwinObject
+ [AXSharp.Connector.SourceFileAttribute(@"compileromitsattribute.st")]
+ public partial class ComersVehicle : AXSharp.Connector.ITwinObject
{
- public misc.Motor m { get; }
+ public CompilerOmmitsMisc.ComersMotor m { get; }
public OnlinerInt displacement { get; }
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
partial void PostConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
- public Vehicle(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail)
+ public ComersVehicle(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail)
{
this.@SymbolTail = symbolTail;
this.@Connector = parent.GetConnector();
@@ -1411,7 +1420,7 @@ public Vehicle(AXSharp.Connector.ITwinObject parent, string readableTail, string
HumanReadable = AXSharp.Connector.Connector.CreateHumanReadable(parent.HumanReadable, readableTail);
Symbol = AXSharp.Connector.Connector.CreateSymbol(parent.Symbol, symbolTail);
PreConstruct(parent, readableTail, symbolTail);
- m = new misc.Motor(this, "m", "m");
+ m = new CompilerOmmitsMisc.ComersMotor(this, "m", "m");
displacement = @Connector.ConnectorAdapter.AdapterFactory.CreateINT(this, "displacement", "displacement");
parent.AddChild(this);
parent.AddKid(this);
@@ -1423,9 +1432,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
return await (dynamic)this.OnlineToPlainAsync(priority);
}
- public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
+ public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
{
- global::Pocos.misc.Vehicle plain = new global::Pocos.misc.Vehicle();
+ global::Pocos.CompilerOmmitsMisc.ComersVehicle plain = new global::Pocos.CompilerOmmitsMisc.ComersVehicle();
await this.ReadAsync(priority);
#pragma warning disable CS0612
plain.m = await m._OnlineToPlainNoacAsync();
@@ -1436,9 +1445,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _OnlineToPlainNoacAsync()
+ public async Task _OnlineToPlainNoacAsync()
{
- global::Pocos.misc.Vehicle plain = new global::Pocos.misc.Vehicle();
+ global::Pocos.CompilerOmmitsMisc.ComersVehicle plain = new global::Pocos.CompilerOmmitsMisc.ComersVehicle();
#pragma warning disable CS0612
plain.m = await m._OnlineToPlainNoacAsync();
#pragma warning restore CS0612
@@ -1446,7 +1455,7 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
return plain;
}
- protected async Task OnlineToPlainAsync(global::Pocos.misc.Vehicle plain)
+ protected async Task OnlineToPlainAsync(global::Pocos.CompilerOmmitsMisc.ComersVehicle plain)
{
#pragma warning disable CS0612
plain.m = await m._OnlineToPlainNoacAsync();
@@ -1460,7 +1469,7 @@ public async virtual Task PlainToOnline(T plain, eAccessPriority priority = e
await this.PlainToOnlineAsync((dynamic)plain, priority);
}
- public async Task> PlainToOnlineAsync(global::Pocos.misc.Vehicle plain, eAccessPriority priority = eAccessPriority.Normal)
+ public async Task> PlainToOnlineAsync(global::Pocos.CompilerOmmitsMisc.ComersVehicle plain, eAccessPriority priority = eAccessPriority.Normal)
{
#pragma warning disable CS0612
await this.m._PlainToOnlineNoacAsync(plain.m);
@@ -1473,7 +1482,7 @@ public async Task> PlainToOnlineAsync(global::Pocos.
[Obsolete("This method should not be used if you indent to access the controllers data. Use `PlainToOnline` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _PlainToOnlineNoacAsync(global::Pocos.misc.Vehicle plain)
+ public async Task _PlainToOnlineNoacAsync(global::Pocos.CompilerOmmitsMisc.ComersVehicle plain)
{
#pragma warning disable CS0612
await this.m._PlainToOnlineNoacAsync(plain.m);
@@ -1488,15 +1497,15 @@ public async virtual Task ShadowToPlain()
return await (dynamic)this.ShadowToPlainAsync();
}
- public async Task ShadowToPlainAsync()
+ public async Task ShadowToPlainAsync()
{
- global::Pocos.misc.Vehicle plain = new global::Pocos.misc.Vehicle();
+ global::Pocos.CompilerOmmitsMisc.ComersVehicle plain = new global::Pocos.CompilerOmmitsMisc.ComersVehicle();
plain.m = await m.ShadowToPlainAsync();
plain.displacement = displacement.Shadow;
return plain;
}
- protected async Task ShadowToPlainAsync(global::Pocos.misc.Vehicle plain)
+ protected async Task ShadowToPlainAsync(global::Pocos.CompilerOmmitsMisc.ComersVehicle plain)
{
plain.m = await m.ShadowToPlainAsync();
plain.displacement = displacement.Shadow;
@@ -1508,7 +1517,7 @@ public async virtual Task PlainToShadow(T plain)
await this.PlainToShadowAsync((dynamic)plain);
}
- public async Task> PlainToShadowAsync(global::Pocos.misc.Vehicle plain)
+ public async Task> PlainToShadowAsync(global::Pocos.CompilerOmmitsMisc.ComersVehicle plain)
{
await this.m.PlainToShadowAsync(plain.m);
displacement.Shadow = plain.displacement;
@@ -1525,7 +1534,7 @@ public async virtual Task AnyChangeAsync(T plain)
///Compares if the current plain object has changed from the previous object.This method is used by the framework to determine if the object has changed and needs to be updated.
///[!NOTE] Any member in the hierarchy that is ignored by the compilers (e.g. when CompilerOmitAttribute is used) will not be compared, and therefore will not be detected as changed.
///
- public async Task DetectsAnyChangeAsync(global::Pocos.misc.Vehicle plain, global::Pocos.misc.Vehicle latest = null)
+ public async Task DetectsAnyChangeAsync(global::Pocos.CompilerOmmitsMisc.ComersVehicle plain, global::Pocos.CompilerOmmitsMisc.ComersVehicle latest = null)
{
var somethingChanged = false;
if (latest == null)
@@ -1546,9 +1555,9 @@ public void Poll()
this.RetrievePrimitives().ToList().ForEach(x => x.Poll());
}
- public global::Pocos.misc.Vehicle CreateEmptyPoco()
+ public global::Pocos.CompilerOmmitsMisc.ComersVehicle CreateEmptyPoco()
{
- return new global::Pocos.misc.Vehicle();
+ return new global::Pocos.CompilerOmmitsMisc.ComersVehicle();
}
private IList Children { get; } = new List();
@@ -1633,11 +1642,12 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
}
}
-namespace UnknownArraysShouldNotBeTraspiled
+namespace CompilerOmmitsUnknownArrays
{
+ [AXSharp.Connector.SourceFileAttribute(@"compileromitsattribute.st")]
public partial class ClassWithArrays : AXSharp.Connector.ITwinObject
{
- public UnknownArraysShouldNotBeTraspiled.Complex[] _complexKnown { get; }
+ public CompilerOmmitsUnknownArrays.Complex[] _complexKnown { get; }
public OnlinerByte[] _primitive { get; }
partial void PreConstruct(AXSharp.Connector.ITwinObject parent, string readableTail, string symbolTail);
@@ -1650,8 +1660,8 @@ public ClassWithArrays(AXSharp.Connector.ITwinObject parent, string readableTail
this.@Parent = parent;
HumanReadable = AXSharp.Connector.Connector.CreateHumanReadable(parent.HumanReadable, readableTail);
PreConstruct(parent, readableTail, symbolTail);
- _complexKnown = new UnknownArraysShouldNotBeTraspiled.Complex[11];
- AXSharp.Connector.BuilderHelpers.Arrays.InstantiateArray(_complexKnown, this, "_complexKnown", "_complexKnown", (p, rt, st) => new UnknownArraysShouldNotBeTraspiled.Complex(p, rt, st), new[] { (0, 10) });
+ _complexKnown = new CompilerOmmitsUnknownArrays.Complex[11];
+ AXSharp.Connector.BuilderHelpers.Arrays.InstantiateArray(_complexKnown, this, "_complexKnown", "_complexKnown", (p, rt, st) => new CompilerOmmitsUnknownArrays.Complex(p, rt, st), new[] { (0, 10) });
_primitive = new OnlinerByte[11];
AXSharp.Connector.BuilderHelpers.Arrays.InstantiateArray(_primitive, this, "_primitive", "_primitive", (p, rt, st) => @Connector.ConnectorAdapter.AdapterFactory.CreateBYTE(p, rt, st), new[] { (0, 10) });
parent.AddChild(this);
@@ -1664,9 +1674,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
return await (dynamic)this.OnlineToPlainAsync(priority);
}
- public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
+ public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
{
- global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays plain = new global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays();
+ global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays plain = new global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays();
await this.ReadAsync(priority);
#pragma warning disable CS0612
plain._complexKnown = _complexKnown.Select(async p => await p._OnlineToPlainNoacAsync()).Select(p => p.Result).ToArray();
@@ -1677,9 +1687,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _OnlineToPlainNoacAsync()
+ public async Task _OnlineToPlainNoacAsync()
{
- global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays plain = new global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays();
+ global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays plain = new global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays();
#pragma warning disable CS0612
plain._complexKnown = _complexKnown.Select(async p => await p._OnlineToPlainNoacAsync()).Select(p => p.Result).ToArray();
#pragma warning restore CS0612
@@ -1689,7 +1699,7 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- protected async Task _OnlineToPlainNoacAsync(global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays plain)
+ protected async Task _OnlineToPlainNoacAsync(global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays plain)
{
#pragma warning disable CS0612
plain._complexKnown = _complexKnown.Select(async p => await p._OnlineToPlainNoacAsync()).Select(p => p.Result).ToArray();
@@ -1703,7 +1713,7 @@ public async virtual Task PlainToOnline(T plain, eAccessPriority priority = e
await this.PlainToOnlineAsync((dynamic)plain, priority);
}
- public async Task> PlainToOnlineAsync(global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays plain, eAccessPriority priority = eAccessPriority.Normal)
+ public async Task> PlainToOnlineAsync(global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays plain, eAccessPriority priority = eAccessPriority.Normal)
{
var __complexKnown_i_FE8484DAB3 = 0;
#pragma warning disable CS0612
@@ -1718,7 +1728,7 @@ public async Task> PlainToOnlineAsync(global::Pocos.
[Obsolete("This method should not be used if you indent to access the controllers data. Use `PlainToOnline` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _PlainToOnlineNoacAsync(global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays plain)
+ public async Task _PlainToOnlineNoacAsync(global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays plain)
{
var __complexKnown_i_FE8484DAB3 = 0;
#pragma warning disable CS0612
@@ -1735,15 +1745,15 @@ public async virtual Task ShadowToPlain()
return await (dynamic)this.ShadowToPlainAsync();
}
- public async Task ShadowToPlainAsync()
+ public async Task ShadowToPlainAsync()
{
- global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays plain = new global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays();
+ global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays plain = new global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays();
plain._complexKnown = _complexKnown.Select(async p => await p.ShadowToPlainAsync()).Select(p => p.Result).ToArray();
plain._primitive = _primitive.Select(p => p.Shadow).ToArray();
return plain;
}
- protected async Task ShadowToPlainAsync(global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays plain)
+ protected async Task ShadowToPlainAsync(global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays plain)
{
plain._complexKnown = _complexKnown.Select(async p => await p.ShadowToPlainAsync()).Select(p => p.Result).ToArray();
plain._primitive = _primitive.Select(p => p.Shadow).ToArray();
@@ -1755,7 +1765,7 @@ public async virtual Task PlainToShadow(T plain)
await this.PlainToShadowAsync((dynamic)plain);
}
- public async Task> PlainToShadowAsync(global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays plain)
+ public async Task> PlainToShadowAsync(global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays plain)
{
var __complexKnown_i_FE8484DAB3 = 0;
_complexKnown.Select(p => p.PlainToShadowAsync(plain._complexKnown[__complexKnown_i_FE8484DAB3++])).ToArray();
@@ -1774,7 +1784,7 @@ public async virtual Task AnyChangeAsync(T plain)
///Compares if the current plain object has changed from the previous object.This method is used by the framework to determine if the object has changed and needs to be updated.
///[!NOTE] Any member in the hierarchy that is ignored by the compilers (e.g. when CompilerOmitAttribute is used) will not be compared, and therefore will not be detected as changed.
///
- public async Task DetectsAnyChangeAsync(global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays plain, global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays latest = null)
+ public async Task DetectsAnyChangeAsync(global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays plain, global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays latest = null)
{
if (latest == null)
latest = await this._OnlineToPlainNoacAsync();
@@ -1803,9 +1813,9 @@ public void Poll()
this.RetrievePrimitives().ToList().ForEach(x => x.Poll());
}
- public global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays CreateEmptyPoco()
+ public global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays CreateEmptyPoco()
{
- return new global::Pocos.UnknownArraysShouldNotBeTraspiled.ClassWithArrays();
+ return new global::Pocos.CompilerOmmitsUnknownArrays.ClassWithArrays();
}
private IList Children { get; } = new List();
@@ -1889,6 +1899,7 @@ public System.String GetHumanReadable(System.Globalization.CultureInfo culture)
public AXSharp.Connector.Localizations.Translator Interpreter => global::units.PlcTranslator.Instance;
}
+ [AXSharp.Connector.SourceFileAttribute(@"compileromitsattribute.st")]
public partial class Complex : AXSharp.Connector.ITwinObject
{
public OnlinerString HelloString { get; }
@@ -1916,9 +1927,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
return await (dynamic)this.OnlineToPlainAsync(priority);
}
- public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
+ public async Task OnlineToPlainAsync(eAccessPriority priority = eAccessPriority.Normal)
{
- global::Pocos.UnknownArraysShouldNotBeTraspiled.Complex plain = new global::Pocos.UnknownArraysShouldNotBeTraspiled.Complex();
+ global::Pocos.CompilerOmmitsUnknownArrays.Complex plain = new global::Pocos.CompilerOmmitsUnknownArrays.Complex();
await this.ReadAsync(priority);
plain.HelloString = HelloString.LastValue;
plain.Id = Id.LastValue;
@@ -1927,9 +1938,9 @@ public async virtual Task OnlineToPlain(eAccessPriority priority = eAccess
[Obsolete("This method should not be used if you indent to access the controllers data. Use `OnlineToPlain` instead.")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- public async Task _OnlineToPlainNoacAsync()
+ public async Task _OnlineToPlainNoacAsync()
{
- global::Pocos.UnknownArraysShouldNotBeTraspiled.Complex plain = new global::Pocos.UnknownArraysShouldNotBeTraspiled.Complex();
+ global::Pocos.CompilerOmmitsUnknownArrays.Complex plain = new global::Pocos.CompilerOmmitsUnknownArrays.Complex();
plain.HelloString = HelloString.LastValue;
plain.Id = Id.LastValue;
return plain;
@@ -1937,7 +1948,7 @@ public async virtual Task