Skip to content

Merge Dev to Main - #2168

Merged
RobertvanderHulst merged 204 commits into
mainfrom
dev
Nov 10, 2026
Merged

RobertvanderHulst merged 204 commits into
mainfrom
dev

Conversation

@RobertvanderHulst

Copy link
Copy Markdown
Member

Merge Dev to Main

fforay and others added 30 commits September 4, 2026 12:29
…ated to the current opened Form; then copy back them to the original X# project.
…er() for string comparisons. And using OrdinalIgnoreCase or Ordinal comparisons for strings
* [VsIntegration] CPS project system: new ProjectSystemCPS project and WP-1 skeleton

First step of the MPFproj -> CPS migration (WP-1: project type registration & skeleton).

- New SDK-style project src/VisualStudio/ProjectSystemCPS (net48, XSharp.ProjectSystemCPS.dll),
  references only XSharpCodeModelXs (never ProjectBase/ProjectPackage). Part of
  VSIntegration2022.sln and Master.slnx.
- XSharpProjectSystemPackage registers a CPS project type for .xsproj with the reserved
  guidCpsProjectType {AB494DCE-...}, template language "XSharpCps" and the initial capability
  "XSharpCps". Only compiled with XSHARPCPS (Debug), so the Release VSIX does not register it
  and MPFproj stays the default project system (side by side via the project type GUID).
- XSharpCpsGlobalPropertiesProvider sets XSharpCpsProjectSystem=true for projects loaded by the
  CPS project type.
