diff --git a/CHANGES b/CHANGES
index 76e627da..cf924659 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1458,3 +1458,13 @@ Version history
and provides some assistance in installing them
* dbuild: add file imported from C to the dependencies for rebuilding
* dbuild: add option to set C include search path and C #defines
+
+2025-09-26 version 1.5.0-beta1
+ * installer: added support for VS 2026
+ * dmdserver:
+ - now built with upcoming dmd 2.112 with improved GC performance
+ - don't stop analyzing when a static assert is hit
+ - add option to display server communication in the output pane
+ - some optimizations to to reduce communication overhead
+ * fixed WindowsApp template to build with recent DMD
+
diff --git a/Makefile b/Makefile
index 1d8da39d..1ce23891 100644
--- a/Makefile
+++ b/Makefile
@@ -189,6 +189,11 @@ dbuild17_14:
dbuild17_all: dbuild17_0 dbuild17_1 dbuild17_2 dbuild17_3 dbuild17_4 dbuild17_5 dbuild17_6 dbuild17_7 \
dbuild17_8 dbuild17_9 dbuild17_10 dbuild17_11 dbuild17_12 dbuild17_13 dbuild17_14
+dbuild18_0:
+ cd msbuild\dbuild && $(MSBUILD) dbuild.csproj /p:Configuration=Release-v18_0;Platform=AnyCPU /t:Rebuild
+
+dbuild18_all: dbuild18_0
+
mago:
cd ..\..\mago && devenv /Build "Release|Win32" /Project "MagoNatDE" magodbg_2010.sln
cd ..\..\mago && devenv /Build "Release|x64" /Project "MagoRemote" magodbg_2010.sln
diff --git a/VERSION b/VERSION
index 1a305319..f7314a5a 100644
--- a/VERSION
+++ b/VERSION
@@ -1,5 +1,5 @@
#define VERSION_MAJOR 1
-#define VERSION_MINOR 4
-#define VERSION_REVISION 2
+#define VERSION_MINOR 5
+#define VERSION_REVISION 0
#define VERSION_BETA -beta
#define VERSION_BUILD 1
diff --git a/build/build.visualdproj b/build/build.visualdproj
index 4efdf9e9..e2d1dc04 100644
--- a/build/build.visualdproj
+++ b/build/build.visualdproj
@@ -2043,122 +2043,18 @@ if exist "$(VCINSTALLDIR)\Auxiliary\Build\vcvars32.bat" ( pushd . &
if errorlevel 1 goto reportError
$(DMDInstallDir)\windows\bin\dmd -g -map "$(IntDir)\$(InputName).map" "-of$(OutDir)\$(InputName).dll" "-od$(IntDir)" -defaultlib=user32.lib -m32mscoff -L/SUBSYSTEM:CONSOLE -L/ENTRY:DllMain@12 $(InputPath) kernel32.lib user32.lib" outfile="$(OutDir)\$(InputName).dll" path="..\tools\filemonitor.d" tool="Custom" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+$(LDCInstallDir)\bin\ldmd2 -g -m32 "-of$(OutDir)\$(InputName).exe" $(InputPath) ..\tools\nostacktrace.d ..\stdext\string.d user32.lib oleaut32.lib ole32.lib -L/SUBSYSTEM:CONSOLE,5.01" dependencies="..\tools\nostacktrace.d" outfile="$(OutDir)\$(InputName).exe" path="..\tools\pipedmd.d" tool="Custom" />
+ bin\Release-v18_0\
+ TRACE;TOOLS_V17
+ true
+ true
+ pdbonly
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+ 18.0
+
+
+ bin\Debug-v18_0\
+ TRACE;DEBUG;TOOLS_V17
+ true
+ false
+ pdbonly
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+ 18.0
+
true
full
@@ -493,7 +515,7 @@
or '$(TargetVer)' == '17.4' or '$(TargetVer)' == '17.5' or '$(TargetVer)' == '17.6'
or '$(TargetVer)' == '17.7' or '$(TargetVer)' == '17.8' or '$(TargetVer)' == '17.9'
or '$(TargetVer)' == '17.10' or '$(TargetVer)' == '17.11' or '$(TargetVer)' == '17.12'
- or '$(TargetVer)' == '17.13' or '$(TargetVer)' == '17.14'">v4.7.2
+ or '$(TargetVer)' == '17.13' or '$(TargetVer)' == '17.14' or '$(TargetVer)' == '18.0'">v4.7.2
false
false
false
@@ -832,6 +854,35 @@
assemblies\v17_14\Microsoft.Build.CPPTasks.Common.dll
+
+
+
+ assemblies\v18\Microsoft.Build.dll
+
+
+ assemblies\v18\Microsoft.Build.Framework.dll
+
+
+ assemblies\v18\Microsoft.Build.Tasks.Core.dll
+
+
+ assemblies\v18\Microsoft.Build.Utilities.Core.dll
+
+
+ assemblies\v18\envdte.dll
+
+
+ assemblies\v18\Microsoft.VisualStudio.VCProject.dll
+
+
+ assemblies\v18\Microsoft.VisualStudio.VCProjectEngine.dll
+
+
+
+
+ assemblies\v18\Microsoft.Build.CPPTasks.Common.dll
+
+
Designer
diff --git a/msbuild/dcompile.targets b/msbuild/dcompile.targets
index b354fedd..eb1b868b 100644
--- a/msbuild/dcompile.targets
+++ b/msbuild/dcompile.targets
@@ -347,10 +347,7 @@
phobos32mscoff.lib
phobos64.lib
phobos2-ldc.lib;druntime-ldc.lib
- $(DRuntimeLibs);legacy_stdio_definitions.lib
- $(DRuntimeLibs);legacy_stdio_definitions.lib
- $(DRuntimeLibs);legacy_stdio_definitions.lib
- $(DRuntimeLibs);legacy_stdio_definitions.lib
+ $(DRuntimeLibs);legacy_stdio_definitions.lib
<_CRuntimeLib>@(DCompile->Metadata('CRuntimeLibrary')->Distinct()->ClearMetadata())
diff --git a/msbuild/dcompile_defaults.props b/msbuild/dcompile_defaults.props
index a63688bb..4f2a5e24 100644
--- a/msbuild/dcompile_defaults.props
+++ b/msbuild/dcompile_defaults.props
@@ -47,8 +47,8 @@
$(MSBuildVersion_Major).0
16.0
16.1
- 17.$(MSBuildVersion_Minor)
- 17.14
+ 17.$(MSBuildVersion_Minor)
+ 18.0
diff --git a/nsis/Extensions_vs15/extension.vsixmanifest b/nsis/Extensions_vs15/extension.vsixmanifest
index 7851d21b..512ccd41 100644
--- a/nsis/Extensions_vs15/extension.vsixmanifest
+++ b/nsis/Extensions_vs15/extension.vsixmanifest
@@ -8,13 +8,13 @@
Extension to provide support for the D programming language
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/nsis/basedir.ini b/nsis/basedir.ini
new file mode 100644
index 00000000..f191b0cf
--- /dev/null
+++ b/nsis/basedir.ini
@@ -0,0 +1,77 @@
+[Settings]
+NumFields=9
+
+[Field 1]
+Type=DirRequest
+State=DirRequest
+Left=10
+Right=240
+Top=68
+Bottom=80
+
+[Field 2]
+Type=Label
+Text=Both the reference D-compiler
+Left=10
+Right=108
+Top=6
+Bottom=14
+
+[Field 3]
+Type=Link
+Text=DMD
+State=https://dlang.org/download.html
+Left=108
+Right=125
+Top=6
+Bottom=14
+
+[Field 4]
+Type=Label
+Text=and the LLVM-based
+Left=125
+Right=190
+Top=6
+Bottom=14
+
+[Field 5]
+Type=Link
+Text=LDC
+State=https://wiki.dlang.org/LDC
+Left=193
+Right=208
+Top=6
+Bottom=14
+
+[Field 6]
+Type=Label
+Text=compiler can be installed and kept uptodate.
+Left=10
+Right=240
+Top=16
+Bottom=24
+
+[Field 7]
+Type=Label
+Text=Please specify the folder for these compiler installations.
+Left=10
+Right=240
+Top=40
+Bottom=50
+
+[Field 8]
+Type=Label
+Text=This setting can be changed from within Visual Studio later on the Tools->Options->Projects->Visual D Settings->Updates page.
+Left=10
+Right=234
+Top=84
+Bottom=104
+
+[Field 9]
+Type=Label
+Text=Compiler base folder
+Left=10
+Right=191
+Top=56
+Bottom=64
+
diff --git a/nsis/vcinstall.ini b/nsis/vcinstall.ini
new file mode 100644
index 00000000..58d081bd
--- /dev/null
+++ b/nsis/vcinstall.ini
@@ -0,0 +1,37 @@
+[Settings]
+NumFields=4
+
+[Field 1]
+Type=Groupbox
+Text=Select Action
+Flags=NOTABSTOP
+Left=0
+Right=300
+Top=36
+Bottom=136
+
+[Field 2]
+Type=RadioButton
+Text=Start the the Visual Studio Installer. Please modify the installation to include the "Desktop developemnt with C++" workload including the Windows SDK.
+State=1
+Left=20
+Right=300
+Top=48
+Bottom=100
+
+[Field 3]
+Type=RadioButton
+Text=Do nothing (you can install the VC environment later)
+State=0
+Left=20
+Right=300
+Top=100
+Bottom=128
+
+[Field 4]
+Type=Label
+Text=Visual D needs the C++ environment of Visual Studio for msbuild integration, but no VC installation was found on your system.
+Left=0
+Right=300
+Top=0
+Bottom=36
diff --git a/nsis/visuald.nsi b/nsis/visuald.nsi
index 95f10703..05271c80 100644
--- a/nsis/visuald.nsi
+++ b/nsis/visuald.nsi
@@ -34,7 +34,7 @@
; define LDC to include ldc installation
; !define LDC
-!define LDC_VERSION "1.40.1"
+!define LDC_VERSION "1.41.0"
!define LDC_SRC c:\d\ldc2-${LDC_VERSION}-windows-multilib
; define VS2019 to include VS2019 support
@@ -43,6 +43,9 @@
; define VS2022 to include VS2022 support
; !define VS2022
+; define VS2026 to include VS2026 support
+; !define VS2026
+
!ifdef DMD
!define DMD_PAGE_INI "basedir.ini"
!else
@@ -55,12 +58,15 @@
!include "MUI2.nsh"
!include "Memento.nsh"
!include "Sections.nsh"
+ !include "StrFunc.nsh"
!include "TextFunc.nsh"
!include "InstallOptions.nsh"
!include "uninstall_helper.nsh"
!include "replaceinfile.nsh"
+ ${StrTrimNewLines}
+
;--------------------------------
;General
!searchparse /file ../version "#define VERSION_MAJOR " VERSION_MAJOR
@@ -145,6 +151,7 @@
!define VS2017_REGISTRY_KEY SOFTWARE\Microsoft\VisualStudio\15.0
!define VS2019_REGISTRY_KEY SOFTWARE\Microsoft\VisualStudio\16.0
!define VS2022_REGISTRY_KEY SOFTWARE\Microsoft\VisualStudio\17.0
+ !define VS2026_REGISTRY_KEY SOFTWARE\Microsoft\VisualStudio\18.0
!define VS2017_INSTALL_KEY SOFTWARE\Microsoft\VisualStudio\SxS\VS7
!ifdef EXPRESS
!define VCEXP2008_REGISTRY_KEY SOFTWARE\Microsoft\VCExpress\9.0
@@ -374,6 +381,9 @@ Section "Visual Studio package" SecPackage
${File} ..\msbuild\dbuild\obj\release-v17_12\ dbuild.17.12.dll
${File} ..\msbuild\dbuild\obj\release-v17_13\ dbuild.17.13.dll
${File} ..\msbuild\dbuild\obj\release-v17_14\ dbuild.17.14.dll
+!endif
+!ifdef VS2026
+ ${File} ..\msbuild\dbuild\obj\release-v18_0\ dbuild.18.0.dll
!endif
WriteRegStr HKLM "Software\${APPNAME}" "msbuild" $INSTDIR\msbuild
!endif
@@ -745,6 +755,17 @@ ${MementoSectionEnd}
!endif
+!ifdef VS2026
+;--------------------------------
+${MementoSection} "Install in VS 2026" SecVS2026
+
+ Push 1
+ Call InstallForVS2026
+
+${MementoSectionEnd}
+
+!endif
+
!ifdef EXPRESS
;--------------------------------
${MementoUnselectedSection} "Install in VC-Express 2008" SecVCExpress2008
@@ -805,6 +826,26 @@ SectionGroup Components
!ifdef MSBUILD
${MementoSection} "MSBuild integration" SecMSBuild
+!ifdef VS2026
+ SectionGetFlags ${SecVS2026} $2
+ IntOp $2 $2 & ${SF_SELECTED}
+ IntCmp $2 ${SF_SELECTED} 0 NoVS2026
+
+ Push 1
+ Call DetectVS2026_InstallationFolder
+ StrCmp $1 "" NoVS2026
+ ${RegisterPlatform} "$1\MsBuild\Microsoft\VC\v180" "x64"
+ ${RegisterPlatform} "$1\MsBuild\Microsoft\VC\v180" "Win32"
+ ${RegisterPlatform} "$1\MsBuild\Microsoft\VC\v180" "ARM64"
+ ${RegisterIcons} "18.0"
+
+ !define V180_GENERAL_XML "$1\MsBuild\Microsoft\VC\v180\1033\general.xml"
+
+ ExecWait 'rundll32 "$INSTDIR\${DLLNAME}" GenerateGeneralXML ${V180_GENERAL_XML};$INSTDIR\msbuild\general_d.snippet;$INSTDIR\msbuild\general_d.18.0.xml'
+ ${AddItem} "$INSTDIR\msbuild\general_d.18.0.xml"
+ NoVS2026:
+!endif
+
!ifdef VS2022
SectionGetFlags ${SecVS2022} $2
IntOp $2 $2 & ${SF_SELECTED}
@@ -1156,6 +1197,7 @@ SectionEnd
LangString DESC_SecVS2017 ${LANG_ENGLISH} "Register for usage in Visual Studio 2017."
LangString DESC_SecVS2019 ${LANG_ENGLISH} "Register for usage in Visual Studio 2019."
LangString DESC_SecVS2022 ${LANG_ENGLISH} "Register for usage in Visual Studio 2022."
+ LangString DESC_SecVS2026 ${LANG_ENGLISH} "Register for usage in Visual Studio 2026."
LangString DESC_SecVS2017BT ${LANG_ENGLISH} "Register for usage in Visual Studio 2017 Build Tools."
LangString DESC_SecVS2019BT ${LANG_ENGLISH} "Register for usage in Visual Studio 2019 Build Tools."
LangString DESC_SecVS2022BT ${LANG_ENGLISH} "Register for usage in Visual Studio 2022 Build Tools."
@@ -1199,6 +1241,7 @@ SectionEnd
!insertmacro MUI_DESCRIPTION_TEXT ${SecVS2022_2} $(DESC_SecVS2022)
!insertmacro MUI_DESCRIPTION_TEXT ${SecVS2022_3} $(DESC_SecVS2022)
!insertmacro MUI_DESCRIPTION_TEXT ${SecVS2022_4} $(DESC_SecVS2022)
+ !insertmacro MUI_DESCRIPTION_TEXT ${SecVS2026} $(DESC_SecVS2026)
!insertmacro MUI_DESCRIPTION_TEXT ${SecVS2017BT} $(DESC_SecVS2017BT)
!insertmacro MUI_DESCRIPTION_TEXT ${SecVS2019BT} $(DESC_SecVS2019BT)
!insertmacro MUI_DESCRIPTION_TEXT ${SecVS2022BT} $(DESC_SecVS2022BT)
@@ -1238,6 +1281,19 @@ Section "Uninstall"
ExecWait 'rundll32 "$INSTDIR\${DLLNAME}" RunDLLUnregister ${VCEXP2010_REGISTRY_KEY}'
!endif
+!ifdef VS2026
+ ReadRegStr $1 HKLM "Software\${APPNAME}" "VS2026InstallDir"
+ StrCmp $1 "" NoVS2026pkgdef
+ StrCpy $1 "$1Common7\IDE"
+ IfFileExists '$1${EXTENSION_DIR_APP}' +1 NoVS2026ExtensionDir
+ Push $1
+ Call un.VSConfigurationChanged
+ NoVS2026ExtensionDir:
+ RMDir /r '$1${EXTENSION_DIR_APP}'
+ RMDir '$1${EXTENSION_DIR_ROOT}'
+ NoVS2026pkgdef:
+!endif
+
!ifdef VS2022
ReadRegStr $1 HKLM "Software\${APPNAME}" "VS2022InstallDir"
StrCmp $1 "" NoVS2022pkgdef
@@ -1572,6 +1628,19 @@ Function .onInit
!endif
+!ifdef VS2026
+ ; detect VS2026
+ ClearErrors
+ Push 1
+ Call DetectVS2026_InstallationFolder
+ StrCmp $1 "" 0 Installed_VS2026
+ SectionSetFlags ${SecVS2026} ${SF_RO}
+ goto Done_VS2026
+ Installed_VS2026:
+ SectionSetText ${SecVS2026} "Install in $2"
+ Done_VS2026:
+!endif
+
!ifdef EXPRESS
; detect VCExpress 2008
ClearErrors
@@ -2248,6 +2317,81 @@ FunctionEnd
!endif ; VS2022
+!ifdef VS2026
+; TODO: expects index of installation to be pushed as an argument, return folder in $1, display name in $2
+Function DetectVS2026_InstallationFolder
+
+ StrCpy $3 "$PROGRAMFILES\Microsoft Visual Studio\Installer\vswhere.exe"
+ IfFileExists "$3" 0 no_vswhere
+ nsExec::ExecToStack '"$3" -products * -prerelease -version [18.0,19.0) -property displayName'
+ Pop $0 ; result code
+ Pop $2 ; stdout: name
+ StrCmp $0 0 0 no_vswhere
+ StrCmp $2 "" no_vswhere
+
+ nsExec::ExecToStack '"$3" -products * -prerelease -version [18.0,19.0) -property installationPath'
+ Pop $0 ; result code
+ Pop $1 ; stdout: path
+ StrCmp $0 0 0 no_vswhere
+ StrCmp $1 "" no_vswhere
+ ; return path in $1 with trailing separator
+ ${StrTrimNewLines} $0 "$0"
+ ${StrTrimNewLines} $1 "$1"
+ StrCpy $1 "$1\"
+ Goto done
+ no_vswhere:
+ StrCpy $1 ""
+ StrCpy $2 ""
+ done:
+
+FunctionEnd
+
+Function InstallForVS2026
+
+ Exch $1 ; argument Index
+
+ Push $1
+ Call DetectVS2026_InstallationFolder
+ WriteRegStr HKLM "Software\${APPNAME}" "VS2026InstallDir" $1
+
+ StrCpy $1 "$1Common7\IDE\"
+ RMDir /r '$1${EXTENSION_DIR_APP}'
+ ExecWait 'rundll32 "$INSTDIR\${DLLNAME}" WritePackageDef ${VS2026_REGISTRY_KEY} $1${EXTENSION_DIR}\visuald.pkgdef'
+ ${AddItem} "$1${EXTENSION_DIR}\visuald.pkgdef"
+
+ ${SetOutPath} "$1${EXTENSION_DIR}"
+ ${File} ..\nsis\Extensions_vs15\ extension.vsixmanifest
+ ${File} ..\nsis\Extensions\ vdlogo.ico
+ ${AddItem} "$1${EXTENSION_DIR}"
+
+ GetFullPathName $0 $INSTDIR
+ !insertmacro ReplaceInFile "$1${EXTENSION_DIR}\extension.vsixmanifest" "VDINSTALLPATH" "$0" NoBackup
+ !insertmacro ReplaceInFile "$1${EXTENSION_DIR}\extension.vsixmanifest" "VSVERSION" "18" NoBackup
+ !insertmacro ReplaceInFile "$1${EXTENSION_DIR}\extension.vsixmanifest" "VDVERSION" "${VERSION_MAJOR}.${VERSION_MINOR}" NoBackup
+
+ !ifdef MAGO
+ ; remove old DLL, now in x64\
+ Delete "$1..\Packages\Debugger\MagoNatCC.dll"
+ ${SetOutPath} "$1..\Packages\Debugger\x64"
+ ${File} ${MAGO_SOURCE}\bin\x64\Release\ MagoNatCC.dll
+ ${SetOutPath} "$1..\Packages\Debugger\arm64"
+ ${File} ${MAGO_SOURCE}\bin\ARM64\Release\ MagoNatCC.dll
+ ${SetOutPath} "$1..\Packages\Debugger"
+ ${File} ${MAGO_SOURCE}\bin\x64\Release\ MagoNatCC.vsdconfig
+ !endif
+
+ ${SetOutPath} "$1\PublicAssemblies"
+ ${File} "..\bin\Release\VisualDWizard\obj\" VisualDWizard.dll
+
+ push $1
+ Call VSConfigurationChanged
+
+ pop $1
+
+FunctionEnd
+
+!endif ; VS2026
+
; -----------------------------------------
Function DetectVS
@@ -2257,9 +2401,9 @@ Function DetectVS
StrCpy $0 "$PROGRAMFILES\Microsoft Visual Studio\Installer\vswhere.exe"
IfFileExists "$0" 0 no_vswhere
nsExec::ExecToStack '"$0" -products * -prerelease -property installationPath'
- Pop $1 ; stdout: path
Pop $0 ; result code
- StrCmp $0 0 no_vswhere
+ Pop $1 ; stdout: path
+ StrCmp $0 0 0 no_vswhere
StrCmp $1 "" no_vswhere
StrCpy $VSVersion "VS2017+" ; value not used, but only checked if empty
no_vswhere:
@@ -2272,9 +2416,9 @@ Function DetectVC
StrCpy $0 "$PROGRAMFILES\Microsoft Visual Studio\Installer\vswhere.exe"
IfFileExists "$0" 0 no_vswhere
nsExec::ExecToStack '"$0" -products * -prerelease -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath'
- Pop $1 ; stdout: path
Pop $0 ; result code
- StrCmp $0 0 no_vswhere
+ Pop $1 ; stdout: path
+ StrCmp $0 0 0 no_vswhere
StrCmp $1 "" no_vswhere
StrCpy $VCVersion "VC2017+" ; value not used, but only checked if empty
StrCpy $VCPath $1
diff --git a/nsis/vsinstall.ini b/nsis/vsinstall.ini
new file mode 100644
index 00000000..0e89429a
--- /dev/null
+++ b/nsis/vsinstall.ini
@@ -0,0 +1,63 @@
+[Settings]
+NumFields=7
+
+[Field 1]
+Type=Groupbox
+Text=Select VS Install
+Flags=NOTABSTOP
+Left=0
+Right=300
+Top=36
+Bottom=136
+
+[Field 2]
+Type=RadioButton
+Text=Download and install Visual Studio 2022 Community or select your
+State=1
+Left=20
+Right=300
+Top=48
+Bottom=60
+
+[Field 3]
+Type=RadioButton
+Text=Download and install Visual Studio 2019 Community (for 32-bit host OS)
+State=0
+Left=20
+Right=300
+Top=74
+Bottom=86
+
+[Field 4]
+Type=RadioButton
+Text=Do nothing (when using an undetected Visual Studio Installation or only requiring msbuild integration)
+State=0
+Left=20
+Right=300
+Top=100
+Bottom=128
+
+[Field 5]
+Type=Label
+Text=Visual D is an extension to Microsoft Visual Studio, but no Visual Studio installation was found on your system. Please install one of the options below. Make sure to select the C++ workload for desktop development including the Windows SDK during installation.
+Left=0
+Right=300
+Top=0
+Bottom=36
+
+[Field 6]
+Type=Label
+Text=preferred version from
+Left=40
+Right=120
+Top=60
+Bottom=72
+
+[Field 7]
+Type=Link
+Text=https://visualstudio.microsoft.com/downloads/
+State=https://visualstudio.microsoft.com/downloads/
+Left=120
+Right=300
+Top=60
+Bottom=72
diff --git a/sdk/port/textfind100.d b/sdk/port/textfind100.d
new file mode 100644
index 00000000..f4cfac4b
--- /dev/null
+++ b/sdk/port/textfind100.d
@@ -0,0 +1,3 @@
+// missing in the SDK of VS 2022 Preview 17.8
+module sdk.port.textfind100;
+public import sdk.vsi.textfind90;
diff --git a/stdext/container.d b/stdext/container.d
index 42619331..07b94b6e 100644
--- a/stdext/container.d
+++ b/stdext/container.d
@@ -39,6 +39,13 @@ struct Queue(T)
return data[idx];
}
+ void clear()
+ {
+ for(size_t i = 0; i < used; i++)
+ data[i] = T.init;
+ used = 0;
+ }
+
ref Queue!T opOpAssign(string op)(ref T t) if (op == "~")
{
append(t);
diff --git a/stdext/string.d b/stdext/string.d
index 7343b177..b28d3648 100644
--- a/stdext/string.d
+++ b/stdext/string.d
@@ -379,10 +379,19 @@ T[] firstLine(T)(T[] s)
{
for(size_t i = 0; i < s.length; i++)
if(s[i] == '\n' || s[i] == '\r')
- return s[0..i];
+ return i + 2 < s.length ? s[0..i] ~ "..." : s[0..i];
return s;
}
+T[] firstLineOf(T)(T[][] arr)
+{
+ if (arr.length > 1)
+ return firstLine(arr[0]) ~ "...";
+ else if (arr.length > 0)
+ return firstLine(arr[0]);
+ return "";
+}
+
char kInvalidUTF8Replacement = '?';
inout(char)[] toUTF8Safe(inout(char)[] text)
diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd
index f49c420e..44c43d25 160000
--- a/vdc/dmdserver/dmd
+++ b/vdc/dmdserver/dmd
@@ -1 +1 @@
-Subproject commit f49c420e8197f61346d66ce0ecbd10088bd04625
+Subproject commit 44c43d25ec6dd7fb359d9f00d8efaead9bd3ae8c
diff --git a/vdc/dmdserver/dmdrmem.d b/vdc/dmdserver/dmdrmem.d
index e1d728ee..76e3054b 100644
--- a/vdc/dmdserver/dmdrmem.d
+++ b/vdc/dmdserver/dmdrmem.d
@@ -24,13 +24,13 @@ extern (C++) struct Mem
static void* xmalloc(size_t n) nothrow pure
{
if (*pcancel)
- throw new Error("cancel malloc"); //*pcancelError;
+ throw new CancelError("cancel malloc"); //*pcancelError;
return GC.malloc(n);
}
static void* xmalloc_noscan(size_t n) nothrow pure
{
if (*pcancel)
- throw new Error("cancel malloc");//*pcancelError;
+ throw new CancelError("cancel malloc");//*pcancelError;
return GC.malloc(n, GC.BlkAttr.NO_SCAN);
}
@@ -66,13 +66,21 @@ extern (C++) struct Mem
return p;
}
- extern(D) __gshared immutable cancelError = new Error("cancel malloc");
+ extern(D) __gshared immutable cancelError = new CancelError("cancel malloc");
extern(D) __gshared bool cancel;
// fake purity
enum pcancel = cast(immutable) &cancel;
enum pcancelError = cast(immutable) &cancelError;
}
+class CancelError : Error
+{
+ this(string s) pure
+ {
+ super(s);
+ }
+}
+
extern (C++) const __gshared Mem mem;
/**
diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d
index 011b48d5..99ad7886 100644
--- a/vdc/dmdserver/dmdserver.d
+++ b/vdc/dmdserver/dmdserver.d
@@ -137,6 +137,28 @@ version(DebugServer)
fflush(dbgfh);
}
}
+ string dbghdr(string msg, string fname, int line = -1, int col = -1)
+ {
+ if (fname.length)
+ {
+ fname = baseName(fname);
+ if (line >= 0)
+ {
+ fname ~= "(";
+ fname ~= line.to!string();
+ if (col >= 0)
+ {
+ fname ~= ",";
+ fname ~= col.to!string();
+ }
+ fname ~= ")";
+ }
+ msg ~= " ";
+ msg ~= fname;
+ }
+ msg ~= ": ";
+ return msg;
+ }
}
///////////////////////////////////////////////////////////////
@@ -204,6 +226,8 @@ class DMDServer : ComObject, IVDServer
return super.QueryInterface(riid, pvObject);
}
+ static __gshared bool gScheduuleBusy;
+
extern(D) static void taskLoop(Tid tid)
{
bool cont = true;
@@ -214,6 +238,8 @@ class DMDServer : ComObject, IVDServer
receiveTimeout(dur!"msecs"(50),
(delegate_fake dg_fake)
{
+ gScheduuleBusy = true;
+ scope(exit) gScheduuleBusy = false;
void delegate() dg = *(cast(void delegate()*)&dg_fake);
dg();
},
@@ -302,12 +328,16 @@ class DMDServer : ComObject, IVDServer
auto p = opts.cmdline.indexOf(" -memThreshold=");
const(char)[] arg = p >= 0 ? opts.cmdline[p + 15..$] : "0";
opts.restartMemThreshold = parseLong(arg, res) ? cast(uint)res : 0;
+
+ version(DebugServer)
+ if(dbgfh) dbglog(dbghdr("Configure", fname) ~ " " ~ cmdln);
}
return S_OK;
}
override HRESULT ClearSemanticProject()
{
+ version(DebugServer) if(dbgfh) dbglog("ClearSemanticProject");
/+
synchronized(mSemanticProject)
mSemanticProject.disconnectAll();
@@ -318,7 +348,7 @@ class DMDServer : ComObject, IVDServer
return S_OK;
}
- extern(D) static void tryExec(void delegate() dg)
+ extern(D) static void tryExec(string dbgmsg, void delegate() dg)
{
try
{
@@ -330,16 +360,22 @@ class DMDServer : ComObject, IVDServer
}
catch(Exception e)
{
- version(DebugServer) if(dbgfh) dbglog("UpdateModule.doParse: exception " ~ e.toString());
+ version(DebugServer) if(dbgfh) dbglog(dbgmsg ~ ": exception " ~ e.toString());
}
catch(OutOfMemoryError oom)
{
+ version(DebugServer) if(dbgfh) dbglog(dbgmsg ~ ": out of memory");
exit(33); // throw oom; // terminate
}
+ catch(CancelError t)
+ {
+ t.info = null;
+ version(DebugServer) if(dbgfh) dbglog(dbgmsg ~ ": " ~ t.toString());
+ }
catch(Throwable t)
{
- version(DebugServer) if(dbgfh) dbglog("UpdateModule.doParse: error " ~ t.toString());
- if (t.msg != "cancel malloc" && t.msg != "fatal error") // fatal() is a non-fatal error
+ version(DebugServer) if(dbgfh) dbglog(dbgmsg ~ ": error " ~ t.toString());
+ if (t.msg != "fatal error") // fatal() is a non-fatal error
exit(37); // terminate the server and let it be restarted
}
}
@@ -400,8 +436,6 @@ class DMDServer : ComObject, IVDServer
void doParse()
{
- version(DebugServer) if(dbgfh) dbglog(" doParse: " ~ firstLine(text));
-
synchronized(gErrorSync)
{
modData.state = ModuleState.Parsing;
@@ -414,7 +448,7 @@ class DMDServer : ComObject, IVDServer
if(flags & 1)
writeReadyMessage();
}
- version(DebugServer) if(dbgfh) dbglog(" scheduleParse: " ~ firstLine(text));
+ version(DebugServer) if(dbgfh) dbglog(dbghdr("UpdateModule", fname) ~ firstLine(text));
schedule(&doParse);
return S_OK;
}
@@ -430,7 +464,7 @@ class DMDServer : ComObject, IVDServer
if (md.state == ModuleState.Done)
{
string err = md.parseErrors ~ md.analyzeErrors;
- version(DebugServer) if(dbgfh) dbglog("GetParseErrors: " ~ err);
+ version(DebugServer) if(dbgfh) dbglog(" GetParseErrors: " ~ err);
*errors = allocBSTR(err);
return S_OK;
@@ -473,18 +507,19 @@ class DMDServer : ComObject, IVDServer
}
catch(OutOfMemoryError e)
{
+ version(DebugServer) if(dbgfh) dbglog(" GetTip: out of memory");
throw e; // terminate
}
catch(Throwable t)
{
- version(DebugServer) if(dbgfh) dbglog("GetTip: exception " ~ t.toString());
+ version(DebugServer) if(dbgfh) dbglog(" GetTip: exception " ~ t.toString());
txt = "exception: " ~ t.msg;
}
}
mLastTip = txt;
mSemanticTipRunning = false;
}
- version(DebugServer) if(dbgfh) dbglog(" schedule GetTip: " ~ fname);
+ version(DebugServer) if(dbgfh) dbglog(dbghdr("GetTip", fname, startLine, startIndex));
mSemanticTipRunning = true;
schedule(&_getTip);
@@ -499,7 +534,7 @@ class DMDServer : ComObject, IVDServer
return S_OK;
}
- version(DebugServer) if(dbgfh) dbglog("GetTipResult: " ~ mLastTip);
+ version(DebugServer) if(dbgfh) dbglog(" GetTipResult: " ~ mLastTip);
writeReadyMessage();
startLine = mTipSpan.start.line;
startIndex = mTipSpan.start.index;
@@ -540,17 +575,18 @@ class DMDServer : ComObject, IVDServer
}
catch(OutOfMemoryError e)
{
+ version(DebugServer) if(dbgfh) dbglog(" GetDefinition: out of memory");
throw e; // terminate
}
catch(Throwable t)
{
- version(DebugServer) if(dbgfh) dbglog("GetDefinition: exception " ~ t.toString());
+ version(DebugServer) if(dbgfh) dbglog(" GetDefinition: exception " ~ t.toString());
}
}
mLastDefFile = deffilename;
mSemanticDefinitionRunning = false;
}
- version(DebugServer) if(dbgfh) dbglog(" schedule GetDefinition: " ~ fname);
+ version(DebugServer) if(dbgfh) dbglog(dbghdr("GetDefinition", fname, startLine, startIndex));
mSemanticDefinitionRunning = true;
schedule(&_getDefinition);
@@ -565,7 +601,7 @@ class DMDServer : ComObject, IVDServer
return S_OK;
}
- version(DebugServer) if(dbgfh) dbglog("GetDefinitionResult: " ~ mLastDefFile);
+ version(DebugServer) if(dbgfh) dbglog(" GetDefinitionResult: " ~ mLastDefFile);
writeReadyMessage();
startLine = mDefSpan.end.line;
startIndex = mDefSpan.end.index - 1;
@@ -599,16 +635,17 @@ class DMDServer : ComObject, IVDServer
}
catch(OutOfMemoryError e)
{
+ version(DebugServer) if(dbgfh) dbglog(" GetSemanticExpansions: out of memory");
throw e; // terminate
}
catch(Throwable t)
{
- version(DebugServer) if(dbgfh) dbglog("calcExpansions: exception " ~ t.toString());
+ version(DebugServer) if(dbgfh) dbglog(" GetSemanticExpansions: exception " ~ t.toString());
}
mSemanticExpansionsRunning = false;
mLastSymbols = symbols;
}
- version(DebugServer) if(dbgfh) dbglog(" schedule GetSemanticExpansions: " ~ fname ~ "(" ~ to!string(line) ~ "," ~ to!string(idx) ~ "): " ~ stok);
+ version(DebugServer) if(dbgfh) dbglog(dbghdr("GetSemanticExpansions", fname, line, idx) ~ stok);
mLastSymbols = null;
mSemanticExpansionsRunning = true;
schedule(&_calcExpansions);
@@ -629,7 +666,7 @@ class DMDServer : ComObject, IVDServer
}
*stringList = allocBSTR(slist.data);
- version(DebugServer) if(dbgfh) dbglog("GetSemanticExpansionsResult: " ~ slist.data);
+ version(DebugServer) if(dbgfh) dbglog(" GetSemanticExpansionsResult: " ~ slist.data);
writeReadyMessage();
return S_OK;
}
@@ -707,10 +744,36 @@ class DMDServer : ComObject, IVDServer
override HRESULT GetLastMessage(BSTR* message)
{
+ checkGCStats();
+
if(!mLastMessage.length)
{
if(mNextReadyMessage > Clock.currTime())
+ {
+ version(none)
+ if(!gScheduuleBusy)
+ {
+ void doAnalyze()
+ {
+
+ synchronized(gDMDSync)
+ {
+ if (Module m = analyzeInvalidatedModule(true))
+ {
+ version(DebugServer) if(dbgfh) dbglog(" doAnalyze " ~ m.srcfile.toString());
+ analyzeModule(m, lastContext.options);
+ }
+ }
+ }
+ if (Module m = analyzeInvalidatedModule(true))
+ {
+ mLastMessage = "Analyzing " ~ cast(string)m.srcfile.toString();
+ schedule(&doAnalyze);
+ }
+
+ }
return S_FALSE;
+ }
mLastMessage = "Ready";
mNextReadyMessage = Clock.currTime().add!"years"(1);
@@ -757,17 +820,18 @@ class DMDServer : ComObject, IVDServer
}
catch(OutOfMemoryError e)
{
+ version(DebugServer) if(dbgfh) dbglog(" GetReferences: out of memory");
throw e; // terminate
}
catch(Throwable t)
{
- version(DebugServer) if(dbgfh) dbglog("GetReferences: exception " ~ t.toString());
+ version(DebugServer) if(dbgfh) dbglog(" GetReferences: exception " ~ t.toString());
}
}
mLastReferences = references;
mSemanticGetReferencesRunning = false;
}
- version(DebugServer) if(dbgfh) dbglog(" schedule GetReferences: " ~ fname);
+ version(DebugServer) if(dbgfh) dbglog(dbghdr("GetReferences", fname));
mSemanticGetReferencesRunning = true;
schedule(&_getReferences);
@@ -781,7 +845,7 @@ class DMDServer : ComObject, IVDServer
*stringList = allocBSTR("__pending__");
return S_OK;
}
- version(DebugServer) if(dbgfh) dbglog("GetReferencesResult: " ~ firstLine(mLastReferences) ~ "...");
+ version(DebugServer) if(dbgfh) dbglog(" GetReferencesResult: " ~ firstLine(mLastReferences) ~ "...");
*stringList = allocBSTR(mLastReferences);
return S_OK;
}
@@ -820,19 +884,23 @@ class DMDServer : ComObject, IVDServer
}
catch(OutOfMemoryError e)
{
+ version(DebugServer) if(dbgfh) dbglog(" GetIdentifierTypes: out of memory");
throw e; // terminate
}
catch(Throwable t)
{
- version(DebugServer) if(dbgfh) dbglog("GetIdentifierTypes: exception " ~ t.toString());
+ version(DebugServer) if(dbgfh) dbglog(" GetIdentifierTypes: exception " ~ t.toString());
}
}
mLastIdentifierTypes = identiferTypes;
mSemanticIdentifierTypesRunning = false;
}
- version(DebugServer) if(dbgfh) dbglog(" schedule GetIdentifierTypes: " ~ fname);
+ version(DebugServer) if(dbgfh) dbglog(dbghdr("GetIdentifierTypes", fname));
mSemanticIdentifierTypesRunning = true;
- schedule(&_getIdentifierTypes);
+ if (flags & 2)
+ _getIdentifierTypes();
+ else
+ schedule(&_getIdentifierTypes);
return S_OK;
}
@@ -844,7 +912,7 @@ class DMDServer : ComObject, IVDServer
*types = allocBSTR("__pending__");
return S_OK;
}
- version(DebugServer) if(dbgfh) dbglog("GetIdentifierTypesResult: " ~ firstLine(mLastIdentifierTypes) ~ "...");
+ version(DebugServer) if(dbgfh) dbglog(" GetIdentifierTypesResult: " ~ firstLine(mLastIdentifierTypes) ~ "...");
*types = allocBSTR(mLastIdentifierTypes);
return S_OK;
}
@@ -860,7 +928,7 @@ class DMDServer : ComObject, IVDServer
md = findModule(fname, false);
if (!md || !md.analyzedModule)
{
- version(DebugServer) if(dbgfh) dbglog("GetParameterStorageLocs: " ~ fname ~ " not found");
+ version(DebugServer) if(dbgfh) dbglog(dbghdr("GetParameterStorageLocs", fname) ~ " not found");
return S_FALSE;
}
}
@@ -870,7 +938,7 @@ class DMDServer : ComObject, IVDServer
SAFEARRAY *sa = SafeArrayCreateVector(VT_INT, 0, 3 * cast(ULONG) stcLoc.length);
if(!sa)
{
- version(DebugServer) if(dbgfh) dbglog("GetParameterStorageLocs: " ~ fname ~ " out of memory (" ~ to!string(stcLoc.length) ~ " entries)");
+ version(DebugServer) if(dbgfh) dbglog(dbghdr("GetParameterStorageLocs", fname) ~ " out of memory (" ~ to!string(stcLoc.length) ~ " entries)");
return E_OUTOFMEMORY;
}
@@ -887,7 +955,7 @@ class DMDServer : ComObject, IVDServer
SafeArrayPutElement(sa, &idx, &value);
}
- version(DebugServer) if(dbgfh) dbglog("GetParameterStorageLocs: " ~ fname ~ " OK (" ~ to!string(stcLoc.length) ~ " entries)");
+ version(DebugServer) if(dbgfh) dbglog(dbghdr("GetParameterStorageLocs", fname) ~ " OK (" ~ to!string(stcLoc.length) ~ " entries)");
locs.vt = VT_ARRAY | VT_INT;
locs.parray = sa;
return S_OK;
@@ -944,7 +1012,7 @@ class DMDServer : ComObject, IVDServer
if (fname)
{
- tryExec(()
+ tryExec(" parseModule", ()
{
initErrorMessages(fname);
modData.parsedModule = createModuleFromText(fname, text);
@@ -954,7 +1022,7 @@ class DMDServer : ComObject, IVDServer
modData.state = ModuleState.Analyzing;
- tryExec(()
+ tryExec(" analyzeModule", ()
{
if (modData.parsedModule)
{
@@ -1007,6 +1075,26 @@ private:
return md;
}
+ void checkGCStats()
+ {
+ version(DebugServer)
+ {
+ auto profileStats = GC.profileStats();
+ if (profileStats.numCollections == mProfileStats.numCollections)
+ return;
+
+ auto stats = GC.stats();
+
+ auto count = profileStats.numCollections - mProfileStats.numCollections;
+ auto time = profileStats.totalCollectionTime - mProfileStats.totalCollectionTime;
+ if(dbgfh)
+ dbglog("GC: " ~ to!string(count) ~ " collections took " ~ to!string(time.total!"msecs") ~ " ms, " ~
+ "now at " ~ to!string(stats.usedSize >> 20) ~ " MB");
+
+ mProfileStats = profileStats;
+ }
+ }
+
version(SingleThread) Tid mTid;
Options mOptions;
@@ -1036,6 +1124,8 @@ private:
string mLastError;
bool mHadMessage;
SysTime mNextReadyMessage;
+
+ GC.ProfileStats mProfileStats;
}
////////////////////////////////////////////////////////////////
diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj
index d98e2eb0..9026fe68 100644
--- a/vdc/dmdserver/dmdserver.visualdproj
+++ b/vdc/dmdserver/dmdserver.visualdproj
@@ -1673,7 +1673,7 @@
1
0
0
- 0
+ 1
1
0
0
diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d
index 61996022..d07a882a 100644
--- a/vdc/dmdserver/semanalysis.d
+++ b/vdc/dmdserver/semanalysis.d
@@ -22,12 +22,17 @@ import dmd.errors;
import dmd.globals;
import dmd.identifier;
import dmd.location;
+import dmd.mtype;
import dmd.semantic2;
import dmd.semantic3;
+import dmd.visitor;
+import dmd.root.string: toDString;
+import dmd.root.stringtable;
import std.algorithm;
import std.path;
import std.conv;
+import stdext.array;
// version = ReinitSemanticAll;
@@ -50,7 +55,7 @@ struct ModuleInfo
if (resolve)
{
m.resolvePackage(); // adds module to Module.amodules (ignore return which could be module with same name)
- Module.modules.insert(m);
+ //Module.modules.insert(m);
}
return m;
}
@@ -128,6 +133,167 @@ void reinitSemanticModules()
mi.semanticModule = null;
}
+alias Mod = void*;
+alias Typ = void*;
+Mod asKey(Module m) { return cast(Mod)m; }
+Typ asKey(Type t) { return cast(Typ)t; }
+
+bool[Mod] findDependentModules(Module mod)
+{
+ // C++ classes don't work as AA keys
+ bool[Mod] dependents;
+ bool[Mod][Mod] importedBy;
+
+ foreach(m; Module.amodules)
+ foreach (Module mi; m.aimports)
+ importedBy[mi.asKey][m.asKey] = true;
+
+ if (mod.asKey !in importedBy)
+ return null;
+
+ // transitive closure
+ for (int chg = 1; chg > 0; )
+ {
+ chg = 0;
+ bool create_imp() scope { chg++; return true; }
+ void update_imp(ref bool) scope {}
+ foreach (m1, imps1; importedBy)
+ foreach (m2, b2; imps1) // m1 imported by m2
+ if (auto pimps2 = m2 in importedBy)
+ foreach (m3, b3; *pimps2) // m2 imported by m3
+ imps1.update(m3, &create_imp, &update_imp); // -> m1 imported by m3
+ }
+
+ return importedBy[mod.asKey];
+}
+
+bool[Typ] findDependentTypes(bool[Mod] deps)
+{
+ bool[Typ] depTypes;
+ int isDependentType(const(StringValue!Type)* sv) nothrow scope
+ {
+ extern(C++) class DependentTypeVisitor : Visitor
+ {
+ alias visit = Visitor.visit;
+ bool inDeps;
+
+ override void visit(Type t)
+ {
+ if (!inDeps && t.asKey in depTypes)
+ inDeps = true;
+ }
+ override void visit(TypeBasic t)
+ {
+ // avoid the lookup in visit(Type)
+ }
+ override void visit(TypeVector tv)
+ {
+ super.visit(tv);
+ if (!inDeps)
+ tv.basetype.accept(this);
+ }
+ override void visit(TypeNext tn)
+ {
+ super.visit(tn);
+ if (!inDeps)
+ tn.next.accept(this);
+ }
+ override void visit(TypeAArray taa)
+ {
+ super.visit(taa);
+ if (!inDeps)
+ taa.index.accept(this);
+ }
+ override void visit(TypeFunction tf)
+ {
+ super.visit(tf);
+ if (!inDeps)
+ foreach (i, fparam; tf.parameterList)
+ fparam.type.accept(this);
+ }
+ override void visit(TypeTuple tt)
+ {
+ super.visit(tt);
+ if (!inDeps && tt.arguments)
+ foreach (arg; *tt.arguments)
+ arg.type.accept(this);
+ }
+ override void visit(TypeStruct ts)
+ {
+ super.visit(ts);
+ auto m = ts.sym.getModule();
+ if (m.asKey in deps)
+ inDeps = true;
+ }
+ override void visit(TypeClass tc)
+ {
+ super.visit(tc);
+ auto m = tc.sym.getModule();
+ if (m.asKey in deps)
+ inDeps = true;
+ }
+ override void visit(TypeEnum te)
+ {
+ super.visit(te);
+ auto m = te.sym.getModule();
+ if (m.asKey in deps)
+ inDeps = true;
+ }
+ }
+ auto type = cast(Type)sv.value;
+ scope vis = new DependentTypeVisitor;
+ try
+ {
+ type.accept(vis);
+ if (vis.inDeps)
+ depTypes[type.asKey] = true;
+ }
+ catch(Exception e)
+ {
+ // Stringtype.apply wants this to be nothrow
+ }
+ return 0; // continue
+ }
+ Type.stringtable.opApply(&isDependentType);
+ return depTypes;
+}
+
+bool invalidateDependents(AnalysisContext ctxt, Module mod)
+{
+ bool[Mod] deps = findDependentModules(mod);
+ deps[mod.asKey] = true;
+
+ for (size_t i = 0; i < Module.amodules.dim; )
+ if (Module.amodules[i].asKey in deps)
+ Module.amodules.remove(i);
+ else
+ i++;
+
+ foreach(mv, b; deps)
+ {
+ auto m = cast(Module)mv;
+ DsymbolTable dst;
+ if (m.md)
+ dst = Package.resolve(m.md.packages, null, null);
+ else
+ dst = Module.modules;
+
+ version(GC) // needed for self-compilation
+ if (dst.lookup(m.ident))
+ dst.tab.aa.remove(cast(void*)m.ident);
+ }
+
+ foreach(ref mi; ctxt.modules)
+ if (mi.semanticModule.asKey in deps)
+ mi.semanticModule = null;
+
+ auto depTypes = findDependentTypes(deps);
+ foreach(type, b; depTypes)
+ Type.stringtable.remove((cast(Type)type).deco.toDString);
+
+ return true;
+}
+
//
Module analyzeModule(Module parsedModule, const ref Options opts)
{
@@ -138,6 +304,7 @@ Module analyzeModule(Module parsedModule, const ref Options opts)
lastContext = new AnalysisContext;
AnalysisContext ctxt = lastContext;
+ size_t[] dependents;
auto filename = parsedModule.srcfile.toString();
int idx = ctxt.findModuleInfo(filename);
if (ctxt.options == opts)
@@ -150,6 +317,30 @@ Module analyzeModule(Module parsedModule, const ref Options opts)
ctxt.modules[idx].parsedModule = parsedModule;
// TODO: only update dependent modules
+ version(none) // too unstable
+ {
+ needsReinit = false;
+
+ if (auto m = ctxt.modules[idx].semanticModule)
+ {
+ DsymbolTable dst;
+ if (parsedModule.md)
+ dst = Package.resolve(parsedModule.md.packages, null, null);
+ else
+ dst = Module.modules;
+ auto mid = parsedModule.md ? parsedModule.md.id : parsedModule.ident;
+ Dsymbol prev = dst.lookup(mid); // package handling?
+ if (prev && prev != m)
+ needsReinit = true;
+ else
+ invalidateDependents(ctxt, m);
+ }
+ }
+ if (!needsReinit)
+ {
+ ctxt.modules[idx].semanticModule = null;
+ ctxt.modules[idx].createSemanticModule(true);
+ }
}
else
{
@@ -248,9 +439,32 @@ Module analyzeModule(Module parsedModule, const ref Options opts)
mi.semanticModule.importAll(null);
semantic(mi.semanticModule);
+ version(none)
+ {
+ foreach(i; dependents)
+ ctxt.modules[i].createSemanticModule(true);
+ foreach(i; dependents)
+ ctxt.modules[i].semanticModule.importAll(null);
+ foreach(i; dependents)
+ semantic(ctxt.modules[i].semanticModule);
+ }
return Module.rootModule;
}
+Module analyzeInvalidatedModule(bool findOnly)
+{
+ if (lastContext)
+ foreach(mi; lastContext.modules)
+ if (mi.parsedModule && !mi.semanticModule)
+ {
+ if (findOnly)
+ return mi.parsedModule;
+ else
+ return analyzeModule(mi.parsedModule, lastContext.options);
+ }
+ return null;
+}
+
debug
{
auto __debugOverview(Identifier id)
@@ -1608,16 +1822,30 @@ void do_unittests()
};
m = checkErrors(source, "");
- import dmd.common.outbuffer;
- import dmd.hdrgen;
- auto buf = OutBuffer();
- buf.doindent = 1;
- moduleToBuffer(buf, true, m);
- auto modstr = buf.extractData();
-
checkTip(m, 12, 17, "`source.Expression source.ctfeEmplaceExp!(source.Expression)() pure nothrow @safe`");
checkTip(m, 12, 23, "(class) `source.Expression`");
+ source = q{
+ char[100] tempMem;
+ size_t allocOffset = 0;
+
+ char[] concat(char[] s, string a, string b) // Line 5
+ {
+ return s;
+ }
+ char[] tconcat(Args...)(Args args)
+ { // Line 10
+ char[] r = concat(tempMem[allocOffset..$], args);
+ return r;
+ }
+ void inst_tconcat()
+ {
+ auto t = tconcat("1", "2");
+ }
+ };
+ m = checkErrors(source, "");
+ checkTip(m, 11, 22, "(thread local global) `char[100] source.tempMem`");
+
// check FQN types in cast
source = q{
void foo(Error*)
@@ -2088,10 +2316,11 @@ void do_unittests()
checkTip(tmpl_m, 4, 11, "(parameter) `int x`");
filename = "source.d";
- version(ReinitSemanticAll)
+ version(all) //ReinitSemanticAll)
{
// parsing the template source file again forgets all instantiations
tmpl_m = checkErrors(tmpl_source, "");
+ analyzeInvalidatedModule(false);
checkTip(tmpl_m, 4, 11, "(parameter) `int x`");
//checkTip(tmpl_m, 8, 11, "(parameter) `T x`");
}
diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d
index 73e7be02..97c161a0 100644
--- a/vdc/dmdserver/semvisitor.d
+++ b/vdc/dmdserver/semvisitor.d
@@ -1384,6 +1384,32 @@ const(char)* docForSymbol(Dsymbol var)
return null;
}
+string rootObjectToString(RootObject obj)
+{
+ final switch (obj.dyncast())
+ {
+ case DYNCAST.identifier:
+ case DYNCAST.dsymbol:
+ case DYNCAST.type: // https://issues.dlang.org/show_bug.cgi?id=1215
+ case DYNCAST.expression: // https://issues.dlang.org/show_bug.cgi?id=1215
+ case DYNCAST.object:
+ case DYNCAST.tuple:
+ case DYNCAST.parameter:
+ case DYNCAST.statement:
+ case DYNCAST.templateparameter:
+ case DYNCAST.initializer:
+ return obj.toString().dup;
+ case DYNCAST.condition:
+ auto cond = cast(Condition)obj;
+ if (auto dc = cond.isDebugCondition())
+ return dc.ident.toString().dup;
+ if (auto vc = cond.isVersionCondition())
+ return vc.ident.toString().dup;
+ assert(0);
+ }
+ return "";
+}
+
TipData tipDataForObject(RootObject obj)
{
TipData tip;
@@ -1461,7 +1487,7 @@ TipData tipDataForObject(RootObject obj)
}
if (!tip.code.length)
{
- tip.code = obj.toString().dup;
+ tip.code = rootObjectToString(obj);
}
// append doc
if (doc)
diff --git a/vdc/ivdserver.d b/vdc/ivdserver.d
index 84e2fcf5..06d5640e 100644
--- a/vdc/ivdserver.d
+++ b/vdc/ivdserver.d
@@ -173,6 +173,7 @@ public:
// startLine:
// endLine: results may be restricted to identifiers within this range
// flags: bit 0 - resolveTypes: resolve field/alias identifier types
+ // bit 1 - syncExec: no asynchronous execution
//
// this method is called once after GetParseErrors returned successfully
HRESULT GetIdentifierTypes(const BSTR filename, int startLine, int endLine, int flags);
diff --git a/visuald/Templates/ProjectItems/VCProject/main.d b/visuald/Templates/ProjectItems/VCProject/main.d
index 316c1c52..2dc67ab9 100644
--- a/visuald/Templates/ProjectItems/VCProject/main.d
+++ b/visuald/Templates/ProjectItems/VCProject/main.d
@@ -8,10 +8,10 @@ extern (C) int _d_run_main(int argc, char **argv, MainFunc mainFunc);
extern (Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
- return _d_run_main(0, null, &main); // arguments unused, retrieved via CommandLineToArgvW
+ return _d_run_main(0, null, &win_main); // arguments unused, retrieved via CommandLineToArgvW
}
-extern(C) int main(string[] args)
+extern(C) int win_main(string[] args)
{
MessageBoxW(null, "Hello D World!"w.ptr, "D Windows Application"w.ptr, MB_OK);
return 0;
@@ -47,4 +47,4 @@ int foo()
{
return 42;
}
-$endif$
\ No newline at end of file
+$endif$
diff --git a/visuald/dlangsvc.d b/visuald/dlangsvc.d
index 63e7efcf..be799c1f 100644
--- a/visuald/dlangsvc.d
+++ b/visuald/dlangsvc.d
@@ -1160,7 +1160,11 @@ class LanguageService : DisposingComObject,
string docName = toLower(file);
CHierNode node = searchNode(cfg.GetProject().GetRootNode(), delegate (CHierNode n) { return n.GetCanonicalName() == docName; });
if (auto pFile = cast(CFileNode) node)
- cmdline = cfg.GetCompileCommand(pFile, true);
+ {
+ cmdline = cfgopts.buildCommandLine(cfg, true, false, null, true);
+ if (cfgopts.additionalOptions.length)
+ cmdline ~= " " ~ cfgopts.additionalOptions.replace("\n", " ");
+ }
else
cmdline = cfgopts.dmdFrontEndOptions();
}
@@ -4701,7 +4705,7 @@ else
}
extern(D) void OnUpdateModule(uint request, string filename, string parseErrors, vdc.util.TextPos[] binaryIsIn,
- string tasks, string outline, ParameterStorageLoc[] parameterStcLocs)
+ string tasks, string outline, string identifierTypes, ParameterStorageLoc[] parameterStcLocs)
{
mHasPendingUpdateModule = false;
if (!Package.GetGlobalOptions().showParseErrors)
@@ -4719,8 +4723,9 @@ else
Package.GetTaskProvider().updateTaskItems(filename, tasks);
if (Package.GetGlobalOptions().semanticHighlighting)
- Package.GetLanguageService().GetIdentifierTypes(this, 0, -1, Package.GetGlobalOptions().semanticResolveFields,
- &OnUpdateIdentifierTypes);
+ OnUpdateIdentifierTypes(request, filename, identifierTypes);
+ // Package.GetLanguageService().GetIdentifierTypes(this, 0, -1, Package.GetGlobalOptions().semanticResolveFields,
+ // &OnUpdateIdentifierTypes);
if (mCodeWinMgr && mCodeWinMgr.mNavBar)
mCodeWinMgr.mNavBar.UpdateFromSource(outline);
diff --git a/visuald/dpackage.d b/visuald/dpackage.d
index 8e3a9323..30e4cb6f 100644
--- a/visuald/dpackage.d
+++ b/visuald/dpackage.d
@@ -1623,6 +1623,7 @@ class GlobalOptions
bool mixinAnalysis;
bool UFCSExpansions;
bool showParamStorage;
+ bool logToOutputPane;
byte analyzeAfterEdit; // 0: edited file, 1: dependent files, 2: all edited files
byte sortExpMode; // 0: alphabetically, 1: by type, 2: by declaration and scope
bool exactExpMatch;
@@ -2052,6 +2053,7 @@ class GlobalOptions
//parseSource = getBoolOpt("parseSource", true);
showParseErrors = getBoolOpt("showParseErrors", true);
showParamStorage = getBoolOpt("showParamStorage", true);
+ logToOutputPane = getBoolOpt("logToOutputPane", false);
expandFromSemantics = getBoolOpt("expandFromSemantics", true);
//expandFromBuffer = getBoolOpt("expandFromBuffer", true);
expandFromJSON = getBoolOpt("expandFromJSON", true);
@@ -2243,6 +2245,7 @@ class GlobalOptions
updateDefaultColors();
+ setVDServerLogging(logToOutputPane);
if(VDServerIID.length > 0)
gServerClassFactory_iid = uuid(VDServerIID);
else
@@ -2333,6 +2336,7 @@ class GlobalOptions
//keyToolOpts.Set("parseSource", parseSource);
keyToolOpts.Set("showParseErrors", showParseErrors);
keyToolOpts.Set("showParamStorage", showParamStorage);
+ keyToolOpts.Set("logToOutputPane", logToOutputPane);
keyToolOpts.Set("expandFromSemantics", expandFromSemantics);
//keyToolOpts.Set("expandFromBuffer", expandFromBuffer);
keyToolOpts.Set("expandFromJSON", expandFromJSON);
@@ -2425,6 +2429,7 @@ class GlobalOptions
if(auto svc = Package.s_instance.mLangsvc)
svc.UpdateColorizer(true);
+ setVDServerLogging(logToOutputPane);
if(lastUseDParser != useDParser)
{
updateVDServer();
diff --git a/visuald/pkgutil.d b/visuald/pkgutil.d
index c7191b57..17c6658a 100644
--- a/visuald/pkgutil.d
+++ b/visuald/pkgutil.d
@@ -66,9 +66,12 @@ IVsOutputWindowPane getVisualDOutputPane()
IVsOutputWindowPane pane;
if(win.GetPane(&g_outputPaneCLSID, &pane) == S_OK && pane)
return pane;
- if(win.CreatePane(&g_outputPaneCLSID, "Visual D", false, true) == S_OK)
- if(win.GetPane(&g_outputPaneCLSID, &pane) == S_OK && pane)
- return pane;
+ if(win.CreatePane(&g_outputPaneCLSID, "Visual D", false, true) == S_OK &&
+ win.GetPane(&g_outputPaneCLSID, &pane) == S_OK && pane)
+ {
+ pane.Activate();
+ return pane;
+ }
if(win.GetPane(&GUID_BuildOutputWindowPane, &pane) != S_OK || !pane)
return null;
@@ -104,21 +107,27 @@ void openSettingsPage(in GUID clsid)
class OutputPaneBuffer
{
static shared(string) buffer;
+ static shared(bool) activatePane;
static shared(Object) syncOut = new shared(Object);
- static void push(string msg)
+ static void push(string msg, bool activate)
{
synchronized(OutputPaneBuffer.syncOut)
+ {
buffer ~= msg;
+ activatePane = activatePane || activate;
+ }
}
- static string pop()
+ static string pop(out bool activate)
{
string msg;
synchronized(OutputPaneBuffer.syncOut)
{
msg = buffer;
buffer = buffer.init;
+ activate = activatePane;
+ activate = false;
}
return msg;
}
@@ -127,22 +136,24 @@ class OutputPaneBuffer
{
if(buffer.length)
{
- string msg = pop();
- writeToBuildOutputPane(msg);
+ bool activate;
+ string msg = pop(activate);
+ writeToBuildOutputPane(msg, activate);
}
}
}
-void writeToBuildOutputPane(string msg)
+void writeToBuildOutputPane(string msg, bool activate = true)
{
if(IVsOutputWindowPane pane = getVisualDOutputPane())
{
scope(exit) release(pane);
- pane.Activate();
+ if (activate)
+ pane.Activate();
pane.OutputString(_toUTF16z(msg));
}
else
- OutputPaneBuffer.push(msg);
+ OutputPaneBuffer.push(msg, activate);
}
bool OutputErrorString(string msg)
diff --git a/visuald/propertypage.d b/visuald/propertypage.d
index eab55a1d..2a016753 100644
--- a/visuald/propertypage.d
+++ b/visuald/propertypage.d
@@ -38,6 +38,7 @@ import std.process : environment;
import std.string;
version = DParserOption;
+// version = AnalyzeAfterEditOption;
enum hasDubSupport = false;
class PropertyWindow : Window
@@ -2999,11 +3000,14 @@ class IntellisensePropertyPage : GlobalPropertyPage
kLabelWidth = kPageWidth * 4 / 5;
AddControl(" Restart parsing engine if it needs more than (MB, 0 for never)", mDmdServerMemThres = new Text(mCanvas));
kLabelWidth = saveWidth;
+ version(AnalyzeAfterEditOption)
+ AddControl(" after edit, analyze", mAnalyzeAfterEdit = new ComboBox(mCanvas, [ "edited file", "dependent files", "all edited files" ], false));
auto lineY = mLineY;
AddControl("", mShowParamStorage = new CheckBox(mCanvas, "Show parameter storage class at call site (experimental)"));
mLineY = lineY; // overlay with next
AddTwoControls(mMixinAnalysis = new CheckBox(mCanvas, "Enable mixin analysis"),
mUFCSExpansions = new CheckBox(mCanvas, "Enable UFCS expansions"));
+ AddControl("", mLogToOutputPane = new CheckBox(mCanvas, "Log semantic server communication to output pane"));
//AddControl("", mSemanticGotoDef = new CheckBox(mCanvas, "Use semantic analysis for \"Goto Definition\" (before trying JSON info)"));
AddTitleLine("Expansions");
AddControl("", mExpandSemantics = new CheckBox(mCanvas, "Expansions from semantic analysis"));
@@ -3037,6 +3041,8 @@ class IntellisensePropertyPage : GlobalPropertyPage
mShowValueInTooltip.setEnabled(mShowTypeInTooltip.isChecked());
mShowSizeAndAlign.setEnabled(!useDParser);
mDmdServerMemThres.setEnabled(!useDParser);
+ version(AnalyzeAfterEditOption)
+ mAnalyzeAfterEdit.setEnabled(!useDParser);
}
override void SetControls(GlobalOptions opts)
@@ -3054,9 +3060,12 @@ class IntellisensePropertyPage : GlobalPropertyPage
mMixinAnalysis.setChecked(opts.mixinAnalysis);
mUFCSExpansions.setChecked(opts.UFCSExpansions);
mShowParamStorage.setChecked(opts.showParamStorage);
+ mLogToOutputPane.setChecked(opts.logToOutputPane);
mSortExpMode.setSelection(opts.sortExpMode);
mExactExpMatch.setChecked(opts.exactExpMatch);
mDmdServerMemThres.setText(to!string(opts.dmdServerMemThres));
+ version(AnalyzeAfterEditOption)
+ mAnalyzeAfterEdit.setSelection(opts.analyzeAfterEdit);
//mExpandSemantics.setEnabled(false);
EnableControls();
@@ -3078,8 +3087,11 @@ class IntellisensePropertyPage : GlobalPropertyPage
changes += changeOption(mMixinAnalysis.isChecked(), opts.mixinAnalysis, refopts.mixinAnalysis);
changes += changeOption(mUFCSExpansions.isChecked(), opts.UFCSExpansions, refopts.UFCSExpansions);
changes += changeOption(mShowParamStorage.isChecked(), opts.showParamStorage, refopts.showParamStorage);
+ changes += changeOption(mLogToOutputPane.isChecked(), opts.logToOutputPane, refopts.logToOutputPane);
changes += changeOption(cast(ubyte) mSortExpMode.getSelection(), opts.sortExpMode, refopts.sortExpMode);
changes += changeOption(mExactExpMatch.isChecked(), opts.exactExpMatch, refopts.exactExpMatch);
+ version(AnalyzeAfterEditOption)
+ changes += changeOption(cast(ubyte) mAnalyzeAfterEdit.getSelection(), opts.analyzeAfterEdit, refopts.analyzeAfterEdit);
import stdext.string;
long thres;
@@ -3100,10 +3112,13 @@ class IntellisensePropertyPage : GlobalPropertyPage
//CheckBox mSemanticGotoDef;
version(DParserOption) CheckBox mUseDmdParser;
CheckBox mShowParamStorage;
+ CheckBox mLogToOutputPane;
CheckBox mUFCSExpansions;
ComboBox mSortExpMode;
CheckBox mExactExpMatch;
CheckBox mMixinAnalysis;
+ version(AnalyzeAfterEditOption)
+ ComboBox mAnalyzeAfterEdit;
Text mDmdServerMemThres;
}
diff --git a/visuald/vdserverclient.d b/visuald/vdserverclient.d
index 53cdd860..7fbf7672 100644
--- a/visuald/vdserverclient.d
+++ b/visuald/vdserverclient.d
@@ -33,13 +33,14 @@ import std.string;
import std.conv;
import std.path;
import std.windows.charset;
+import core.atomic;
import core.thread;
alias object.AssociativeArray!(string, std.concurrency.Tid) _wa1; // fully instantiate type info for string[Tid]
alias object.AssociativeArray!(std.concurrency.Tid, string[]) _wa2; // fully instantiate type info for string[Tid]
// version(TESTMAIN) version = InProc;
-debug version = DebugCmd;
+version = DebugCmd;
// debug version = InProc;
version(InProc) import vdc.vdserver;
@@ -48,11 +49,17 @@ version(InProc) import vdc.vdserver;
version(DebugCmd)
{
import std.datetime;
-import core.stdc.stdio : fprintf, fopen, fflush, fputc, FILE;
+import core.stdc.stdio : fprintf, snprintf, fopen, fflush, fputc, FILE;
__gshared FILE* dbgfh;
+__gshared bool dbgfh_failed;
+__gshared bool dbglog_enabled;
private void dbglog(string s)
{
+ char[40] strtm;
+ SysTime now = Clock.currTime();
+ auto len = snprintf(strtm.ptr, 40, "%02d:%02d:%02d.%03d ",
+ now.hour, now.minute, now.second, cast(int)now.fracSecs.total!"msecs");
debug
{
version(all)
@@ -60,27 +67,31 @@ private void dbglog(string s)
else
OutputDebugStringA(toMBSz("VDClient: " ~ s ~ "\n"));
}
- else
+ else if (!dbgfh_failed)
{
if(!dbgfh)
{
import std.file;
- string fname = tempDir();
+ string fname = tempDir() ~ "/dmdserver";
char[20] name = "/vdclient0.log";
for (char i = '0'; !dbgfh && i <= '9'; i++)
{
name[9] = i;
dbgfh = fopen((fname ~ name).ptr, "w");
}
+ if (!dbgfh)
+ {
+ dbgfh_failed = true;
+ return;
+ }
}
- SysTime now = Clock.currTime();
uint tid = sdk.win32.winbase.GetCurrentThreadId();
- auto len = fprintf(dbgfh, "%02d:%02d:%02d - %04x - ",
- now.hour, now.minute, now.second, tid);
- fprintf(dbgfh, "%.*s", s.length, s.ptr);
+ fprintf(dbgfh, "%s - %04x - ", strtm.ptr, tid);
+ fprintf(dbgfh, "%.*s", cast(int)s.length, s.ptr);
fputc('\n', dbgfh);
fflush(dbgfh);
}
+ writeToBuildOutputPane(cast(string)(strtm[0..len] ~ firstLine(s) ~ "\n"), false);
}
}
@@ -127,7 +138,8 @@ bool startVDServer()
return false;
}
}
- version(DebugCmd) dbglog ("VDServer startet successfully");
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("VDServer startet successfully");
return true;
}
@@ -136,7 +148,8 @@ bool stopVDServer()
if(!gVDServer)
return false;
- version(DebugCmd) dbglog ("stopping VDServer");
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("stopping VDServer");
gVDServer = release(gVDServer);
gVDClassFactory = release(gVDClassFactory);
@@ -144,6 +157,11 @@ bool stopVDServer()
return true;
}
+void setVDServerLogging(bool log)
+{
+ dbglog_enabled = log;
+}
+
///////////////////////////////////////////////////////////////////////
struct FileCacheData
{
@@ -169,8 +187,9 @@ template _shared(T)
{
this(string cmd)
{
- mCommand = cmd;
- mRequest = sLastRequest++;
+ version(DebugCmd)
+ mCommand = cmd;
+ mRequest = sLastRequest.atomicOp!"+="(1);
}
// called from clientLoop (might block due to server garbage collecting)
@@ -186,22 +205,26 @@ template _shared(T)
// called from onIdle
bool forward()
{
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("#" ~ to!string(mRequest) ~ " fwrd: " ~ mCommand);
return true;
}
void send(Tid id)
{
- version(DebugCmd) dbglog(to!string(cast(void*)this) ~ " send: " ~ to!string(mRequest) ~ " " ~ mCommand);
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("#" ~ to!string(mRequest) ~ " send: " ~ mCommand);
.send(id, cast(size_t) cast(void*) this);
// .send(id, cast(shared)this);
// .send(id, this);
}
- static uint sLastRequest;
+ static shared uint sLastRequest;
uint mRequest;
- string mCommand;
+ version(DebugCmd)
+ string mCommand;
}
class ExitCommand : Command
@@ -259,7 +282,7 @@ class FileCommand : Command
{
this(string cmd, string filename)
{
- version(DebugCmd) cmd ~= ":" ~ baseName(filename);
+ version(DebugCmd) cmd ~= " " ~ baseName(filename);
super(cmd);
mFilename = filename;
}
@@ -377,6 +400,8 @@ class GetTipCommand : FileCommand
override bool forward()
{
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("#" ~ to!string(mRequest) ~ " fwrd: " ~ mCommand ~ " " ~ ": " ~ mType);
if(mCallback)
mCallback(mRequest, mFilename, mType, mSpan);
return true;
@@ -443,6 +468,8 @@ class GetDefinitionCommand : FileCommand
override bool forward()
{
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("#" ~ to!string(mRequest) ~ " fwrd: " ~ mCommand ~ " " ~ ": " ~ mDefFile);
if(mCallback)
mCallback(mRequest, mDefFile, mSpan);
return true;
@@ -456,17 +483,21 @@ class GetDefinitionCommand : FileCommand
//////////////////////////////////////
alias void delegate(uint request, string filename, string parseErrors,
- TextPos[] binaryIsIn, string tasks, string outline, ParameterStorageLoc[] stcLocs) UpdateModuleCallBack;
+ TextPos[] binaryIsIn, string tasks, string outline, string idTypes, ParameterStorageLoc[] stcLocs) UpdateModuleCallBack;
+
+__gshared uint[string] gLastModuleUpdates;
+shared(Object) gSyncLastModuleUpdates = new Object;
class UpdateModuleCommand : FileCommand
{
this(string filename, wstring text, bool verbose, UpdateModuleCallBack cb)
{
super("UpdateModule", filename);
- version(DebugCmd) mCommand ~= " " ~ to!string(firstLine(text));
mText = text;
mCallback = cb;
mVerbose = verbose;
+ synchronized(gSyncLastModuleUpdates)
+ gLastModuleUpdates[mFilename] = mRequest;
}
override HRESULT exec() const
@@ -474,6 +505,10 @@ class UpdateModuleCommand : FileCommand
if(!gVDServer)
return S_FALSE;
+ synchronized(gSyncLastModuleUpdates)
+ if (gLastModuleUpdates[mFilename] != mRequest)
+ return ERROR_CANCELLED;
+
BSTR bfname = allocBSTR(mFilename);
BSTR btxt = allocwBSTR(mText);
@@ -489,6 +524,10 @@ class UpdateModuleCommand : FileCommand
if(!gVDServer)
return S_FALSE;
+ synchronized(gSyncLastModuleUpdates)
+ if (gLastModuleUpdates[mFilename] != mRequest)
+ return ERROR_CANCELLED;
+
BSTR fname = allocBSTR(mFilename);
scope(exit) freeBSTR(fname);
BSTR errors;
@@ -543,17 +582,27 @@ class UpdateModuleCommand : FileCommand
if(gVDServer.GetParameterStorageLocs(fname, &stclocs) == S_OK)
variantToArray(stclocs, mParameterStcLocs);
}
-
+ if (Package.GetGlobalOptions().semanticHighlighting)
+ {
+ int flags = 2 | (Package.GetGlobalOptions().semanticResolveFields ? 1 : 0);
+ if (gVDServer.GetIdentifierTypes(fname, 0, -1, flags) == S_OK)
+ {
+ BSTR types;
+ if(gVDServer.GetIdentifierTypesResult(&types) == S_OK)
+ mIdentifierTypes = detachBSTR(types);
+ }
+ }
send(gUITid);
return S_OK;
}
override bool forward()
{
- version(DebugCmd)
- dbglog(to!string(mRequest) ~ " forward: " ~ mCommand ~ " " ~ ": " ~ mErrors);
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("#" ~ to!string(mRequest) ~ " fwrd: " ~ mCommand ~ " " ~ ": " ~ mErrors);
if(mCallback)
- mCallback(mRequest, mFilename, mErrors, cast(TextPos[])mBinaryIsIn, mTasks, mOutline, mParameterStcLocs);
+ mCallback(mRequest, mFilename, mErrors, cast(TextPos[])mBinaryIsIn, mTasks,
+ mOutline, mIdentifierTypes, mParameterStcLocs);
return true;
}
@@ -562,6 +611,7 @@ class UpdateModuleCommand : FileCommand
string mErrors;
string mTasks;
string mOutline;
+ string mIdentifierTypes;
bool mVerbose;
TextPos[] mBinaryIsIn;
ParameterStorageLoc[] mParameterStcLocs;
@@ -618,8 +668,8 @@ class GetIdentifierTypesCommand : FileCommand
override bool forward()
{
- version(DebugCmd)
- dbglog(to!string(mRequest) ~ " forward: " ~ mCommand ~ " " ~ ": " ~ mIdentifierTypes);
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("#" ~ to!string(mRequest) ~ " fwrd: " ~ mCommand ~ " " ~ ": " ~ mIdentifierTypes);
if(mCallback)
mCallback(mRequest, mFilename, mIdentifierTypes);
return true;
@@ -683,6 +733,8 @@ class GetExpansionsCommand : FileCommand
override bool forward()
{
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("#" ~ to!string(mRequest) ~ " fwrd: " ~ mCommand ~ " " ~ ": " ~ join(mExpansions, "\n"));
if(mCallback)
mCallback(mRequest, mFilename, mTok, mLine, mIndex, cast(string[])mExpansions);
return true;
@@ -747,6 +799,8 @@ class GetReferencesCommand : FileCommand
override bool forward()
{
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("#" ~ to!string(mRequest) ~ " fwrd: " ~ mCommand ~ " " ~ ": " ~ join(mReferences, "\n"));
if(mCallback)
mCallback(mRequest, mFilename, mTok, mLine, mIndex, cast(string[])mReferences);
return true;
@@ -790,6 +844,8 @@ class ServerRestartedCommand : Command
override bool forward()
{
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("#" ~ to!string(mRequest) ~ " fwrd: " ~ mCommand);
import visuald.dpackage;
Package.GetLanguageService().RestartParser();
return true;
@@ -821,6 +877,7 @@ class VDServerClient
//////////////////////////////////////
void shutDown()
{
+ dbglog_enabled = false; // output pane no longer accessible during shutdown
if(gVDServer)
{
(new _shared!(ExitCommand)).send(mTid);
@@ -954,12 +1011,16 @@ class VDServerClient
(size_t icmd)
{
auto cmd = cast(Command) cast(void*) icmd;
- version(DebugCmd) dbglog(to!string(cmd.mRequest) ~ " clientLp: " ~ cmd.mCommand);
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("#" ~ to!string(cmd.mRequest) ~ " exec: " ~ cmd.mCommand);
HRESULT hr = cmd.exec();
if(hr == S_OK)
toAnswer ~= cmd;
else if((hr & 0xffff) == RPC_S_SERVER_UNAVAILABLE)
restartServer = true;
+ else
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("#" ~ to!string(cmd.mRequest) ~ " skip: " ~ cmd.mCommand);
changed = true;
},
(Variant var)
@@ -973,6 +1034,8 @@ class VDServerClient
HRESULT hr = cmd.answer();
if(hr == S_OK || hr == ERROR_CANCELLED)
{
+ version(DebugCmd) if (dbglog_enabled && hr == ERROR_CANCELLED)
+ dbglog("#" ~ to!string(cmd.mRequest) ~ " cncl: " ~ cmd.mCommand);
toAnswer.remove(i);
changed = true;
lastAnswerTime = Clock.currTime();
@@ -1013,7 +1076,7 @@ class VDServerClient
restartServer = true;
}
- version(DebugCmd) if (changed)
+ version(DebugCmd) if (dbglog_enabled) if (changed)
{
string s = " answerQ = [";
for(int i = 0; i < toAnswer.length; i++)
@@ -1023,8 +1086,10 @@ class VDServerClient
if(restartServer)
{
restartServer = false;
- version(DebugCmd) dbglog("*** clientLoop: restarting server ***");
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("*** clientLoop: restarting server ***");
stopVDServer();
+ toAnswer.clear();
if (startVDServer())
(new _shared!(ServerRestartedCommand)()).send(gUITid);
else
@@ -1034,7 +1099,8 @@ class VDServerClient
}
catch(Throwable e)
{
- version(DebugCmd) dbglog ("clientLoop exception: " ~ e.msg);
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog ("clientLoop exception: " ~ e.msg);
}
stopVDServer();
}
@@ -1048,9 +1114,6 @@ class VDServerClient
(size_t icmd)
{
auto cmd = cast(Command) cast(void*) icmd;
- version(DebugCmd)
- if(cmd.mCommand != "GetMessage")
- dbglog(to!string(cmd.mRequest) ~ " " ~ "idleLoop: " ~ cmd.mCommand);
cmd.forward();
},
(Variant var)
@@ -1063,7 +1126,8 @@ class VDServerClient
}
catch(Throwable e)
{
- version(DebugCmd) dbglog ("clientLoop exception: " ~ e.msg);
+ version(DebugCmd) if (dbglog_enabled)
+ dbglog("clientLoop exception: " ~ e.msg);
}
}
}