- X# MSBuild: XSharp.DesignTime.targets revived; it imports VS' Microsoft.Managed.DesignTime.targets
  (managed project system: Dependencies tree, PackageReference, launch profiles, property pages)
  and removes the LanguageService/ReferencesFolder capabilities (no Roslyn workspace for X#).
  It is only imported when XSharpCpsProjectSystem is true, so MPFproj and command line builds
  are unchanged. New Rules/ProjectItemsSchema.XSharp.xaml (.prg/.prgx/.xs -> Compile, headers -> None).
- ProjectPackage2022 ships XSharp.ProjectSystemCPS.dll + pkgdef in its VSIX.
- Test bed src/VisualStudio/ProjectSystemCPS.TestBed: SDK-style CpsTestBed.xsproj, CpsTestBed.sln
  with the CPS project type GUID, StartExp.cmd (starts the VS 2022 experimental instance with the
  repository X# MSBuild files, without changing the installed X#).

Verified from the command line: normal builds unchanged; with the CPS property the managed
capabilities and rules are present and the design-time build returns the compiler switches and
resolved references. Acceptance test in the VS experimental instance still pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system WP-5: XSharpProjectAdapter feeds the code model

XSharpProjectAdapter (IProjectDynamicLoadComponent + IXSharpProject, one per UnconfiguredProject,
active configuration) creates the unchanged XProject and feeds it from CPS instead of MPFproj
hierarchy walking and .rsp parsing:
- source items (evaluation) -> XProject.AddFile/RemoveFile, ModelWalker.AddProject
- XSharpProjectProperties + EvaluatedProjectReference (evaluation) -> RootNamespace, output paths,
  NS, provisional dialect, X# project references (AddProjectReference/RemoveProjectReference)
- XSharpCompilerCommandLineArgs (design-time build, CompileDesignTime without running xsc)
  -> XParseOptions.FromVsValues/ResetParseOptions and RefreshReferences/ResolveReferences,
  so parse options and references are correct before the first real build.

XSharpCommandLine maps the Xsc switches to the FromVsValues format (as XSharpProjectOptions
does for MPFproj). IntellisenseErrorStore keeps the code model errors per file (no Error List yet).
If the X# solution model is not open yet, the adapter loads the X# project package by GUID.

New rules Rules/XSharpCompilerCommandLineArgs.xaml and Rules/XSharpProjectProperties.xaml
(Context ProjectSubscriptionService), registered in XSharp.DesignTime.targets.

Verified from the command line with the design-time output of a VO dialect project
(dialect, /ns, defines, include path, references). Acceptance test in VS pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system WP-2: project capabilities and X# icons

- Initial capabilities of the CPS project type (ProjectTypeRegistration.Capabilities), modelled on
  the managed C# project type: XSharpCps; AppDesigner; HandlesOwnReload; OpenProjectFile;
  PreserveFormatting; ProjectConfigurationsDeclaredDimensions; .NET; UseProjectEvaluationCache
  (without LanguageService, CSharp, SharedImports and EditAndContinue).
- XSharp.DesignTime.targets adds ProjectPropertiesEditor (new property editor for the XAML
  property pages of WP-4) to the managed capability set.
- The managed project system only provides project icons for C#/VB/F# (internal
  IProjectImageProvider): XSharpProjectTreePropertiesProvider sets the X# project icon and the
  X# document icon for .prg/.prgx/.xs files via IProjectTreePropertiesProvider.
  New XSharp.ProjectSystemCPS.imagemanifest (images as WPF resources in the assembly),
  shipped as ImageManifest asset in the ProjectPackage2022 VSIX.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system WP-3: X# item types and item templates

- ProjectItemsSchema.XSharp.xaml maps .rc to NativeResource and the VO binaries
  (.xsfrm/.vnfrm/.xsdbs/.vndbs/.xsmnu/.vnmnu/.xsfs/.vnfs/.xssql/.xsrep) to VOBinary.
- NativeResource/VOBinary File and BrowseObject rules restored from 58cca0eaeb^ and registered
  in XSharp.DesignTime.targets; fixed CustomTool/SubType data sources that still used ItemType None.
- AddItemTemplatesGuid, GeneratorsTypeGuid and CmdUIContextGuid now use the X# project factory
  GUID {AA6C8D78-...} instead of the C# values, so CPS projects get the X# item templates and
  single file generators that the X# project package already registers there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system WP-4: X# property pages as XAML rules

Property pages for the new property editor (capability ProjectPropertiesEditor), restored
from 58cca0eaeb^ and registered with Context Project in XSharp.DesignTime.targets:
- LanguagePage.XSharp.xaml (Language) and DialectPage.XSharp.xaml (Dialect)
- BuildPropertyPage.XSharp.xaml and ApplicationPropertyPage.XSharp.xaml extend the managed
  Build/Application pages (OverrideMode="Extend")
- ReferencesPage.XSharp.xaml (Global Usings)

Corrected against the property names read by the Xsc task and persisted by MPFproj:
Stddefs -> StandardDefs, OtherFlags -> CommandLineOption, UseShared -> UseSharedCompilation,
INS as bool; added the missing VO17 and FOX3 dialect options.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system WP-6: commands side by side, Error List and Task List

MPFproj commands (ProjectPackage) with X# projects loaded by CPS, where XProject.ProjectNode is
the XSharpProjectAdapter instead of an XSharpProjectNode:
- CommandGenerateWinForm: hard cast replaced by a type check (would throw InvalidCastException)
- CommandAddDesignerFile: only visible for MPFproj projects (needs the MPFproj file node)
- CommandEditProjectFile: only visible for MPFproj projects (CPS has its own Edit Project File)
- new helper Commands.ProjectIsMpfProjectAsync()

ProjectSystemCPS replacements for the MPFproj ErrorListManager/TaskListManager:
- IntellisenseErrorList shows the code model errors of the project in the Error List
- CommentTaskList shows the comment tasks after project/file walks in the Task List
Both refresh coalesced on the UI thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system WP-7: VO designers through the adapter

The VO editor panes hold the IXSharpProject of the file's XProject, which is the
XSharpProjectAdapter for CPS projects, so the VO designers are served through the adapter.

The designers (XSharpVoEditors Functions.EnsureFileNodeExists/DeleteFile) write generated
files to disk and then call HasFileNode/AddFileNode/DeleteFileNode. The adapter now registers
and unregisters these files with the code model immediately instead of ignoring the calls;
in SDK-style projects the XSharp.SDK.Props globs include them (with DependentUpon), so the
project file does not change and CPS confirms the item with the next evaluation.
HasFileNode compares full paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: make the project properties UI available

X# CPS projects had no project properties UI: CPS only offers the project designer when at least
one IVsProjectDesignerPageProvider applies (VsProjectDesignerPageService.IsProjectDesignerSupported),
and the managed project system only has providers for C#, VB and F#.

- New XSharpProjectDesignerPageProvider ([AppliesTo("XSharpCps & AppDesigner")]). It lists no
  classic COM pages: with the ProjectPropertiesEditor capability the AppDesigner editor factory
  opens the new property editor, which shows the XAML rules (managed pages + X# pages).
- ProjectPropertiesEditor is now also an initial capability of the project type, so the new
  editor does not depend on the X# targets that declare it in XSharp.DesignTime.targets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: project selector for SDK-style and legacy projects

Two X# project systems side by side, like the legacy and SDK project systems of C#/VB/F#:
legacy .xsproj stay on MPFproj ({AA6C8D78-...}), SDK-style .xsproj are loaded by CPS
({AB494DCE-...}).

- XSharpProjectSelector (IVsProjectSelector, the reserved guidProjectSelectorString) is
  registered for the MPFproj project type and sends projects with <Project Sdk>, <Import Sdk>
  or <Sdk Name> to the CPS project type. Existing solution files keep their project type GUID.
  Unreadable project files and errors fall back to MPFproj.
- ProvideProjectSelectorAttribute writes Projects\{AA6C8D78}\ProjectSelector and
  ProjectSelectors\{selector}\Package; the package registers the selector with
  IVsRegisterProjectSelector during initialization and unregisters it on dispose.
- Tools > Options > X# > Project System: "Load SDK-style projects with the new project system
  (CPS)" (default on) switches the routing off without uninstalling anything.
- Still only registered with XSHARPCPS (Debug builds).
- Test bed: Legacy/LegacyTestBed.xsproj and SelectorTestBed.sln (both projects with the MPFproj
  GUID); StartExp.cmd takes the solution as optional parameter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: open the X# solution model for CPS-only solutions

Found in the log of the first VS test: "XSharpProjectAdapter: X# solution model is not open,
no code model". XSolution.Open is called by the X# project package in OnBeforeOpenSolution.
For solutions with the MPFproj project type VS loads that package before the solution opens
(it provides the project factory); for the CPS project type it is only autoloaded later, misses
OnBeforeOpenSolution and does not see the solution yet while it is still opening, so the
database was never opened and the CPS project got no code model.

- XSharpProjectAdapter: after loading the X# project package, open the solution model for the
  solution file reported by IVsSolution.GetSolutionInfo, instead of waiting 10s and giving up.
- XSharpShellLink.OnAfterOpenSolution: open the solution model before XSolution.AfterOpen()
  when it is still closed (safety net for any late package load).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: fix source item subscription, first VS test results

Found in the experimental instance: the CPS code model got parse options and references from
the design-time build, but never any source files. LinkTo without rule names subscribes to an
empty rule set, so the SourceItemsRuleSource link delivered nothing. The source item rules are
dynamic (one per item type): link with SourceItemRuleNamesSource as the rule names block, as
dotnet/project-system does. Added a log line with the evaluated project properties.

Verified in VS (SelectorTestBed.sln): the selector loads CpsTestBed through CPS and
LegacyTestBed through MPFproj; the adapter opens the solution model, adds Program.prg, the
walker parses it, the design-time build delivers 58 options and 10 references; editing the
project file removes files live.

Test bed: CpsTestBed.xsproj excludes the Legacy subfolder from its globs (it compiled the
legacy project's Start.prg as well).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS test bed: refresh the image library cache of the experimental instance

The X# project icon was not shown in the experimental instance: its ImageLibrary.cache dated
from 2024 and did not contain XSharp.ProjectSystemCPS.imagemanifest, because the Debug build
deploys the VSIX without refreshing that cache. StartExp.cmd now deletes the cache of the
experimental instance before starting; VS rebuilds it (verified: the manifest is in the rebuilt
cache). Normal VSIX installations refresh the cache themselves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: register the CPS project type in Release builds

The CPS project type, the project selector and the Tools > Options page were only registered
with XSHARPCPS (Debug builds). The define and the conditional code are removed, so the Release
VSIX registers them as well.

Safety net for the shipped product: the selector only sends SDK-style projects to CPS when the
installed X# MSBuild support files contain the CPS design-time import (XSharpCpsProjectSystem in
XSharp.CurrentVersion.targets) and the XAML rules (new XSharpMsBuildSupport; folder from
XSharpMsBuildDir, the registry or Program Files (x86)\XSharp\MsBuild, like
XSharp.BeforeCommon.Props). With an older X# installation SDK-style projects stay on MPFproj
instead of loading in CPS without rules. Verified: installed X# -> false, repository overlay
(StartExp.cmd) -> true.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Port the shadow WinForms designer to the CPS project system

Prerequisite for removing the MPFproj SDK path (WP-8): the shadow designer (WinForms designer
for SDK-style X# projects via a hidden companion C# project) was built on the MPFproj SDK
project node, so SDK projects loaded by CPS had no WinForms designer.

- ShadowDesigner moved from ProjectPackage to ProjectSystemCPS (namespace
  XSharp.ProjectSystem.ShadowDesigner) and made project system independent:
  ShadowDesignerBridge.TryOpen/TryResolveCompanionPaths take the .prg path and the XProject
  instead of an XSharpFileNode; services from the global service provider instead of the MPFproj
  node/package; ShadowDesignerCleanup implements IVsSolutionEvents instead of deriving from the
  MPFproj SolutionListener; no Community Toolkit dependency. Public helpers IsCpsProject and
  HasDesignerFile.
- XSharpCodeDomHelper (BuildDesignerFileName, MergeCodeCompileUnit, ...) moved from
  ProjectPackage to the shared CodeDomProvider project, so both project systems can use it.
- CPS entry points: XSharpShadowDesignerDefaultActionCommand (double click / Enter) and
  XSharpShadowDesignerViewFormCommand (View Designer) open the shadow designer for a .prg with a
  matching .Designer.prg; otherwise CPS falls back to its default action.
- MPFproj keeps working: XSharpFileNode calls the new API; the Sync Designer Changes / Sync Event
  Handlers commands now work for SDK projects in MPFproj and in CPS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS test bed: SDK-style WinForms project for the shadow designer

WinForms/WinFormsTestBed.xsproj (net8.0-windows, UseWindowsForms, Core dialect, from the
CoreWinFormApp template) with Form1.prg/Form1.designer.prg, added to SelectorTestBed.sln with the
classic X# project type GUID, so it is loaded by CPS through the project selector. Double click or
View Designer on Form1.prg must open the shadow WinForms designer. CpsTestBed.xsproj excludes the
WinForms subfolder from its globs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Keep XSharpCodeDomHelper out of the GAC'd XSharp.CodeDomProvider

VS test: "Could not load type 'XSharp.CodeDom.XSharpCodeDomHelper' from assembly
'XSharp.CodeDomProvider, Version=3.0.2.0'". The X# installation puts XSharp.CodeDomProvider (and
XSharp.VSParser, XSharp.Evaluator) in the GAC with the same assembly version, and the GAC copy wins
over the one in the VSIX, so the class moved there in the shadow designer port was not found.

- XSharpCodeDomHelper back in ProjectPackage/CodeDomProvider; CodeDomProvider.csproj and the VS 2019
  ProjectPackage.csproj are unchanged compared to before the port again.
- ProjectSystemCPS links the same source file as an internal copy (define XSHARP_PROJECTSYSTEMCPS),
  so the shadow designer does not depend on a GAC'd assembly version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Keep shadow designer companion projects out of X# SDK globs

VS test: the shadow designer opened the first time, the second time the WinForms designer
reported that Form1.Designer.cs "is not contained within a project that supports code". The
companion C# project ({Project}.ShadowDesigner) is generated next to the X# project folder, so the
X# project's own globs never see it -- but an SDK-style X# project in a parent folder does
(here CpsTestBed, which contains the WinForms test project). After the first open the generated
.cs files were None items of that X# project, VS used it as the owning hierarchy of
Form1.Designer.cs and the designer refused it.

XSharp.SDK.Props excludes **/*.ShadowDesigner/** from the default items of every X# SDK project
(before XSharpDefaultItemExcludes captures DefaultItemExcludes, so the X# specific globs skip it
too). Verified with a dummy companion folder: installed props -> None item, fixed props -> excluded.
StartExp.cmd copies XSharp.SDK.Props into the overlay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: form, user control and VO binary icons

VS test: X# forms showed the X# document icon in CPS projects. XSharpProjectTreePropertiesProvider
now mirrors XSharpFileNode (MPFproj): a .prg is a form/user control when its SubType says so, or
when it has a matching .Designer.prg and its class inherits from Form/UserControl (same inference
as the MPFproj SDK node, cached per file timestamp) -> KnownImageIds.WindowsForm / UserControl.
VO binaries get the MPFproj icons (FormInstance, Database, MainMenuControl, ValidationRule, Report).
The item path comes from the FullPath metadata (ItemName is only the file name).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Shadow designer: remove the empty companion solution folder on close

VS test: after closing, the saved .sln still contained the "Shadow Designer (generated)"
Solution Folder. ShadowDesignerCleanup removed the companion projects in OnQueryCloseSolution,
but not the folder they were nested in (behaviour inherited from the MPFproj implementation).
It now also removes that folder when it is empty (IVsSolution.CloseSolutionElement, like the
companion projects), so the .sln stays unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: register the project selector for the CPS project type GUID too

When VS saves a solution it writes the GUID of the factory that loaded the
project, so an SDK project's .sln entry flips from {AA6C8D78} (MPFproj) to
{AB494DCE} (CPS). C# SDK projects flip the same way ({FAE04EC0} ->
{9A19103F}), and VS offers no way to keep the original GUID. Routing the CPS
GUID through the same selector means those entries still load with MPFproj
when the routing option is off, the project is not SDK-style, or the
installed X# MSBuild files are too old for CPS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Shadow designer: make the empty solution folder cleanup work

The first version never found the "Shadow Designer (generated)" folder:
solution folders are virtual projects, so GetProjectEnum needs
EPF_ALLPROJECTS rather than EPF_ALLINSOLUTION. Right after the companion
project is removed the folder can still list it as a child without a name
and without a nested project, so such children, and *.ShadowDesigner
projects, no longer count as content. Each step is logged.

Verified in the Exp instance: the folder is removed and is no longer in the
saved .sln.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Shadow designer: resolve assembly references before parsing the form

Opening a form shortly after the solution loaded failed with an
ArgumentNullException ("e") in CSharpCodeGenerator. The project's assembly
references were still queued (XProject.ResolveReferences runs at most every
15 seconds), so System.Windows.Forms.Form could not be resolved and the
parser dropped the right-hand side of assignments. TryOpen already forced
the queued references to load, but only after parsing; it now does so
before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] WP-8: remove the SDK-style project path from MPFproj

SDK-style X# projects are loaded by the CPS project system
(XSharp.ProjectSystemCPS) since the project selector routes them there and
the shadow WinForms designer was ported. MPFproj keeps the legacy projects.

Removed from ProjectPackage (VS 2022 only; VS 2019 never had it):
- NodesSDK (XSharpSdkProjectNode, SDK reference/dependency/folder nodes)
- the debug target "Framework" menu (commandDebuggerFramework.cs), the
  Publish/Pack commands with PublishDialog, and the priority command target
  that intercepted VS's own Publish/Pack. That interception also hid or
  broke Publish/Pack for X# projects loaded by CPS.
- the SDK-only parts of the file node (shadow designer redirect), project
  node (SDK project reference completion), configuration provider and
  shell events, and the matching Menus.vsct/Menus.cs symbols.

The MPFproj factory now rejects an SDK-style project with a clear message
instead of creating the removed node. That only happens when the selector
cannot use CPS (X# MSBuild support files too old).

ProjectSystemCPS: the Tools > Options switch is gone, because MPFproj can no
longer load SDK-style projects. The SDK project file check moved to the
public SdkProjectFile class, which the MPFproj factory uses as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] WP-8: remove the dead SDK-style branches from MPFproj

After the removal of XSharpSdkProjectNode, ProjectNode.IsSdkProject was
always false. Removed the property and every branch that depended on it or on
the project file's Sdk attribute, in ProjectBase and ProjectPackage:
- ProjectFactory.CreateSdkProject (MPFproj rejects SDK-style projects in
  XSharpProjectFactory.CreateProject)
- target framework update, rename and file refresh special cases (ProjectNode,
  FileNode, ProjectElement), project reference guid handling
- XSharpFileNode: <Compile Remove> handling on include, designer inference
  from a .Designer.prg (the CPS tree provider does this now), MarkDirty on
  remove
- XSharpProjectNode reload/upgrade checks, CommandConvertXsRuntime visibility

The legacy code paths are unchanged. ProjectBase (VS 2019) builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: fix the UseNativeVersion and NoWin32Manifest property names

The Application page extension declared "usenativeversion " and
"nowin32manifest  " (with trailing spaces) as property and persisted names.
That is not a valid MSBuild property name: the checkboxes always showed
unchecked and saving wrote nothing usable. Use the names that the Xsc task
reads and MPFproj writes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: hide the Win32 resource file option

The Application page offered the C# choice between "Icon and manifest" and
"Resource file". X# gets its Win32 resources from the Win32Resource item
(compiled from the .rc files); the $(Win32Resource) property is never read.
Choosing "Resource file" made the managed interceptor remove ApplicationIcon
and ApplicationManifest and write a property the build ignores. Hide
ResourceSpecificationKind and Win32Resource; Icon and Manifest stay visible
because the interceptor still evaluates the kind to IconAndManifest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: error squiggles for build errors

In MPFproj the build logger fills the ErrorListManager, and
GetIntellisenseErrors returns those build errors and warnings to
XSharpErrorColorizer, which draws the squiggles. Under CPS the build errors
only reached the VS Error List, and GetIntellisenseErrors stayed empty (the
code model's own AddIntellisenseError is not called anymore), so the editor
showed no squiggles at all.

BuildErrorLoggerProvider (IBuildLoggerProviderAsync) attaches an MSBuild
logger to real builds (Build/Rebuild/Clean, not design-time builds) and
hands the errors and warnings to the adapter. Each build of a configuration
replaces its previous errors; the store merges them with the code model
errors per file. They are not added to the Error List, VS shows them there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: remove the C# global usings editor

"Manage Implicit Global Usings" (ImplicitUsingsEditor) only works through
ImplicitUsingsValueProvider of the managed project system, which maps the
value to <Using> items and applies to CSharp projects only. For X# the
editor read and wrote a meaningless ImplicitUsingsEditor property. The
interceptor contract lives in the private
Microsoft.VisualStudio.ProjectSystem.Managed.dll, so an X# version would tie
the VSIX to one VS build. The "Implicit global usings" switch stays; <Using>
items are edited in the project file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: open the X# solution model before the solution file is saved

The adapter only opened the X# solution model (database) when the .sln
existed on disk, and did not try again. A project opened without a solution
(devenv project.xsproj, File > Open > Project) or a new project lives in a
solution that VS writes only when it is saved, so these projects got no
code model and no IntelliSense. XSolution.Open only needs the folder and the
name, so open it for the (future) solution file, or for the project name
when VS reports no solution file. Also load the X# project package with
IVsShell7.LoadPackageAsync instead of blocking the UI thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: do not pass XSharpCpsProjectSystem to referenced projects

The CPS project type sets XSharpCpsProjectSystem as a global property, and
the MSBuild task calls for project references inherit global properties.
Referenced C# and legacy X# projects were evaluated and built a second time
with different global properties (overbuild, file locks), and referenced X#
projects imported the design-time targets in a normal build. Add it to
_GlobalPropertiesToRemoveFromProjectReferences (verified: a referenced
project now sees an empty value, before it saw 'true').

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: fix a dispose race in the Error List and Task List

Dispose ran on the unloading thread and cleared the provider field while a
refresh could be running on the UI thread past its disposed check. That
refresh then created a new provider that was never disposed, and its
entries stayed in the list after the project was unloaded. Dispose now only
sets the (volatile) flag and removes the provider on the UI thread, where
the refresh runs as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Shadow designer: keep the companions when the solution close is already cancelled

OnQueryCloseSolution removed the companion projects and the "Shadow Designer
(generated)" Solution Folder even when another listener had already cancelled
the close. It now returns right away in that case.

OnQueryCloseSolution is not final: the close can still be cancelled later
(e.g. Cancel in the save prompt). That leaves the solution open without the
companion projects, which is harmless: their paths stay tracked, the next View
Designer adds the project back (SolutionWiring.EnsureProjectInSolution), and
the folders are only deleted after a real close. Documented in the class
remarks. Tested in VS: close, Cancel in the save prompt, View Designer works.

Also removes the stale remark that the class subclasses the MPFproj
SolutionListener; it implements IVsSolutionEvents directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Shadow designer: cancel the pending folder deletion when a companion is used again

After a solution close the companion folders are deleted in the background,
retrying for up to 20 s because the out-of-process designer host still locks
the folder. When the solution was reopened in that time and the designer
opened again, the retry could delete the freshly written companion folder
while the designer used it.

Each background deletion now has a CancellationTokenSource per folder.
ShadowDesignerBridge calls ShadowDesignerCleanup.CancelPendingDelete before it
writes the companion project (new CompanionProjectWriter.ComputeCompanionDir).
Every delete attempt runs under a lock and checks the cancellation first, so
after CancelPendingDelete returns no deletion is running or will start; the
wait between attempts ends early on cancellation.

Tested in VS with the folder locked by a process (cmd working directory):
close, reopen, View Designer within 20 s -> "cancelled the pending deletion",
folder and designer intact after the lock was released.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Shadow designer: companion stub with the real base class

The companion's Form1.cs-equivalent stub always declared
": System.Windows.Forms.Form", while the generated .Designer.cs carries the
real base type. For a user control the two partial declarations named
different base classes (CS0263).

ShadowDesignerBridge.BuildStubCSharp now generates the stub with the same
CSharpCodeProvider, the same base type references and the same namespace
imports as the designer code, so both parts always agree. The stub is where
the designer puts new members (event handler stubs, see EventHandlerSync),
so it is only rewritten while it is still an empty generated stub
(CompanionProjectWriter.IsEmptyStub), e.g. one with an outdated base class.

Verified outside VS: a user control gives ": UserControl" with its using, a
stub with a handler is kept, old and new stub formats are recognized.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Shadow designer: companion target framework from the loaded project

The companion project took its target framework only from <TargetFramework>
in the .xsproj XML, so multi-targeting projects (<TargetFrameworks>) and a
TargetFramework from Directory.Build.props made the designer fail.

The bridge now passes the active target framework of the loaded project
(VSHPROPID_TargetFrameworkMoniker of its hierarchy, converted to the short
form: net8.0, net48, netcoreapp3.1, ...). Without it the writer falls back to
the project file, now including the first entry of <TargetFrameworks>. The
"-windows" suffix is still appended as before.

Verified: moniker conversion for .NETCoreApp 8.0/3.1 and .NETFramework
4.8/4.7.2; the test bed companion gets net8.0-windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Shadow designer: wait for the project load instead of a blocking build

When the package references of the X# project were not resolved yet, the
bridge built the project with EnvDTE BuildProject(WaitForBuildToFinish: true)
-- a nested message pump inside the async CPS command handler. Under CPS a
build does not even refresh the code model's references: they come from the
design-time build (XSharpProjectAdapter), which runs after the NuGet restore.

ShadowDesignerBridge.EnsureReferencesAsync (called by the CPS commands before
TryOpen) now first waits asynchronously for the IntelliSense stage of the
project load (IVsOperationProgressStatusService, up to 60 s) and briefly for
the adapter to process the result. Only when the references are still
missing it offers a build as before, which now runs through
IVsSolutionBuildManager2.StartSimpleUpdateProjectConfiguration and completes
through IVsUpdateSolutionEvents. A second double click during the wait is
swallowed. TryOpen loses its refreshReferences parameter (the MPFproj .rsp
re-read); the class docs no longer mention the removed MPFproj SDK caller.

Not tested in VS: the path only runs for a project with NuGet references
before its restore has finished.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Shadow designer: add new form files to an already loaded companion project

When the companion project was already loaded (another form of the project
was opened before), the bridge wrote the new form's .cs/.Designer.cs into its
folder and opened the designer immediately. The companion includes its files
through the SDK globs, but it did not pick them up in time -- verified in VS,
not even after 10 s -- so the designer failed with "... is not contained
within a project that supports code" and only worked on a second attempt.

TryOpen is split into TryPrepareCompanion (parse, write, add to the solution)
and TryOpenAsync: missing files are added with ProjectItems.AddFromFile, then
it waits (up to 10 s) until IVsProject.IsDocumentInProject finds them, and only
then opens the designer. For files covered by a glob CPS writes no explicit
item into the companion .csproj (verified: the .csproj stays unchanged).

Tested in VS: open a user control (loads the companion), then Form1 -> the
designer opens on the first attempt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Shadow designer: open forms added with "Add New Item" in the designer

The item template wizard opens the new .prg itself, with the default editor
for .prg (the X# code editor), so a new form or user control did not open in
the designer. MPFproj redirected this in XSharpFileNode, which was removed
with the MPFproj SDK path. CPS' own mechanism (IProjectSpecificEditorProvider
with IsDefaultEditor) is not usable: it routes every open of the file to the
project specific editor, also debugger and navigation opens
(LOGVIEWID_Debugging/TextView), which the shadow designer cannot serve.

New NewFormDesignerRedirect (IVsRunningDocTableEvents, advised when the first
X# CPS project loads): on the first window of a document of a CPS X# project
that belongs to a form .prg (a .Designer.prg exists) created within the last
30 s, it waits until the code model knows the file, opens the shadow designer
and, only when that succeeded, closes the code window. Each file is
redirected once per session, so a later View Code is not affected; Add
Existing Item opens no window. XSharpShadowDesignerCommands.TryOpenAsync gets
an overload without IProjectThreadingService for it.

Tested in VS: Add New Item > UserControl in the CPS WinForms project opens the
designer and closes the code editor (about 1.4 s); in the legacy (MPFproj)
project the MPFproj designer opens as before, no redirect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: create the code model on the UI thread

The projects of a solution load in parallel, and the adapters created their
XProjects at the same time on background threads. That raced in the code
model: with a new X# database the lazily created OrphanedFiles project was
added twice and XDatabase.Read failed with SQLite "FOREIGN KEY constraint
failed" (seen in the VS log after deleting the .vs folder). MPFproj creates
its XProjects one after the other on the UI thread; the adapter now switches
to the UI thread before it creates the model as well.

Verified in VS with a fresh database: OrphanedFiles is added once, both
models are created on the UI thread, no SQLite error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: refresh the Task List when a file is saved

The comment tasks (TODO etc.) of a CPS project only showed up after the next
project walk, e.g. after a design-time build, not when the file was saved.
MPFproj walks a changed file again in XSharpProjectNode.OnFileChanged
(WalkFile(file, notify: true)), whose FileWalkComplete event refreshes the
Task List; the CPS adapter had no counterpart.

New ProjectFileSaveWatcher (IVsRunningDocTableEvents, advised when the first
X# CPS project loads): after a save of a source file of an X# CPS project it
walks the file again on a background thread, so the adapter's
FileWalkComplete handler refreshes the Task List.

It also passes the Task List comment tokens (Tools > Options) to the code
model when nobody did yet: the X# project package only sets them when an
MPFproj project opens or after the options dialog, so a solution with only
CPS projects had no comment tasks at all.

Verified in VS: the TODO entry appears right after saving (the save walk
runs on a background thread); "4 comment tokens set" with a fresh database.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: make the image manifest assembly findable at startup

The project and .prg icons of CPS projects were often empty. The image
manifest refers to its PNGs with pack URIs that name XSharp.ProjectSystemCPS
by its short name. The image library resolves them when it builds its cache
at startup, usually before a CPS project has loaded the assembly; no X#
package registered a binding path, so the lookup failed and the whole
manifest was missing from ImageLibrary.cache (no GUID, no images, while e.g.
the IntelliCode manifest was there). The icons only worked when a CPS
project happened to load the assembly first.

- [ProvideBindingPath] on XSharpProjectSystemPackage: the extension folder is
  probed for loads by name, the image library finds the assembly.
- [assembly: ProvideCodeBase(AssemblyName = "XSharp.ProjectSystemCPS")] next to
  the sibling assemblies in ProjectPackage/ExternalAssemblies.cs: loads with
  the full identity work too, e.g. when ProjectPackage2022 uses
  ShadowDesignerBridge before a CPS project has loaded the assembly.

Verified in VS: after StartExp (fresh cache) the cache contains the manifest
GUID and both images, the project and document icons show.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: check the overridable managed design-time targets path

XSharp.DesignTime.targets imports $(XSharpManagedDesignTimeTargetsPath), but
the import gates in XSharp.CurrentVersion.targets and
XSharp.CrossTargeting.targets checked the hard-coded path of
Microsoft.Managed.DesignTime.targets. With the property overridden to a file
that does not exist, the gate passed and the project failed to load (MSB4019).
The property is now defined next to XSharpDesignTimeTargetsPath and the gate
checks it.

Verified from the command line: default -> design-time targets imported;
override to a missing file -> not imported, no error (before: MSB4019);
without XSharpCpsProjectSystem -> unchanged. Project loads in VS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: hide the property page of the NativeResource and VOBinary rules

The File rules of the X# item types were copied from the managed None rule
without PropertyPagesHidden="true" and without the TargetPath property.
Without PropertyPagesHidden the file property dialog shows an extra, empty
page for .rc files and VO binaries. Both are added as in None.xaml.

Tested in VS: Test.rc shows its properties (Build Action Native Resource),
no empty extra page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: map .vnsqs and .vnrep to VOBinary

The X# code model treats .vnsqs as a VO SQL table and .vnrep as a VO report,
like .xssql and .xsrep (FileTypeHelpers), and the icon provider already maps
them, but ProjectItemsSchema.XSharp.xaml did not: such files got no X# item
type when added to a CPS project.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: SuppressRCWarnings on the Build page

The MPFproj Build page has "Suppress Resource Compiler warnings"
(SuppressRCWarnings, passed to the NativeResourceCompiler task, default true
in XSharp.props); the CPS Build page had no rule for it. Added as a bool
property in the "Errors and warnings" category with the MPFproj texts.

Tested in VS: the checkbox shows ticked by default, unticking writes the
property to the project file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: do not hold the adapter lock during code model I/O

The adapter's single lock protected both its file/reference sets and the
calls into the code model. XProject.AddFile/RemoveFile do database I/O and
ResolveReferences loads the referenced assemblies, so HasFileNode, which the
VO designers call on the UI thread, could wait for that I/O.

Two locks now, always taken in the same order: modelGate serializes the
changes of the code model (the three subscriptions, AddFileNode/DeleteFileNode,
load/unload) as before; gate only protects the file set and the model field,
briefly, and HasFileNode only takes gate. ResolveReferences runs outside both
locks: XProject guards it itself (_resolvingReferences), and the ModelWalker
and the type lookups call it without these locks as well.

Tested in VS: projects load, design-time builds apply, files added through
Add New Item reach the code model, completion works.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: less file system access in the tree properties provider

XSharpProjectTreePropertiesProvider runs synchronously on the CPS tree thread
for every node on every tree update. It called File.Exists for every .prg
(is there a .Designer.prg?), read form files completely (File.ReadAllText) to
infer Form/UserControl from the base class, and its cache grew without limit.

- The designer file check uses a listing of the *.Designer.prg files per
  folder, reused for 250 ms and read again when the folder's timestamp
  changes (on NTFS: a file was created, deleted or renamed). 250 ms covers the
  burst of one tree update; longer could miss a .Designer.prg created by Add
  New Item. ShadowDesignerBridge.HasDesignerFile stays uncached (the commands
  and NewFormDesignerRedirect need the current state).
- The base class check reads the file in 4 KB blocks only until the first
  CLASS ... INHERIT declaration, at most 64 KB.
- Both caches are cleared when they exceed 1000 entries.

Verified outside VS (reflection): Form1.prg -> Form, a UserControl whose
declaration follows after ~6 KB -> UserControl, a new .Designer.prg is found
after 0.3 s. Tested in VS: project, document, form and user control icons,
also for a user control added with Add New Item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: do not copy all intellisense errors on every Add

IntellisenseErrorStore built the complete error list of the project on every
Add and handed it to IntellisenseErrorList, which only applies the last one
per (coalesced) UI refresh. The store now only reports the change; the Error
List fetches the errors with IntellisenseErrorStore.GetAll once per refresh
(after resetting its scheduled flag, so a later change schedules the next one).

The code model does not report intellisense errors at the moment (see the
CPS migration spec, WP-6), so this matters once it does again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS test bed: SDK-style VO project for the VO designers

New VO\VOTestBed.xsproj in SelectorTestBed.sln (classic X# project type GUID,
the project selector sends it to CPS), made from the VO SDI Application
template (ProjectPackage/Templates/Projects/Windows/VOSdiApp): a VO window
(Help About.HELPABOUT.xsfrm), two menus (SDI Menus.*.xsmnu), their .prg/.rc
files, the VO designer templates in Properties\ and the resources.
Differences from the template: SDK-style (net48, x86, VO dialect and the
template's compiler options), no AssemblyInfo.prg (the SDK generates the
attributes), no explicit items (the X# SDK globs add .prg/.rc/VO binaries with
DependentUpon), and the X# runtime and VO SDK assemblies referenced with a
HintPath into the X# installation (XSharpPath from the registry).

CpsTestBed.xsproj keeps VO\** out of its globs, including the NativeResource
and VOBinary items. StartExp.cmd describes the test projects.

Verified: builds from the command line; in VS the selector loads it with CPS,
the code model gets all 23 files, the VO window editor opens the window and
saving regenerates the .xsfrm and .rc without changing the project file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: walk source files that change on disk

Under CPS nobody re-read a source file that changed on disk outside the VS
editor. The VO designers write the generated .prg directly to disk when it is
not open in an editor (menu editor: SDI Menus.prg with the new menu IDs,
window editor: Help About.prg with the new control), and the code model kept
the old types until the next project walk (found in the VS test with
VO/VOTestBed). MPFproj covers this in XSharpProjectNode.OnFileChanged
(WalkFile(file, notify: true)).

New SourceFileWatcher (one per project, created by the adapter): a
FileSystemWatcher on the project folder including subfolders. Changes to
source files of the project (adapter: in the file set and XFile.IsSource) are
collected and walked after 500 ms, one walk per file for a burst of writes;
notify: true refreshes the Task List. After a buffer overflow the whole
project is walked again. Files outside the project folder (links) are not
watched.

The watcher also sees saves from the VS editor, so the editor save walk of
ProjectFileSaveWatcher (IVsRunningDocTableEvents.OnAfterSave, 1803b79e2a) is
removed to avoid a second walk per save. What remains of that file, setting
the comment tokens for pure CPS solutions, is now CommentTokens.EnsureSet.

Verified outside VS: 5 quick writes -> one callback 500 ms after the last,
temp file + rename (editor save) -> callback, non-source file -> none, none
after Dispose. Tested in VS: menu editor and window editor saves with the .prg
closed -> "changed on disk, walking it again" 0.5 s later, new menu item and
control in the code model and in completion; TODO saved in the editor ->
Task List entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS test bed: DBServer and FieldSpec for the VO designers

VO\VOTestBed gets a DBServer (Customer.prg + Customer.Customer.xsdbs, class
Customer on Customer.dbf) and FieldSpecs (Fieldspecs.prg +
Fieldspecs.FieldSpecs.xsfs), created from the X# item templates VODBServer and
VOFieldSpec (ProjectPackage/Templates/ProjectItems/VO) with
$safeitemrootname$ replaced; Fieldspecs.prg is the template's empty stub,
the FieldSpec editor fills it. The X# SDK globs add the VO binaries as
VOBinary with DependentUpon.

Tested in VS: the FieldSpec editor regenerates Fieldspecs.prg, the DBServer
editor regenerates Customer.prg and creates Customer.FieldSpecs.xsfs (added to
the code model through AddFileNode and the glob); SourceFileWatcher walks
the .prg files 0.5 s after the save; the generated code compiles; the project
file stays unchanged. The committed files are the template state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [CodeDomProvider] Write static field references on parsed types with '.'

GenerateFieldReferenceExpression used the static selector only when the
target was exactly a CodeTypeReferenceExpression. The X# CodeDOM parser
creates the subclass XCodeTypeReferenceExpression, so code that was parsed
and generated again got a colon: "Add .designer file" wrote
"System.Windows.Forms.AutoScaleMode:Font", which the compiler rejects
(XS9114) and the shadow designer cannot convert. GeneratePropertyReference-
Expression already tested with "is"; now both do.

Checked outside VS with the dev build (DEVPATH, the GAC copy of 3.0.2
still writes the colon): an XCodeTypeReferenceExpression target gives
"AutoScaleMode.Font", SELF:button1 keeps the colon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: form icon for generated form files

The tree properties provider found the base class of a form with
"CLASS name INHERIT base" on one line. The X# CodeDOM generator writes the
declaration with a line continuation ("CLASS Form1 ;" and "INHERIT ..." on
the next line), so a form lost its icon as soon as the generator wrote its
main file: "Add .designer file", or the shadow designer adding an event
handler. The regex now allows the continuation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: update the form icon when a designer file is added

CPS calls the tree properties providers only for the nodes that changed in
a tree update. "Add .designer file" adds a .Designer.prg below an existing
.prg: that adds a child node but leaves the node of the .prg unchanged, so
its form icon only appeared after the project was loaded again. When the
list of properties providers changes, CPS calculates the properties of all
nodes again (PhysicalProjectTreeProvider.OnProjectTreePropertiesProviders-
Changed, providers compared by instance).

New XSharpProjectTreePropertiesProviderSource (IProjectTreePropertiesProvider-
DataSource, the pattern of the managed project system's TreeItemOrder-
PropertyProviderSource) supplies the provider, which is no longer a MEF
export itself. It follows the source items and publishes a new provider
only when a .Designer.prg was added or removed.

Its values carry their own version, not the versions of the source items
subscription: the tree input synchronizes its sources by their data source
versions, and with the source item versions the tree was never published
and VS hung while restoring the open documents (seen in the experimental
instance, stacks read with cdb). The first provider is published right
away.

Tested in VS: the icon changes right after "Add .designer file" and after
deleting the designer file; the solution loads normally.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Add .designer file for X# projects loaded by CPS

The command was hidden for CPS projects: it generated the designer file
from the MPFproj file node (XSharpFileNode) and cast the project node to
XSharpProjectNode.

- Visible for .prg files of X# projects only (before, the MPFproj check
  also kept it away from C# forms). SDK-style projects rarely have a
  SubType, so for CPS projects the base classes of the first class in the
  file are followed through the code model, the same rule as
  XSharpFileNode.DetermineSubType (TypeNameToSubtype is now internal).
  Also hidden when a .designer.prg exists next to the file without being
  nested below it; the command would have overwritten it.
- VSXSharpCodeDomProvider has a second constructor with the code model
  project and the file path; without a file node it writes into an open
  editor buffer by path. The CPS project system needs no AddFileNode: the
  SDK globs include the new file and XSharp.SDK.Props nests it.
- The form is parsed first; the files are only created when the form class
  with InitializeComponent was found. Right after the solution was opened
  the references are not loaded yet and the parser cannot recognize it
  (the command left an empty designer file behind and failed silently).
  Now a message says to try again later. Exceptions are shown instead of
  only going to the activity log.

Tested in VS with a single-file form in the WinForms test project: the
designer file is created and nested, the form keeps its icon, the designer
opens it (after correcting "AutoScaleMode:Font", written by the GAC copy
of the CodeDOM generator without 5ec34de0f2), and the project builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] Add .designer file: do not write the form file in lower case

The generated form source was lowered for the "#endregion without #region"
check and only restored when that check applied. For a form without a
#region the whole form file was written back in lower case. Only the check
is case insensitive now. The bug is also on dev.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS shadow designer: do not wait for the references on the blocked UI thread

CPS waits synchronously on the UI thread for the task of a command handler
(ProjectNode.ExecCommand), without pumping messages. When a form was opened
while the package references were still missing, EnsureReferencesAsync
waited for the project load inside that wait: the NuGet restore and the
design-time build after it could not finish, the wait gave up after 3 s
(the IntelliSense stage was already complete, the first design-time build
had run without the packages), the build prompt came, and after OK VS hung
for good (seen in the experimental instance, stacks read with cdb).

- Double click / Enter and View Designer report the command as handled
  right away when package references are missing, and open the designer in
  the background. When it cannot be opened, the form opens in the code
  editor, the default action CPS would have taken. With the references
  present nothing changes.
- After the load stage the references are awaited for up to 20 s instead
  of 3 s, with a status bar message.

Tested in VS with a WebView2 PackageReference restored from a local feed:
double click right after the solution opened -> no prompt, the designer
opened 1.4 s later, after the design-time build with the packages; with a
failing restore -> VS stays responsive, prompt after the wait, the build
runs, the designer opens.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS shadow designer: wait only briefly for the references after a build

After the build offered by EnsureReferencesAsync, the references were
awaited for the same 20 s as during the project load. A build restores, and
the design-time build with the references follows right after it (0.2 s in
VS), so 3 s are enough. Also for a failed build: it can have restored and
failed on compile errors, then the references still come; when the restore
failed, the Designer used to open only after the full 20 s.

Tested in VS with a restore that fails (local feed renamed): prompt, OK,
the build fails, the Designer opens 3.8 s later (before: 21 s).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: conditional compilation symbols keep DEBUG and TRACE

The "Conditional compilation symbols" field of the managed Build page edits
DefineConstants with a MultiStringSelector, whose value is a list of
name/value pairs. For C# the managed DefineConstantsValueProvider
(persistence ProjectFileWithInterception, AppliesTo CSharp | FSharp)
converts it. For X# nothing did: adding MYSYM wrote
<DefineConstants>MYSYM=False</DefineConstants> into the project file, the
implicit DEBUG and TRACE were lost and MYSYM was not defined either
(verified in VS).

That value provider cannot be used for X#: its interfaces are in
Microsoft.VisualStudio.ProjectSystem.Managed.dll, which has no usable
package and a version per VS release (the part would be rejected on older
VS). So:
- BuildPropertyPage.XSharp.xaml defines DefineConstants like the managed
  page, with the persistence "XSharpDefineConstants".
- XSharpDefineConstantsPropertiesProvider (public CPS API only) wraps the
  project file provider and converts DefineConstants: the list shows the
  symbols of the project file after "$(DefineConstants);" (a value without
  the prefix is shown as a whole), a change is written as
  "$(DefineConstants);SYMBOL;...", an empty list deletes the property.
  Exported named and unnamed: the property pages import the unnamed
  contract and select by the "Name" metadata.
- KeyValuePairListEncoding: the editors' list format, internal in the
  managed project system.

Tested in VS: MYSYM added for Debug -> "$(DefineConstants);MYSYM", the
program reports DEBUG, TRACE and MYSYM; the page shows MYSYM again after
reopening; removing it deletes the property.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VsIntegration] CPS project system: documentation

README.md in src/VisualStudio/ProjectSystemCPS: what the CPS project system
for SDK-style X# projects offers, the supported Visual Studio versions, the
installation (VSIX plus matching X# MSBuild support files and rules), how it
works (project selection, capabilities, MSBuild integration, feeding the
code model, errors and Task List, property pages, icons, VO designers,
shadow WinForms designer, commands, multi-targeting), the source layout,
building, testing and debugging, troubleshooting and the known limitations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com>
Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com>
Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com>
Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com>
* Added 2 workflows to be able to run the tests independent of the compiler build

* Updated names

* Renamed

* Update download-artifact action to version 8

* Upgrade upload-artifact action to v7

Updated artifact upload actions to version 7.

* Update download-artifact action version to v7

* Deleted yml

* [Runtime] Fix for #2092

* Apply remaining changes

Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com>

---------

Co-authored-by: Robert van der Hulst <robert@xsharp.eu>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: RobertvanderHulst <14240939+RobertvanderHulst@users.noreply.github.com>
…pound assignments (#2096)

Two X#-specific blocks in the binder enumerate diagnostics.DiagnosticBag
without a null check. When a public SemanticModel query binds, diagnostics
is BindingDiagnosticBag.Discarded, whose DiagnosticBag is null.

- Binder_Operators.cs, BindCompoundAssignment: the "clear 9020" block threw
  for every compound assignment (+=, -=, ...).
- Binder_Expressions.cs, CheckVOIndexedValue: foreach over
  DiagnosticBag?.AsEnumerable() enumerated null (hardening, not observed).

Both guards use diagnostics.AccumulatesDiagnostics. The guarded code only
filters diagnostics, so xsc output is unchanged. In CheckVOIndexedValue the
CheckValue binding result still runs; only the diagnostic filter is guarded.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Irwin1985 and others added 25 commits November 6, 2026 07:59
* [VS] Find references: find a name in comments, strings and inactive code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Find references: search options, certainty of each place, transitive scope

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: check the new name

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: refuse unsafe targets, find name conflicts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: plan the changes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: apply the changes with one undo

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: preview the changes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename (Ctrl+R, Ctrl+R) for X# symbols

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: report #Name of classes and functions, refuse overrides of interface implementations

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: open means shown in a window, save hidden files only on undo, safe rollback, one search at a time

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: a linked, not a global undo transaction, so that open files stay unsaved

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: refuse overrides of System.Object members in classes without INHERIT

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: search again on Checked/Unchecked, not only on Click

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: an open file renamed with its class keeps its code model

The project reads a renamed file from disk, but an open file keeps the
rename unsaved, so the code model still had the old class name under
the new path ("'Dog' already exists" when renaming back). The editor
also kept the XFile of the old path, so a second rename did not offer
to rename the file. XFile.Rename moves that object to the new path, and
the editor text is parsed afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Rename: option to rename late-bound calls and symbols

A new checkbox in the rename dialog (members only, unchecked at the
start of every rename) also changes the late-bound group that Find All
References lists: o:Name sends and #Name symbols; for a symbol only the
name behind the hash is replaced. Unresolved, ambiguous and inactive
places are still only reported. The dialog now says that the places
that are not changed are listed in the Find All References window
after Apply.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* [VS] Code model: change counter and Navigate To queries

XDatabase.ChangeCounter changes after every write of files, types or
members and when the database opens or closes, so that a cache can tell
when to read again. GetAllProjectTypes / GetAllProjectMembers read every
type and member of the projects in one query each.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Navigate To: name matching

Exact, prefix, beginnings of two or more name parts in order (WT,
WrTe for WriteText) and substring, ignoring case, ranked in that order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Navigate To: snapshot of types and members

All declarations of the solution in memory, read again when the code
model changed, at most every 2 seconds; concurrent searches share one
load. The global type itself, constructors and other kinds that Go To
All does not list are left out; a declaration in a file of several
projects, and an ACCESS/ASSIGN pair, are listed once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Navigate To (Ctrl+T) for X# types, members and functions

A Go To All provider: matches the search text against the snapshot of
the solution's declarations, reports the kind (so that the t/m filters
work), the declaring type, file and project, and opens the declaration
(also as a preview). Supports the "current document" scope.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Navigate To: own source for the Code Search of VS 2022 17.6+ and VS 2026

The Code Search (Ctrl+T) asks classic INavigateToItemProviders only for the
first query of a session: CodeSearchItemsSource.StopSearch reports progress
to the callback of the previous, already cancelled search, the
OperationCanceledException leaves PerformSearchAsync before StartSearch, and
the stale callback stays. X# therefore gets its own ISearchItemsSourceProvider,
built like Roslyn's, in a separate assembly XSharp.LanguageService2022.Search:
it is the only one that references Microsoft.VisualStudio.Search.dll (ships
with VS 17.6+, referenced from the VS installation, not distributed), so in
older versions only this MEF component fails to load.

The classic provider is limited to the classic Go To window
(OnlyNavigateToSupport) so that the Code Search does not list X# twice. The
runtime functions in BuiltInFunctions.prg are no longer listed; the types and
members filters are shared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Navigate To: review fixes

- The classic provider gets the OnlyNavigateToSupport metadata through
  ExportMetadata: the attribute type is missing in early VS 2022 versions.
- The snapshot load reads only name, kind, type, place and project (no
  source code or comments) under dbLock, and the entries share one copy of
  each file, project and type name; the load logs its time.
- The Code Search honours the "current document" and "current project"
  scope like Roslyn and matches on a background thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* [VS] Find References: overrides match by parameter types, not names

An override renames or drops parameters (FocusChange(oFocusChangeEvent AS ...)
vs FocusChange(oEvent AS ...), Close() vs Close(oEvent)). OverrideFamily
compared ParameterList, which contains names and default values, so those
were separate families. Now: same name and kind, same parameter types and
REF/OUT; untyped (CLIPPER) methods of the same name are one slot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Go To Implementation: type hierarchy search

TypeHierarchy walks down (derived classes over all levels, implementers of
an interface incl. derived interfaces, overrides) and up (base class and
interfaces, overridden member, implemented interface members). Lookups are
passed in: database candidates of a short name are only a prefilter, a
candidate counts when its resolved base or interface is the type itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Code model: queries for derived and implementing types

GetProjectTypesByBaseName: types whose BaseTypeName is the short name
(also qualified or generic). GetProjectTypesMentioning: classes, structures
and interfaces whose declaration line contains the name. Both are read-only
prefilters for Go To Implementation; no schema change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Go To Implementation: source lookups for the hierarchy

SourceHierarchy serves TypeHierarchy from the code model: candidates from
the new database queries (one per type, shown at the partial part with
INHERIT/IMPLEMENTS), base classes resolved as OverrideFamily does,
interfaces from the Interfaces list plus the declaration line, resolved
with the file's USINGs and the type's namespace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Go To Implementation (Ctrl+F12) and Go To Base (Alt+Home)

Go To Implementation lists derived classes (all levels), implementers of
an interface and overrides / implementing members; Go To Base the base
class and interfaces, or the overridden member and the implemented
interface members. The starting symbol may come from a DLL. One result
opens the declaration, several go to the Find All References window.

Ctrl+F12 is bound to Edit.GoToImplementation only in the C#/VB editors,
everywhere else to Edit.GoToDeclaration, so that is intercepted too. The
symbol under the cursor is resolved as Find References does
(TargetUnderCursor, extracted from FindReferencesCommand).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Go To Implementation: review fixes

- Slot rule: parameter types are compared by their system name without
  namespace (System.Windows.Forms.PaintEventArgs = PaintEventArgs,
  System.Int32 = INT), so typed overrides of DLL members match; a
  parameter written AS USUAL is typed, only one without AS is CLIPPER.
- Same-named classes in different projects (VO solutions without
  namespaces) are listed separately: types are keyed by project and name.
- Partial classes: the row and the jump go to the part with INHERIT /
  IMPLEMENTS, whose USINGs also resolve the base class and interfaces.
- Go To Base on a member lists every base declaration once.
- Result rows mark the name as a whole word (DeclarationHit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Go To Implementation: build the hierarchy in memory

acslib took 5-8 s for classes with 600-900 descendants: one query per
level and a full type (with members) for every candidate. Now all types
with a base class come in one query, the tree is built from those rows,
INHERIT/IMPLEMENTS names are resolved to full names only (FilterUsings,
cached per project, USINGs and name), and only types that declare a member
of the searched name are loaded for the override check. acslib: 0.2-0.9 s
with the same results (tabStdAbstract 612, FSBase 895, DefineFilter 60).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Robert van der Hulst <robert@xsharp.eu>
…efine: net5_0_or_greater. This sets the compiler option Net5orHigher to true.
…2156 (#2161)

The squash merge of #2156 mixed the SelectTarget method from #2154 (Rename)
with the old inline lookup, so FindReferencesCommand.cs did not compile.
SelectTarget now resolves the symbol through TargetUnderCursor.Resolve and
fills TargetSelection from it; messages are unchanged.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Tests for BAR, PAD, POPUP, MENU, MRKBAR, MRKPAD, PRMBAR and PRMPAD using
menus built with the DEFINE commands, checked against VFP 9. They found a
few problems that are fixed here too: the plain DEFINE and ACTIVATE POPUP
forms weren't expanded by the header, RELEASE MENUS/POPUPS with a list
didn't compile, PRMBAR/MRKBAR/BAR used the bar position instead of its
number, prompts kept the \< marker, names were case sensitive, RELEASE
MENUS left the menu registered and PAD()/MENU() were empty when the bar
was selected without opening the menu.
…roject tree (#2163)

- The rename dialog is defined in XAML (RenameDialog.xaml) instead of being built in code;
  both LanguageService projects include it. It now uses the VS theme like the other X# windows.
- XSharpProjectTreePropertiesProvider: while a file is renamed the tree can still ask for the
  old path; return early when the file does not exist instead of throwing (and catching)
  a FileNotFoundException in FindClassDeclaration.

Follow-up to #2154 (review comments).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* [VS] Fix the build: SelectTarget after the Go To Implementation merge

The squash merge of #2156 on top of #2154 mixed the old body of
FindReferencesCommand.SelectTarget with the Go To Implementation version
(await in a non-async method, duplicate locals, undefined doc/name), so
the language service did not compile. SelectTarget now uses
TargetUnderCursor.Resolve, as Find References did in #2156, and keeps the
TargetSelection result that Rename (#2154) needs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: thread-safe lookup state and walker suspend

XSharpLookup.nestedSearches is per thread now: lookups run in the
background (inlay hints, Find References) next to QuickInfo on the UI
thread and shared the recursion guard. ModelWalker.Suspend/Resume use
Interlocked, they are called from several threads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: candidates

HintCandidates finds calls with arguments (Name(...), Type{...}) and
implied declarations (VAR, LOCAL IMPLIED, FOREACH VAR, FOR VAR, USING VAR)
on lexer tokens. Declarations (FUNCTION Foo(...)) and OUT VAR are skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: rules

HintRules decides which hints show: parameter names only for arguments
that say nothing (literals, NIL, NULL_*, signed numbers, Type{...}), only
when exactly one overload fits the call, none beyond the last parameter
or after the first PARAMS argument; extension methods called on an
instance skip their first parameter. Type hints are hidden when the
initializer names the type. Type names are shown without namespaces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: type rewrite

The double-click on a type hint writes the type: VAR x := e and
LOCAL IMPLIED x := e become LOCAL x := e AS T (X# puts the type after the
initializer), FOREACH VAR x IN c becomes FOREACH x AS T IN c. No edit for
FOR, USING, STATIC and statements with several variables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: computer and queue

InlayHintComputer resolves the candidates of a document snapshot on a
private copy of its tokens (the classifier refills the live document),
inside one ModelWalker.Suspend/Resume, and logs the time per file. A type
hint is silent when the initializer ends in an ambiguous call or the type
is unknown. InlayHintQueue runs one computation at a time for the IDE;
a newer request for the same document replaces a queued one and cancels
a running one; RequestDebounced waits for a quiet second. The classifier
raises ParseCompleted after each parse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: tagger, options, triggers

InlayHintTagger (IViewTaggerProvider, IntraTextAdornmentTag) shows the
hints of the last computed snapshot, translated to the current one; a
hint whose text was edited disappears until the next result. Hover shows
the parameter (with its XML doc and the member prototype) or the type;
a double-click on a type hint writes the type (one undo step). Colours
in Fonts and Colors (X# Inlay Hint). Options: Show parameter name hints,
Show inferred type hints (both on). Open documents are recomputed after
a quiet second when the code model walker is done (new
ModelWalker.WalkCompleted) or another file of the project was saved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Overload filter: untyped parameters make an implicit CLIPPER method

VO METHOD Open(cName, lShared) accepts any number of arguments, but the
code model only marks CLIPPER when the keyword is written. Inlay hints
were missing for calls with fewer or more arguments (Find References
kept them only by the no-match fallback).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: draw an opaque stored background translucent

Fonts and Colors stores colours without alpha: the hint background came
back as opaque #808080, the same grey as the text, and the hints showed
as empty grey boxes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: no type hint when the lookup leaves the initializer text

The parser stores the initializer text as the type name of a VAR; when
the lookup cannot resolve it, that text stays. FOREACH VAR d IN
<DbFile>{o} showed ' AS <DbFile>{o}' and double-click wrote it out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Lookup: FOREACH VAR over a typed array literal and over a VAR local

FOREACH VAR d IN <DbFile>{o} now types d as DbFile. VAR list := s:Load()
kept List<T> instead of the declared List<STRING>, so FOREACH VAR item
IN list could not type item; implied assignments now keep the type
arguments of the declaration, as FOREACH variables already did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: review fixes

- Type hint stays silent when the overloads of the final call return
  different types: the lookup takes the first overload, not the one the
  arguments pick (Math.Max(1, 2) said BYTE).
- Type hint stays silent when a type argument does not resolve
  (List<TSource> from ToList(), List<T> from a generic class).
- The double-click edit writes the namespace unless a USING or the
  enclosing namespace brings it in, so the edit compiles.
- The lookup's array type cache is a ConcurrentDictionary: the lookup
  now also runs in the background.
- The hint computation no longer suspends the code model walker; a
  suspend made the walker drop and restart its current project after
  every parse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: hover tooltip as QuickInfo shows it

The tooltip of a hint was a plain WPF ToolTip with plain text: white
in every theme and without syntax colours. It now uses the editor's
IToolTipService with the same content elements as the X# QuickInfo
(icon + classified text), so it follows the theme and the
classification colours like the C# hints do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: show all hints while Alt+F1 is held down

As in C#: a third option "Show all hints while pressing Alt+F1" (on by
default) shows the switched off kinds while Alt+F1 is held down in an
X# editor. Releasing F1 or Alt, or moving the focus away, hides them
again at once. A key processor tracks the hold; the tagger computes the
missing kinds without the debounce and filters by the current setting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Code model: no file lookup per member when a source type is built

XProject.GetType rebuilds a source type from the database on every lookup. For each member,
XDbResult.UpdateLocation looked the file up through XSolution.FindFile, which creates a new XFile
and reads it from the database; GetType then replaced that file with its own cached one. For a
VO class with many members this was most of the time of a lookup.

UpdateLocation now takes the file from the caller: GetType passes the file it resolves per file id,
the extension method path looks its single file up once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: compute the visible lines first

A large file was resolved as a whole before any hint appeared. The tagger now computes the visible
lines and one screen above and below, and when the view scrolls to lines that are not covered it
computes those after a short pause and merges them with the hints of the same snapshot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: find the call arguments by position

HintCandidates.Calls looked each call name up in the token list to find its arguments. In the
editor the token index does not match the position in that list, so every call searched the whole
list: a 775 KB file spent about a second on this before any call was resolved.

OverloadFilter.Arguments now also takes the position, and the scan passes it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: the colours of the C# inline hints

The hints were grey on a translucent grey background in every theme. They now take the colours of
the C# "inline hints" item in Fonts and Colors: the Visual Studio themes colour it, so the hints
follow light and dark like the C# hints, and a colour the user picks for C# applies to both.

Without that item (no Roslyn) the X# item is used, now with the C# defaults. It is no longer shown
in Fonts and Colors, where it would change nothing while the C# item exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: generic type arguments in VAR declarations

VAR d := Dictionary<STRING, INT>{} was split at the comma between the type
arguments into two declarators. The double-click edit then wrote the type
after STRING, in the middle of the type arguments, and the code no longer
compiled. The commas of Name<A, B>{...}, Name<A, B>(...) and <T>{...} now stay
in the initializer; a comparison such as VAR a := x < y, b := 2 still splits.

A generic constructor (VAR l := List<STRING>{}) now counts as a visible type,
like Customer{}, so it no longer gets a redundant type hint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Lookup: FOREACH VAR over <T>{} only takes T when it resolves

The element type name of a typed array literal was stored as the type of the
loop variable before the lookup searched it, so an unknown T showed as an
inlay hint (and in QuickInfo). The name is now only taken when the type
resolves; otherwise the variable stays unresolved and gets no hint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: a request cancels a pending debounce of the same document

A pending debounced computation was asked for an older state; after a direct
request for the same document it ran once more for nothing. Request now
cancels it. The CancellationTokenSources of the debounce are disposed when
their delay ends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Find References, inlay hints: generic type arguments in call arguments

OverloadFilter.Arguments split Foo(Dictionary<STRING, INT>{}, 1) at the comma
between the type arguments and counted three arguments. Find References then
dropped the matching overload, and the inlay hints found no parameter for the
call or shifted the names of a CLIPPER method. The commas of Name<A, B>{...},
Name<A, B>(...) and <T>{...} now stay in their argument; a comparison such as
Foo(a < b, c > d, e) still counts three.

The type argument check moved from HintCandidates to OverloadFilter, where
both use it; it now skips tokens off the default channel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Find References, inlay hints: calls with type arguments after the name

List<STRING>{10} and o:Foo<INT>(1, 2) had no argument list: the argument
reader and the inlay hint candidates expected ( or { right after the name,
and a generic creation was not narrowed to the constructors. So these calls
got no parameter hints, and Find References did not filter their overloads.

OverloadFilter.ListAfterName finds the ( or { after the name, also after
type arguments; Arguments, SymbolResolver.ForCreation and
HintCandidates.Calls use it. Foo < 3 and Foo < b, c > d stay no call.
Go To Definition on Foo in Foo<T>{1} now reaches the constructor, as it
already did for Foo{1}.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Find References: generic source classes and their constructors

CLASS Box<T> is stored as Box`1. Find References searched the files for
"Box`1", which no source contains, and did not recognise the declaration,
so a generic class had no references at all. The search name and the
declaration check now drop the arity.

The constructor candidates only took Box{...}; Box<INT>{...} is now one too
(OverloadFilter.ListAfterName), so Find References on the CONSTRUCTOR of a
generic class finds its creations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Go To Definition: a keyword is no target

F12 on a keyword (the caret on CLASS) showed "Cannot navigate to the symbol
under the cursor"; when nothing is found F12 stays silent, a keyword is now
treated the same. Seen after F12 on Foo{1} through DTE.ExecuteCommand: the
shell sent the command twice, the first call opened the class with the caret
at the start of its line, the second one hit the CLASS keyword.

The deduplication moved into XSharpGotoDefinition.Targets, which also drops
the keywords.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: off by default, all hints while Alt+F1 is held down

As C# (Roslyn: EnabledForParameters and EnabledForTypes false,
DisplayAllHintsWhilePressingAltF1 true): parameter and type hints are off
until switched on in Tools - Options; holding Alt+F1 shows both. The
defaults are constants in InlayHintSettings, used by the options page and
as the start values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: an argument of only names and dots is no constructor

5df8da4 dropped the end check in HintRules.IsConstructor: for an argument
or initializer made only of IDs and dots (Foo(Color.Red), VAR e :=
Encoding.UTF8) it read past the end of the token list. The exception left
the computation, so the whole range showed no hints. Found in review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: a recompute drops the hints it no longer finds

Merging with the older hints of the same snapshot kept every old hint the
fresh result had no hint for at the same place, also inside the range just
recomputed. After the walker finished or another file was saved, a call
that had become ambiguous kept its stale parameter name until the next
edit. Inside the freshly covered range only the fresh hints count now.
Found in review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Inlay hints: generic VAR calls get the overload check; no fixed time limit in the linear-time test

FinalCallName took the token before the argument list as the call name, so for
VAR x := o:Foo<INT>(1) it found '>' and skipped the check that the call is
unambiguous; the type hint could come from the wrong overload. It now steps back
over the type arguments to the name (checked with OverloadFilter.ListAfterName).

ALargeFileIsScannedInLinearTime had a 1000 ms wall-clock limit that can fail on
the E-cores. It now compares 5000 with 20000 calls (fastest of three runs each):
linear is about 4x, the test allows less than 8x; the quadratic scan it guards
against measured 23x.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Correction to the message of f80b56f (no code change)

f80b56f says: "Go To Definition on Foo in Foo<T>{1} now reaches the
constructor, as it already did for Foo{1}." That is wrong. Correct is:

Find References on Foo in Foo<T>{1} now resolves to the constructors, as it
already did for Foo{1}; Go To Definition still goes to the class, for Foo{1}
as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…onvert to property (#2166)

* [VS] Quick actions: USING candidates and insertion

Pure helpers for the coming "Add USING" light bulb: which namespaces
hold a type of the name under the caret (without the ones the file
already uses or sits in), and where the USING line goes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Quick actions: method skeleton

The text of a method generated from a call: parameter names from the
arguments (p1, p2 otherwise, duplicates numbered), known argument types
or the dialect's untyped type (USUAL, OBJECT in Core), AS VOID in Core,
a CLASS clause for VO-style classes without END CLASS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Quick actions: generate-method rule

When "Generate method" is offered and into which class: SELF calls and
bare calls go into the enclosing class, oVar:Foo() into the variable's
source class. Not for SUPER, chains, DLL/unknown receivers, names that
exist in the class or a base class, classes with NoMethod, and bare
calls to a known function or define.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Quick actions: override candidates and skeleton

The members a class can override (every method of a VO-dialect class,
otherwise virtual/abstract/override ones; nearest base first, members
already declared with the same kind, name and parameter types skipped)
and the text of an override: same signature, REF/OUT kept, SUPER call,
CLIPPER methods via _Args(), ACCESS/ASSIGN and properties.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Quick actions: add USING, generate method, generate overrides

One light-bulb source resolves the caret once per text version and
position in the background and offers:
- USING Namespace for a name that does not resolve, when a type of that
  name exists in another namespace (project, referenced projects and
  assemblies);
- Generate method 'Foo' in class 'Bar' for SELF:Foo(), bare calls and
  calls on a variable typed as a source class; the method goes before
  END CLASS or, for VO-style classes, after the last member with a CLASS
  clause, also in another file (which is opened);
- Generate overrides... with a dialog of the overridable base members.
OverrideSkeleton gets the CLASS clause for VO-style classes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Quick actions: review fixes

- Generated VO methods end with RETURN NIL (no /vo9 needed); the caret
  goes on the empty body line.
- Overrides of CLIPPER methods keep CLIPPER and the return type, also
  without parameters; abstract members throw NotImplementedException
  instead of calling SUPER; DLL properties get only their accessors;
  Finalize is not offered.
- Already overridden members are recognised against DLL bases: parameter
  types compared by simple name, ACCESS/ASSIGN matched with properties.
- Generate method is not offered for names the lookup resolves
  (extension methods) or for compiler pseudo functions (PCount, _Args...).
- END CLASS is recognised by its keywords, so a VO-style class whose
  last line is END METHOD no longer gets members inserted inside it.
- No overrides bulb when System.Object members are the only candidates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Quick actions: fixes from the check in Visual Studio

- VS passes the caret line as range and calls the source off the UI
  thread: the caret is now taken from Caret.PositionChanged.
- Base classes are resolved like Find References does (BaseType is only
  set by ForceComplete), with the USINGs of the class part in the file.
- In VO an unknown name comes back as an undeclared variable: it counts
  as unresolved for "Add USING" and "Generate method".
- "Add USING" only for names without a receiver (SELF:Missing offered
  USING System.Reflection) and also for types the lenient code model
  finds without their USING.
- FindFunction & co. throw when nothing is found: treated as not found.
- Argument types in X# names (INT instead of System.Int32); generated
  members take the indentation of the methods, not of the fields.
- A log line per light-bulb query when logging is enabled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Quick actions: Generate overrides like C#

"Generate overrides..." is offered on the class header or on a blank line
between members (followed by a member, a type, END CLASS or the end of
the file), no longer everywhere in the class, and as a refactoring
(screwdriver) instead of a fix. The enclosing class is taken from the
member at the caret only when that member really holds the caret: on a
class header the lookup returned the member before it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Convert to property: setter body rewrite

The ASSIGN parameter becomes VALUE on identifier tokens only (strings,
comments and longer names stay), and RETURN x becomes RETURN; a longer
expression (RETURN SELF:_c := c) is kept as a statement of its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Convert to property: property text

The PROPERTY for an ACCESS/ASSIGN pair: one line (GET expr SET expr) when
both bodies are a single expression on one line, else GET/SET blocks
with the bodies re-indented; ACCESS only or ASSIGN only; index
parameters; the wider visibility on the property, the narrower on its
accessor; a final bare RETURN in the setter is dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Convert to property: pairing rule

Pairs ACCESS and ASSIGN of a class by name and keeps only the pairs that
convert without changing behaviour: not in classes without END CLASS,
not for names a base class has, not when the other part is in another
file, when types, index parameters or non-visibility modifiers differ,
or when a member carries an attribute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Convert ACCESS/ASSIGN to property

A refactoring on the header of an ACCESS or ASSIGN: "Convert to property"
for the pair, "Convert all ACCESS/ASSIGN in class 'X' to properties" for
every convertible pair of the class, in one undo step. The property
takes the place of the ACCESS (else the ASSIGN); the comments above the
removed member move with it; members in between stay. Headers with other
modifiers than the visibility are left alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Convert to property: review fixes

- Member names after : . -> :: are not renamed (SELF:oOwner := oOwner
  became SELF:VALUE := VALUE).
- Preprocessor lines (#region, #endif ...) stay outside the moved and
  removed lines; a member with one inside is not converted. Only line
  comments move with a member, block comments are never cut.
- A final RETURN after ";" no longer takes the statement before it.
- RETURN expressions: without calls or assignments they are dropped, an
  assignment or call becomes a statement, anything mixed or a RETURN
  after ";" on its line is not converted.
- The ASSIGN's index names are renamed to the ACCESS's.
- Comments in a body force the GET/SET block form.
- Not offered for headers with other modifiers, a CLASS clause or a ";"
  continuation, for INTERNAL vs PROTECTED, or for members outside the
  class block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Generate method: return type from the call site, like C#

The generated method always has a return type now; it used to have none in
the VO dialect (RETURN NIL) and AS VOID without RETURN elsewhere.

- a call that is a statement of its own: AS VOID, body RETURN
- IF/ELSEIF/WHILE/CASE/UNTIL condition, operand of .AND./.OR./.NOT.: AS LOGIC
- LOCAL x := Foo() AS T: AS T
- x := Foo() / SELF:x := Foo(): the declared type of x
- RETURN Foo(): the return type of the enclosing member
- anything else: USUAL, or OBJECT in Core

A method with a result throws System.NotImplementedException{} until it is
written, as C# does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* [VS] Quick actions: the call around the caret counts as well

The light bulb only looked at the name under the caret, so "Generate method"
was offered on Foo in Foo(1, 2) but not with the caret inside the argument
list or after the closing parenthesis. When the caret is on no name, the
innermost call whose argument list holds the caret, or the call that ends the
statement before the caret, is used now. A literal array or a creation {...}
around the caret stops the search.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
DELETE FROM <table> without a WHERE clause deleted only the current
record. In VFP it deletes every record of the table, so the DELETE - SQL
rules now use the ALL scope and the temporary rule that worked around
this is gone. Three tests added in TallyTests.
Copilot AI balanced review requested due to automatic review settings November 10, 2026 16:06
@RobertvanderHulst RobertvanderHulst changed the title Dev Merge Dev to Main Nov 10, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@RobertvanderHulst
RobertvanderHulst merged commit 30be098 into main Nov 10, 2026
0 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants