diff --git a/CHANGES b/CHANGES
index 011eb8a4..62159c3c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1280,4 +1280,13 @@ Version history
* mago debugger expression evaluator:
- fixed wrong values displayed eventually when switching stack frames
* installer:
- - full installer now bundled with DMD 2.091.1 and LDC 1.23.0
+ - full installer now bundled with DMD 2.093.1 and LDC 1.23.0
+
+unreleased version 1.1.0
+ * dmdserver:
+ - updated to DMD 2.095.0-beta.1
+ - experimental: show parameter storage ref/out/lazy at call site
+ * editor:
+ - bugzilla 21239: navigation bar now sorted, symbols starting with "__" moved to the bottom
+ * installer:
+ - full installer now bundled with DMD 2.095.0-beta.1 and LDC 1.24.0
diff --git a/VERSION b/VERSION
index 8c887726..c9ec3bc4 100644
--- a/VERSION
+++ b/VERSION
@@ -1,5 +1,5 @@
#define VERSION_MAJOR 1
-#define VERSION_MINOR 0
-#define VERSION_REVISION 1
-#define VERSION_BETA
-#define VERSION_BUILD 0
+#define VERSION_MINOR 1
+#define VERSION_REVISION 0
+#define VERSION_BETA -beta
+#define VERSION_BUILD 1
diff --git a/c2d/idl2d.d b/c2d/idl2d.d
index 157c0f69..e99b8343 100644
--- a/c2d/idl2d.d
+++ b/c2d/idl2d.d
@@ -1628,6 +1628,8 @@ version(none) version(vsi)
if(currentModule == "msdbg")
replaceTokenSequence(tokens, "const DWORD S_UNKNOWN = 0x3;", "denum DWORD S_UNKNOWN = 0x3;", true);
+ if(currentModule == "msdbg167")
+ replaceTokenSequence(tokens, "__uuidof($data)", "$data.iid", true);
if(currentModule == "activdbg")
replaceTokenSequence(tokens, "const THREAD_STATE", "denum THREAD_STATE", true);
diff --git a/c2d/vsi2d.visualdproj b/c2d/vsi2d.visualdproj
index e713ed51..c499fec5 100644
--- a/c2d/vsi2d.visualdproj
+++ b/c2d/vsi2d.visualdproj
@@ -40,7 +40,6 @@
0
0
0
- 0
0
0
0
@@ -164,7 +163,6 @@
0
0
0
- 0
0
0
0
@@ -288,7 +286,6 @@
0
0
0
- 0
0
0
0
@@ -412,7 +409,6 @@
0
0
0
- 0
0
0
0
@@ -536,7 +532,6 @@
0
0
0
- 0
0
0
0
@@ -660,7 +655,6 @@
0
0
0
- 0
0
0
0
@@ -784,7 +778,6 @@
0
0
0
- 0
0
0
0
@@ -908,7 +901,6 @@
0
0
0
- 0
0
0
0
@@ -1032,7 +1024,6 @@
0
0
0
- 0
0
0
0
@@ -1156,7 +1147,6 @@
0
0
0
- 0
0
0
0
@@ -1280,7 +1270,6 @@
0
0
0
- 0
0
0
0
@@ -1404,7 +1393,6 @@
0
0
0
- 0
0
0
0
@@ -1528,7 +1516,6 @@
0
0
0
- 0
0
0
0
@@ -1652,7 +1639,6 @@
0
0
0
- 0
0
0
0
@@ -1776,7 +1762,6 @@
0
0
0
- 0
0
0
0
@@ -1900,7 +1885,6 @@
0
0
0
- 0
0
0
0
@@ -1986,6 +1970,7 @@
+
diff --git a/doc/StartPage.dd b/doc/StartPage.dd
index 62a6781a..f8c9d0d1 100644
--- a/doc/StartPage.dd
+++ b/doc/StartPage.dd
@@ -84,6 +84,13 @@ $(H2 News)
$(P $(LINK2 VersionHistory.html, Full version history and complete details...)
)
+2020-08-23 Version 1.0.1
+ $(UL
+ $(LI dmd based semantic engine: updated to DMD 2.093.1)
+ $(LI editor: now extra mouse buttons to navigate backward/forward supported)
+ $(LI installer: full installer now bundled with DMD 2.093.1 and LDC 1.23.0)
+ )
+
2020-07-04 Version 1.0.0
$(UL
$(LI DMD based semantic engine: enabled by default, updated to front end version 2.092)
@@ -92,36 +99,13 @@ $(UL
$(LI goto definition by clicking identifier in tool tip)
)
-2020-23-03 Version 0.52.0
+2020-03-23 Version 0.52.0
$(UL
$(LI mago: added support for tuples and simpler display of globals)
$(LI DMD based semantic engine: updated to 2.091, improvements to code-completions)
$(LI projects: updated support for all language options)
)
-2020-18-01 Version 0.51.0
-$(UL
- $(LI experimental: semantic server built from DMD frontend)
- $(LI VS2017+: Ctrl+Click goto definition added)
- $(LI VS2017+: syntax highlighted tool tips)
-)
-
-2019-09-03 Version 0.50.1
-$(UL
- $(LI Fixes some integration issues with VS 2019 16.2)
- $(LI mago: improve function call in watch window)
- $(LI better version highlighting for files not in project)
-)
-
-2019-06-23 Version 0.50.0
-$(UL
- $(LI Now checks for updates of Visual D, DMD and LDC and assists download and install)
- $(LI Setup including DMD and LDC now available)
- $(LI mago debugger: better support for dynamic type of classes, show exception messages,
- conditional breakpoints)
- $(LI highlight references to symbol at caret)
-)
-
$(LINK2 VersionHistory.html, more...)
$(H2 Download)
diff --git a/doc/VersionHistory.dd b/doc/VersionHistory.dd
index 9192af80..735bd904 100644
--- a/doc/VersionHistory.dd
+++ b/doc/VersionHistory.dd
@@ -1,5 +1,22 @@
Ddoc
+$(H2 2020-08-23 Version 1.0.1)
+ $(UL
+ $(LI dmd based semantic engine:
+ $(UL
+ $(LI updated to DMD 2.093.1)
+ $(LI fixed showing documentation for template functions)
+ ))
+ $(LI editor: now extra mouse buttons to navigate backward/forward supported)
+ $(LI project management:
+ $(UL
+ $(LI bugzilla 21024: VS2017/2019 new project: fixed unrelated files listed in New Project Dialog)
+ $(LI bugzilla 21028: project templates not visible when VS started as standard/restricted user)
+ ))
+ $(LI mago debugger expression evaluator: fixed wrong values displayed eventually when switching stack frames)
+ $(LI installer: full installer now bundled with DMD 2.093.1 and LDC 1.23.0)
+ )
+
$(H2 2020-07-04 Version 1.0.0)
$(UL
$(LI project management:
diff --git a/doc/visuald.ddoc b/doc/visuald.ddoc
index 91c98948..436fc200 100644
--- a/doc/visuald.ddoc
+++ b/doc/visuald.ddoc
@@ -1,6 +1,6 @@
-VERSION = 1.0.0
-DMD_VERSION = 2.092.1
-LDC_VERSION = 1.22.0
+VERSION = 1.0.1
+DMD_VERSION = 2.093.1
+LDC_VERSION = 1.23.0
ROOT_DIR = https://www.dlang.org/
ROOT = https://www.dlang.org
BODYCLASS = visuald
diff --git a/msbuild/dbuild/dbuild.csproj b/msbuild/dbuild/dbuild.csproj
index 0319cd26..6cf744c1 100644
--- a/msbuild/dbuild/dbuild.csproj
+++ b/msbuild/dbuild/dbuild.csproj
@@ -106,6 +106,7 @@
false
AnyCPU
12.0
+ false
pdbonly
@@ -161,7 +162,6 @@
-
@@ -225,7 +225,6 @@
c:\Windows\assembly\GAC\Microsoft.VisualStudio.VCProjectEngine\12.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.VCProjectEngine.dll
-
@@ -291,7 +290,6 @@
c:\Windows\assembly\GAC\Microsoft.VisualStudio.VCProjectEngine\14.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.VCProjectEngine.dll
-
Local
@@ -333,7 +331,6 @@
c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.VCProjectEngine.dll
-
@@ -358,7 +355,6 @@
assemblies\v16\Microsoft.VisualStudio.VCProjectEngine.dll
-
assemblies\v16\Microsoft.Build.CPPTasks.Common.dll
@@ -369,7 +365,6 @@
assemblies\v16_1\Microsoft.Build.CPPTasks.Common.dll
-
Designer
diff --git a/nsis/visuald.nsi b/nsis/visuald.nsi
index 4f1edbcd..d34c4d5b 100644
--- a/nsis/visuald.nsi
+++ b/nsis/visuald.nsi
@@ -29,12 +29,12 @@
; define DMD source path to include dmd installation
; !define DMD
-!define DMD_VERSION "2.093.1"
+!define DMD_VERSION "2.095.0-beta.1"
!define DMD_SRC c:\d\dmd-${DMD_VERSION}
; define LDC to include ldc installation
; !define LDC
-!define LDC_VERSION "1.23.0"
+!define LDC_VERSION "1.24.0"
!define LDC_SRC c:\d\ldc2-${LDC_VERSION}-windows-multilib
; define VS2019 to include VS2019 support
diff --git a/sdk/vsi.visualdproj b/sdk/vsi.visualdproj
index e1e77d4f..005e68af 100644
--- a/sdk/vsi.visualdproj
+++ b/sdk/vsi.visualdproj
@@ -2186,6 +2186,8 @@
+
+
@@ -2254,6 +2256,7 @@
+
diff --git a/vdc/abothe/comserver/DParserCOMServer.csproj b/vdc/abothe/comserver/DParserCOMServer.csproj
index 24e47158..d39272c3 100644
--- a/vdc/abothe/comserver/DParserCOMServer.csproj
+++ b/vdc/abothe/comserver/DParserCOMServer.csproj
@@ -25,6 +25,7 @@
4
x86
false
+ false
pdbonly
diff --git a/vdc/abothe/comserver/IVDServer.cs b/vdc/abothe/comserver/IVDServer.cs
index 2ad8bb48..34cba41e 100644
--- a/vdc/abothe/comserver/IVDServer.cs
+++ b/vdc/abothe/comserver/IVDServer.cs
@@ -38,6 +38,7 @@ public interface IVDServer
void GetReferencesResult (out string stringList);
void ConfigureCommentTasks (string tasks);
void GetCommentTasks (string filename, out string tasks);
+ void GetParameterStorageLocs(string filename, out object locs); // array of triplets of DWORD
}
}
diff --git a/vdc/abothe/comserver/VDServer.cs b/vdc/abothe/comserver/VDServer.cs
index 9ead348d..65d73d92 100644
--- a/vdc/abothe/comserver/VDServer.cs
+++ b/vdc/abothe/comserver/VDServer.cs
@@ -341,7 +341,12 @@ public void GetReferencesResult(out string stringList)
break;
}
}
-
+
+ public void GetParameterStorageLocs(string filename, out object locs)
+ {
+ throw new NotImplementedException();
+ }
+
#if false
[EditorBrowsable(EditorBrowsableState.Never)]
[ComRegisterFunction()]
diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd
index 43c6d688..6afbd059 160000
--- a/vdc/dmdserver/dmd
+++ b/vdc/dmdserver/dmd
@@ -1 +1 @@
-Subproject commit 43c6d688268b659317d8ea9a238642ee4067126b
+Subproject commit 6afbd059a93e5c85f7577f880d604b0a2853aaf4
diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d
index eb75fec3..00aaec55 100644
--- a/vdc/dmdserver/dmdinit.d
+++ b/vdc/dmdserver/dmdinit.d
@@ -67,15 +67,15 @@ enum string[2][] dmdStatics =
//["_D3dmd10expression10IntegerExp__T7literalVii1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"],
//["_D3dmd10expression10IntegerExp__T7literalViN1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"],
["_D3dmd10identifier10Identifier17generateIdWithLocFNbAyaKxSQCe7globals3LocZ8countersHSQDfQDeQCvQCmFNbQBwKxQBwZ3Keyk", "countersType"],
- ["_D3dmd10identifier10Identifier10generateIdFNbAxaZ1ik", "size_t"],
+ ["_D3dmd10identifier10Identifier9newSuffixFNbZ1ik", "size_t"],
];
string cmangled(string s)
{
version (Win64)
{
- if (s == "_D3dmd10identifier10Identifier10generateIdFNbAxaZ1ik")
- return "_D3dmd10identifier10Identifier10generateIdFNbAxaZ1im"; // size_t
+ if (s == "_D3dmd10identifier10Identifier9newSuffixFNbZ1ik")
+ return "_D3dmd10identifier10Identifier9newSuffixFNbZ1im"; // size_t
if (s == "_D3dmd6dmacro10MacroTable6expandMFKSQBi4root9outbuffer9OutBufferkKkAxaZ4nesti")
return "_D3dmd6dmacro10MacroTable6expandMFKSQBi4root9outbuffer9OutBuffermKmAxaZ4nesti";
}
@@ -151,7 +151,7 @@ void dmdInit()
version(CRuntime_Microsoft)
initFPU();
- global.params.isWindows = true;
+ global.params.targetOS = TargetOS.Windows;
global._init();
//Token._init();
Id.initialize();
@@ -238,7 +238,7 @@ void dmdSetupParams(const ref Options opts)
global = global.init;
global._init();
- global.params.isWindows = true;
+ global.params.targetOS = TargetOS.Windows;
global.params.errorLimit = 0;
global.params.color = false;
global.params.link = true;
@@ -403,7 +403,7 @@ void dmdReinit()
void addDefaultVersionIdentifiers(const ref Param params)
{
VersionCondition.addPredefinedGlobalIdent("DigitalMars");
- if (params.isWindows)
+ if (params.targetOS == TargetOS.Windows)
{
VersionCondition.addPredefinedGlobalIdent("Windows");
if (global.params.mscoff)
@@ -417,7 +417,7 @@ void addDefaultVersionIdentifiers(const ref Param params)
VersionCondition.addPredefinedGlobalIdent("CppRuntime_DigitalMars");
}
}
- else if (params.isLinux)
+ else if (params.targetOS == TargetOS.linux)
{
VersionCondition.addPredefinedGlobalIdent("Posix");
VersionCondition.addPredefinedGlobalIdent("linux");
@@ -425,7 +425,7 @@ void addDefaultVersionIdentifiers(const ref Param params)
VersionCondition.addPredefinedGlobalIdent("CRuntime_Glibc");
VersionCondition.addPredefinedGlobalIdent("CppRuntime_Gcc");
}
- else if (params.isOSX)
+ else if (params.targetOS == TargetOS.OSX)
{
VersionCondition.addPredefinedGlobalIdent("Posix");
VersionCondition.addPredefinedGlobalIdent("OSX");
@@ -433,28 +433,28 @@ void addDefaultVersionIdentifiers(const ref Param params)
// For legacy compatibility
VersionCondition.addPredefinedGlobalIdent("darwin");
}
- else if (params.isFreeBSD)
+ else if (params.targetOS == TargetOS.FreeBSD)
{
VersionCondition.addPredefinedGlobalIdent("Posix");
VersionCondition.addPredefinedGlobalIdent("FreeBSD");
VersionCondition.addPredefinedGlobalIdent("ELFv1");
VersionCondition.addPredefinedGlobalIdent("CppRuntime_Clang");
}
- else if (params.isOpenBSD)
+ else if (params.targetOS == TargetOS.OpenBSD)
{
VersionCondition.addPredefinedGlobalIdent("Posix");
VersionCondition.addPredefinedGlobalIdent("OpenBSD");
VersionCondition.addPredefinedGlobalIdent("ELFv1");
VersionCondition.addPredefinedGlobalIdent("CppRuntime_Gcc");
}
- else if (params.isDragonFlyBSD)
+ else if (params.targetOS == TargetOS.DragonFlyBSD)
{
VersionCondition.addPredefinedGlobalIdent("Posix");
VersionCondition.addPredefinedGlobalIdent("DragonFlyBSD");
VersionCondition.addPredefinedGlobalIdent("ELFv1");
VersionCondition.addPredefinedGlobalIdent("CppRuntime_Gcc");
}
- else if (params.isSolaris)
+ else if (params.targetOS == TargetOS.Solaris)
{
VersionCondition.addPredefinedGlobalIdent("Posix");
VersionCondition.addPredefinedGlobalIdent("Solaris");
@@ -482,7 +482,7 @@ void addDefaultVersionIdentifiers(const ref Param params)
{
VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86_64");
VersionCondition.addPredefinedGlobalIdent("X86_64");
- if (params.isWindows)
+ if (params.targetOS == TargetOS.Windows)
{
VersionCondition.addPredefinedGlobalIdent("Win64");
}
@@ -492,7 +492,7 @@ void addDefaultVersionIdentifiers(const ref Param params)
VersionCondition.addPredefinedGlobalIdent("D_InlineAsm"); //legacy
VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86");
VersionCondition.addPredefinedGlobalIdent("X86");
- if (params.isWindows)
+ if (params.targetOS == TargetOS.Windows)
{
VersionCondition.addPredefinedGlobalIdent("Win32");
}
diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d
index afbe5209..4a6f129a 100644
--- a/vdc/dmdserver/dmdserver.d
+++ b/vdc/dmdserver/dmdserver.d
@@ -823,6 +823,43 @@ class DMDServer : ComObject, IVDServer
return S_OK;
}
+ override HRESULT GetParameterStorageLocs(in BSTR filename, VARIANT* locs)
+ {
+ // array of pairs of DWORD
+ string fname = makeFilenameCanonical(to_string(filename), null);
+
+ ModuleData* md;
+ synchronized(gErrorSync)
+ {
+ md = findModule(fname, false);
+ if (!md || !md.analyzedModule)
+ return S_FALSE;
+ }
+
+ auto stcLoc = findParameterStorageClass(md.analyzedModule);
+
+ SAFEARRAY *sa = SafeArrayCreateVector(VT_INT, 0, 3 * cast(ULONG) stcLoc.length);
+ if(!sa)
+ return E_OUTOFMEMORY;
+
+ for(LONG index = 0; index < stcLoc.length; index++)
+ {
+ LONG idx = index * 3;
+ LONG value = stcLoc[index].type;
+ SafeArrayPutElement(sa, &idx, &value);
+ idx++;
+ value = stcLoc[index].line;
+ SafeArrayPutElement(sa, &idx, &value);
+ idx++;
+ value = stcLoc[index].col - 1;
+ SafeArrayPutElement(sa, &idx, &value);
+ }
+
+ locs.vt = VT_ARRAY | VT_INT;
+ locs.parray = sa;
+ return S_OK;
+ }
+
///////////////////////////////////////////////////////////////
// create our own task pool to be able to destroy it (it keeps a the
// arguments to the last task, so they are never collected)
@@ -1120,6 +1157,15 @@ string findIdentifierTypesResultToString(FindIdentifierTypesResult res)
return s;
}
+////////////////////////////////////////////////////////////////
+void dummy_instantiation_of_cas()
+{
+ // workaround missing symbol starting with dmd 2.093
+ import core.atomic;
+ LONG Target, old, Value;
+ cas( cast(shared(LONG)*)Target, old, Value );
+}
+
////////////////////////////////////////////////////////////////
extern(C) int _CrtDumpMemoryLeaks();
diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj
index dc8916c2..79c98da4 100644
--- a/vdc/dmdserver/dmdserver.visualdproj
+++ b/vdc/dmdserver/dmdserver.visualdproj
@@ -562,7 +562,7 @@
0
c:\l\d\dmd2\windows\bin\dmd.exe
dmd\src ..\..
- dmd dmd\res
+ dmd dmd\src\dmd\res
..\..\bin\$(ConfigurationName)
$(OutDir)\$(PlatformName)\$(ProjectName)
@@ -1749,7 +1749,9 @@
-
+
+
+
diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d
index 6c54f6cd..2ac3cc38 100644
--- a/vdc/dmdserver/semanalysis.d
+++ b/vdc/dmdserver/semanalysis.d
@@ -1774,6 +1774,35 @@ void do_unittests()
// TODO: checkTip(m, 3, 18, "(enum) `tok.TOK`");
checkTip(m, 5, 19, "(constant global) `const(uint) shell.VSITEMID_NIL`");
+
+ ///////////////////////////////////////////////////////////
+ // parameter storage class
+ lastContext = null;
+ filename = "source.d";
+ source = q{
+ void funIn(in int p) {}
+ void funRef(ref int p) {}
+ void funOut(out int p) {}
+ void funLazy(lazy int p) {} // Line 5
+
+ void foo(int[] arr)
+ {
+ int x;
+ funIn(x); // Line 10
+ funRef(x);
+ funOut(x);
+ funLazy(x);
+ funRef(arr[3]);
+ }
+ };
+ m = checkErrors(source, "");
+
+ auto stcpos = findParameterStorageClass(m);
+ assert_equal(stcpos.length, 4);
+ assert_equal(stcpos[0], ParameterStorageClassPos(0, 11, 11));
+ assert_equal(stcpos[1], ParameterStorageClassPos(1, 12, 11));
+ assert_equal(stcpos[2], ParameterStorageClassPos(2, 13, 12));
+ assert_equal(stcpos[3], ParameterStorageClassPos(0, 14, 11));
}
unittest
@@ -1867,7 +1896,8 @@ unittest
opts.msvcrt = true;
opts.warnings = true;
opts.importDirs = guessImportPaths() ~ srcdir ~ dirName(dirName(thisdir));
- opts.stringImportDirs ~= srcdir ~ "/dmd/res";
+ opts.stringImportDirs ~= srcdir ~ "/dmd/res"; // for default_ddoc_theme.ddoc
+ opts.stringImportDirs ~= srcdir ~ "/.."; // for VERSION
opts.versionIds ~= "MARS";
//opts.versionIds ~= "NoBackend";
diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d
index 34d918e0..7db20e48 100644
--- a/vdc/dmdserver/semvisitor.d
+++ b/vdc/dmdserver/semvisitor.d
@@ -341,7 +341,7 @@ extern(C++) class ASTVisitor : StoppableVisitor
// function declaration only
if (auto tf = decl.type ? decl.type.isTypeFunction() : null)
{
- if (tf.parameterList && tf.parameterList.parameters)
+ if (tf.parameterList.parameters)
foreach(i, p; *tf.parameterList.parameters)
if (!stop)
{
@@ -1135,7 +1135,7 @@ TipData tipForDeclaration(Declaration decl)
if (auto td = fntype && decl.parent ? decl.parent.isTemplateDeclaration() : null)
functionToBufferFull(fntype, &buf, decl.getIdent(), &hgs, td);
else if (fntype)
- functionToBufferWithIdent(fntype, &buf, decl.toPrettyChars(true), &hgs);
+ functionToBufferWithIdent(fntype, &buf, decl.toPrettyChars(true), &hgs, func.isStatic);
else
buf.writestring(decl.toPrettyChars(true));
auto res = buf.extractSlice(); // take ownership
@@ -1875,6 +1875,88 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod)
return itv.idTypes;
}
+////////////////////////////////////////////////////////////////////////////////
+struct ParameterStorageClassPos
+{
+ int type; // ref, out, lazy
+ int line;
+ int col;
+}
+
+ParameterStorageClassPos[] findParameterStorageClass(Module mod)
+{
+ extern(C++) class ParameterStorageClassVisitor : ASTVisitor
+ {
+ ParameterStorageClassPos[] stcPos;
+ const(char)* filename;
+
+ alias visit = ASTVisitor.visit;
+
+ final void addParamPos(int type, int line, int col)
+ {
+ auto psp = ParameterStorageClassPos(type, line, col);
+ stcPos ~= psp;
+ }
+ final void addParamPos(int type, Expression expr)
+ {
+ if (expr.loc.filename is filename)
+ addParamPos(type, expr.loc.linnum, expr.loc.charnum);
+ }
+ final void addLazyParamPos(int type, Expression expr)
+ {
+ if (!expr.loc.filename)
+ // drill into generated function for lazy parameter
+ if (expr.op == TOK.function_)
+ if (auto fd = (cast(FuncExp)expr).fd)
+ if (fd.fbody)
+ if (auto cs = fd.fbody.isCompoundStatement())
+ if (cs.statements && cs.statements.length)
+ if (auto rs = (*cs.statements)[0].isReturnStatement())
+ expr = rs.exp;
+
+ if (expr.loc.filename is filename)
+ addParamPos(type, expr.loc.linnum, expr.loc.charnum);
+ }
+
+ override void visit(CallExp expr)
+ {
+ if (expr.arguments && expr.arguments.length)
+ {
+ if (auto tf = expr.f ? expr.f.type.isTypeFunction() : null)
+ {
+ if (auto params = tf.parameterList.parameters)
+ {
+ size_t cnt = min(expr.arguments.length, params.length);
+ for (size_t p = 0; p < cnt; p++)
+ {
+ auto stc = (*params)[p].storageClass;
+ if (stc & STC.ref_)
+ {
+ if (stc & (STC.in_ | STC.const_))
+ continue;
+ if((*params)[p].type && !(*params)[p].type.isMutable())
+ continue;
+ addParamPos(0, (*expr.arguments)[p]);
+ }
+ else if (stc & STC.out_)
+ addParamPos(1, (*expr.arguments)[p]);
+ else if (stc & STC.lazy_)
+ addLazyParamPos(2, (*expr.arguments)[p]);
+ }
+ }
+ }
+ }
+ super.visit(expr);
+ }
+ }
+
+ scope psv = new ParameterStorageClassVisitor;
+ psv.filename = mod.srcfile.toChars();
+ mod.accept(psv);
+
+ return psv.stcPos;
+}
+
////////////////////////////////////////////////////////////////////////////////
struct Reference
{
diff --git a/vdc/ivdserver.d b/vdc/ivdserver.d
index 54b4d85e..13ee55ab 100644
--- a/vdc/ivdserver.d
+++ b/vdc/ivdserver.d
@@ -149,7 +149,7 @@ public:
// this method is called once after GetParseErrors returned successfully
HRESULT GetBinaryIsInLocations(in BSTR filename, VARIANT* locs);
- // return the locations where "in" and "is" are used as binary operators
+ // return the document outline, i.e. a simple description of the AST
//
// filename: file name
//
@@ -233,6 +233,15 @@ public:
//
// return S_FALSE as long as the parsing is still running
HRESULT GetCommentTasks(in BSTR filename, BSTR* tasks);
+
+ // return the locations of call arguments with parameter storage class ref, out or lazy
+ //
+ // filename: file name
+ // locs: an array of triplets of DWORDs type,line,index that gives the text
+ // location of the argument expression. type is 0/1/2 for ref/out/lazy
+ //
+ // this method is called once after GetParseErrors returned successfully
+ HRESULT GetParameterStorageLocs(in BSTR filename, VARIANT* locs);
}
///////////////////////////////////////////////////////////////////////
@@ -293,3 +302,17 @@ enum TypeReferenceKind : uint
DebugIdentifier,
VersionIdentifier,
}
+
+enum ParameterStorageClass
+{
+ Ref,
+ Out,
+ Lazy
+}
+
+struct ParameterStorageLoc
+{
+ int type;
+ int line;
+ int col;
+}
diff --git a/vdc/ivdserver.idl b/vdc/ivdserver.idl
index 5bd5ea44..c45be43f 100644
--- a/vdc/ivdserver.idl
+++ b/vdc/ivdserver.idl
@@ -39,5 +39,6 @@ interface IVDServer : IUnknown
HRESULT GetReferencesResult([out,retval] BSTR* stringList);
HRESULT ConfigureCommentTasks([in] BSTR tasks);
HRESULT GetCommentTasks([in] BSTR filename, [out,retval] BSTR* tasks);
+ HRESULT GetParameterStorageLocs([in] BSTR filename, [out, retval] VARIANT* locs); // array of triplets of DWORD
};
diff --git a/vdc/vdserver.d b/vdc/vdserver.d
index 32756850..07e4c506 100644
--- a/vdc/vdserver.d
+++ b/vdc/vdserver.d
@@ -644,6 +644,11 @@ class VDServer : ComObject, IVDServer
return E_NOTIMPL;
}
+ override HRESULT GetParameterStorageLocs(in BSTR filename, VARIANT* locs)
+ {
+ return E_NOTIMPL;
+ }
+
///////////////////////////////////////////////////////////////
// create our own task pool to be able to destroy it (it keeps a the
// arguments to the last task, so they are never collected)
diff --git a/vdextensions/ParamStorageAdornmentTagger.cs b/vdextensions/ParamStorageAdornmentTagger.cs
new file mode 100644
index 00000000..1dadb0ff
--- /dev/null
+++ b/vdextensions/ParamStorageAdornmentTagger.cs
@@ -0,0 +1,623 @@
+// adapted from
+// https://github.com/microsoft/VSSDK-Extensibility-Samples/blob/master/Intra-text_Adornment/C%23/Support/IntraTextAdornmentTagger.cs
+//***************************************************************************
+
+using System;
+using System.ComponentModel.Composition;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Media;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Globalization;
+using System.Runtime.InteropServices; // DllImport
+
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Classification;
+using Microsoft.VisualStudio.Text.Editor;
+using Microsoft.VisualStudio.Text.Tagging;
+using Microsoft.VisualStudio.Utilities;
+using Microsoft.VisualStudio.TextManager.Interop;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+
+namespace vdext15
+{
+ ///
+ /// Helper class for interspersing adornments into text.
+ ///
+ ///
+ /// To avoid an issue around intra-text adornment support and its interaction with text buffer changes,
+ /// this tagger reacts to text and paramStorage tag changes with a delay. It waits to send out its own TagsChanged
+ /// event until the WPF Dispatcher is running again and it takes care to report adornments
+ /// that are consistent with the latest sent TagsChanged event by storing that particular snapshot
+ /// and using it to query for the data tags.
+ ///
+ internal abstract class IntraTextAdornmentTagger
+ : ITagger
+ where TAdornment : UIElement
+ {
+ protected readonly IWpfTextView view;
+ protected Dictionary adornmentCache = new Dictionary();
+ protected ITextSnapshot snapshot { get; private set; }
+ private readonly List invalidatedSpans = new List();
+
+ protected IntraTextAdornmentTagger(IWpfTextView view)
+ {
+ this.view = view;
+ snapshot = view.TextBuffer.CurrentSnapshot;
+
+ this.view.LayoutChanged += HandleLayoutChanged;
+ this.view.TextBuffer.Changed += HandleBufferChanged;
+ }
+
+ /// The span of text that this adornment will elide.
+ /// Adornment corresponding to given data. May be null.
+ protected abstract TAdornment CreateAdornment(TData data, SnapshotSpan span);
+
+ /// True if the adornment was updated and should be kept. False to have the adornment removed from the view.
+ protected abstract bool UpdateAdornment(TAdornment adornment, TData data);
+
+ /// Spans to provide adornment data for. These spans do not necessarily correspond to text lines.
+ ///
+ /// If adornments need to be updated, call or .
+ /// This will, indirectly, cause to be called.
+ ///
+ ///
+ /// A sequence of:
+ /// * adornment data for each adornment to be displayed
+ /// * the span of text that should be elided for that adornment (zero length spans are acceptable)
+ /// * and affinity of the adornment (this should be null if and only if the elided span has a length greater than zero)
+ ///
+ protected abstract IEnumerable> GetAdornmentData(NormalizedSnapshotSpanCollection spans);
+
+ private void HandleBufferChanged(object sender, TextContentChangedEventArgs args)
+ {
+ var editedSpans = args.Changes.Select(change => new SnapshotSpan(args.After, change.NewSpan)).ToList();
+ InvalidateSpans(editedSpans);
+ }
+
+ ///
+ /// Causes intra-text adornments to be updated asynchronously.
+ ///
+ protected void InvalidateSpans(IList spans)
+ {
+ lock (invalidatedSpans)
+ {
+ bool wasEmpty = invalidatedSpans.Count == 0;
+ invalidatedSpans.AddRange(spans);
+
+ if (wasEmpty && this.invalidatedSpans.Count > 0)
+ view.VisualElement.Dispatcher.BeginInvoke(new Action(AsyncUpdate));
+ }
+ }
+
+ private void AsyncUpdate()
+ {
+ // Store the snapshot that we're now current with and send an event
+ // for the text that has changed.
+ if (snapshot != view.TextBuffer.CurrentSnapshot)
+ {
+ snapshot = view.TextBuffer.CurrentSnapshot;
+
+ Dictionary translatedAdornmentCache = new Dictionary();
+
+ foreach (var keyValuePair in adornmentCache)
+ translatedAdornmentCache.Add(keyValuePair.Key.TranslateTo(snapshot, SpanTrackingMode.EdgeExclusive), keyValuePair.Value);
+
+ adornmentCache = translatedAdornmentCache;
+ }
+
+ List translatedSpans;
+ lock (invalidatedSpans)
+ {
+ translatedSpans = invalidatedSpans.Select(s => s.TranslateTo(snapshot, SpanTrackingMode.EdgeInclusive)).ToList();
+ invalidatedSpans.Clear();
+ }
+
+ if (translatedSpans.Count == 0)
+ return;
+
+ var start = translatedSpans.Select(span => span.Start).Min();
+ var end = translatedSpans.Select(span => span.End).Max();
+
+ RaiseTagsChanged(new SnapshotSpan(start, end));
+ }
+
+ ///
+ /// Causes intra-text adornments to be updated synchronously.
+ ///
+ protected void RaiseTagsChanged(SnapshotSpan span)
+ {
+ var handler = TagsChanged;
+ if (handler != null)
+ handler(this, new SnapshotSpanEventArgs(span));
+ }
+
+ private void HandleLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
+ {
+ SnapshotSpan visibleSpan = view.TextViewLines.FormattedSpan;
+
+ // Filter out the adornments that are no longer visible.
+ List toRemove = new List(
+ from keyValuePair
+ in adornmentCache
+ where !keyValuePair.Key.TranslateTo(visibleSpan.Snapshot, SpanTrackingMode.EdgeExclusive).IntersectsWith(visibleSpan)
+ select keyValuePair.Key);
+
+ foreach (var span in toRemove)
+ adornmentCache.Remove(span);
+ }
+
+
+ // Produces tags on the snapshot that the tag consumer asked for.
+ public virtual IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans)
+ {
+ if (spans == null || spans.Count == 0)
+ yield break;
+
+ // Translate the request to the snapshot that this tagger is current with.
+
+ ITextSnapshot requestedSnapshot = spans[0].Snapshot;
+
+ var translatedSpans = new NormalizedSnapshotSpanCollection(spans.Select(span => span.TranslateTo(snapshot, SpanTrackingMode.EdgeExclusive)));
+
+ // Grab the adornments.
+ foreach (var tagSpan in GetAdornmentTagsOnSnapshot(translatedSpans))
+ {
+ // Translate each adornment to the snapshot that the tagger was asked about.
+ SnapshotSpan span = tagSpan.Span.TranslateTo(requestedSnapshot, SpanTrackingMode.EdgeExclusive);
+
+ IntraTextAdornmentTag tag = new IntraTextAdornmentTag(tagSpan.Tag.Adornment, tagSpan.Tag.RemovalCallback, tagSpan.Tag.Affinity);
+ yield return new TagSpan(span, tag);
+ }
+ }
+
+ // Produces tags on the snapshot that this tagger is current with.
+ private IEnumerable> GetAdornmentTagsOnSnapshot(NormalizedSnapshotSpanCollection spans)
+ {
+ if (spans.Count == 0)
+ yield break;
+
+ ITextSnapshot snapshot = spans[0].Snapshot;
+
+ System.Diagnostics.Debug.Assert(snapshot == this.snapshot);
+
+ // Since WPF UI objects have state (like mouse hover or animation) and are relatively expensive to create and lay out,
+ // this code tries to reuse controls as much as possible.
+ // The controls are stored in this.adornmentCache between the calls.
+
+ // Mark which adornments fall inside the requested spans with Keep=false
+ // so that they can be removed from the cache if they no longer correspond to data tags.
+ HashSet toRemove = new HashSet();
+ foreach (var ar in adornmentCache)
+ if (spans.IntersectsWith(new NormalizedSnapshotSpanCollection(ar.Key)))
+ toRemove.Add(ar.Key);
+
+ foreach (var spanDataPair in GetAdornmentData(spans).Distinct(new Comparer()))
+ {
+ // Look up the corresponding adornment or create one if it's new.
+ TAdornment adornment;
+ SnapshotSpan snapshotSpan = spanDataPair.Item1;
+ PositionAffinity? affinity = spanDataPair.Item2;
+ TData adornmentData = spanDataPair.Item3;
+ if (adornmentCache.TryGetValue(snapshotSpan, out adornment))
+ {
+ if (UpdateAdornment(adornment, adornmentData))
+ toRemove.Remove(snapshotSpan);
+ }
+ else
+ {
+ adornment = CreateAdornment(adornmentData, snapshotSpan);
+
+ if (adornment == null)
+ continue;
+
+ // Get the adornment to measure itself. Its DesiredSize property is used to determine
+ // how much space to leave between text for this adornment.
+ // Note: If the size of the adornment changes, the line will be reformatted to accommodate it.
+ // Note: Some adornments may change size when added to the view's visual tree due to inherited
+ // dependency properties that affect layout. Such options can include SnapsToDevicePixels,
+ // UseLayoutRounding, TextRenderingMode, TextHintingMode, and TextFormattingMode. Making sure
+ // that these properties on the adornment match the view's values before calling Measure here
+ // can help avoid the size change and the resulting unnecessary re-format.
+ adornment.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
+
+ adornmentCache.Add(snapshotSpan, adornment);
+ }
+ var tag = new IntraTextAdornmentTag(adornment, null, null, 4, null, null, affinity);
+ yield return new TagSpan(snapshotSpan, tag);
+ }
+
+ foreach (var snapshotSpan in toRemove)
+ adornmentCache.Remove(snapshotSpan);
+ }
+
+ public event EventHandler TagsChanged;
+
+ private class Comparer : IEqualityComparer>
+ {
+ public bool Equals(Tuple x, Tuple y)
+ {
+ if (x == null && y == null)
+ return true;
+ if (x == null || y == null)
+ return false;
+ return x.Item1.Equals(y.Item1);
+ }
+
+ public int GetHashCode(Tuple obj)
+ {
+ return obj.Item1.GetHashCode();
+ }
+ }
+
+ }
+
+ /// Provides paramStorage adornments in place of paramStorage constants.
+ internal sealed class ParamStorageAdornmentTagger
+ : IntraTextAdornmentTagger
+ {
+ [DllImport("visuald.dll")]
+ public static extern bool GetParameterStorageLocs(string fname,
+ [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_INT)] out int[] locs,
+ out bool pending, out int changeCount);
+
+ public static bool GetParameterStorageLocations(string fname, out int[] data, out bool pending, out int changeCount)
+ {
+ try
+ {
+ // grab triplets of (type, line, col)
+ if (!GetParameterStorageLocs(fname, out data, out pending, out changeCount))
+ return false;
+ return true;
+ }
+ catch
+ {
+ data = new int[0];
+ pending = true;
+ changeCount = -1;
+ return false;
+ }
+ }
+
+ public SolidColorBrush storageColor = new SolidColorBrush(Colors.Green);
+ IEditorFormatMap formatMap;
+
+ private static SolidColorBrush toBrush(object obj)
+ {
+ if (obj == null)
+ return new SolidColorBrush(Colors.Red);
+ return (SolidColorBrush)obj;
+ }
+
+ public void UpdateColors()
+ {
+ try
+ {
+ ResourceDictionary rd = formatMap.GetProperties("ParamStorageClassificationFormatVisualD");
+ storageColor = toBrush(rd[EditorFormatDefinition.ForegroundBrushId]);
+
+ foreach (var tag in adornmentCache)
+ tag.Value.Foreground = storageColor;
+ }
+ catch { }
+ }
+
+ internal static ITagger GetTagger(IWpfTextView view, IEditorFormatMap formatMap,
+ Lazy> paramStorageTagger)
+ {
+ return view.Properties.GetOrCreateSingletonProperty(
+ () => new ParamStorageAdornmentTagger(view, formatMap, paramStorageTagger.Value));
+ }
+
+ private ITagAggregator paramStorageTagger;
+
+ private ParamStorageAdornmentTagger(IWpfTextView view, IEditorFormatMap formatMap,
+ ITagAggregator paramStorageTagger)
+ : base(view)
+ {
+ this.paramStorageTagger = paramStorageTagger;
+ this.formatMap = formatMap;
+ this.formatMap.FormatMappingChanged += (sender, args) => UpdateColors();
+ UpdateColors();
+ }
+
+ public void Dispose()
+ {
+ paramStorageTagger.Dispose();
+
+ view.Properties.RemoveProperty(typeof(ParamStorageAdornmentTagger));
+ }
+
+ // To produce adornments that don't obscure the text, the adornment tags
+ // should have zero length spans. Overriding this method allows control
+ // over the tag spans.
+ protected override IEnumerable>
+ GetAdornmentData(NormalizedSnapshotSpanCollection spans)
+ {
+ if (spans.Count == 0)
+ yield break;
+
+ ITextSnapshot snapshot = spans[0].Snapshot;
+
+ var paramStorageTags = paramStorageTagger.GetTags(spans);
+
+ foreach (IMappingTagSpan dataTagSpan in paramStorageTags)
+ {
+ NormalizedSnapshotSpanCollection paramStorageTagSpans = dataTagSpan.Span.GetSpans(snapshot);
+
+ // Ignore data tags that are split by projection.
+ // This is theoretically possible but unlikely in current scenarios.
+ if (paramStorageTagSpans.Count != 1)
+ continue;
+
+ SnapshotSpan adornmentSpan = new SnapshotSpan(paramStorageTagSpans[0].End, 0);
+
+ yield return Tuple.Create(adornmentSpan, (PositionAffinity?)PositionAffinity.Predecessor, dataTagSpan.Tag);
+ }
+ }
+
+ protected override ParamStorageAdornment CreateAdornment(ParamStorageTag dataTag, SnapshotSpan span)
+ {
+ return new ParamStorageAdornment(dataTag, storageColor);
+ }
+
+ protected override bool UpdateAdornment(ParamStorageAdornment adornment, ParamStorageTag dataTag)
+ {
+ adornment.Update(dataTag);
+ return true;
+ }
+ }
+
+ ///
+ /// Determines which spans of text likely refer to paramStorage values.
+ ///
+ ///
+ ///
+ /// This is a data-only component. The tagging system is a good fit for presenting data-about-text.
+ /// The takes paramStorage tags produced by this tagger and creates corresponding UI for this data.
+ ///
+ ///
+ internal class ParamStorageTagger : ITagger
+ {
+ private string _fileName;
+ int[] _stcLocs;
+ ITextSnapshot _pendingSnapshot;
+ ITextSnapshot _currentSnapshot;
+ int _changeCount;
+
+ public ParamStorageTagger(ITextBuffer buffer)
+ {
+ IVsTextBuffer vsbuffer;
+ buffer.Properties.TryGetProperty(typeof(IVsTextBuffer), out vsbuffer);
+ _fileName = "";
+ if (vsbuffer != null)
+ {
+ IPersistFileFormat fileFormat = vsbuffer as IPersistFileFormat;
+ if (fileFormat != null)
+ {
+ UInt32 format;
+ fileFormat.GetCurFile(out _fileName, out format);
+ }
+ }
+
+ buffer.Changed += (sender, args) => HandleBufferChanged(args);
+ _pendingSnapshot = _currentSnapshot = buffer.CurrentSnapshot;
+ }
+
+ #region ITagger implementation
+
+ public void UpdateStcSpans()
+ {
+ int[] stcLocs;
+ bool pending;
+ int changeCount;
+ ParamStorageAdornmentTagger.GetParameterStorageLocations(_fileName, out stcLocs, out pending, out changeCount);
+ if (pending && _stcLocs != null)
+ return;
+ if (_pendingSnapshot == null && _changeCount == changeCount)
+ return;
+
+ if (stcLocs != null)
+ {
+ int j = 0;
+ for (int i = 0; i + 2 < stcLocs.Length; i += 3)
+ {
+ if (stcLocs[i] >= 0 && stcLocs[i] <= 2)
+ {
+ if (stcLocs[i + 1] >= _currentSnapshot.LineCount)
+ continue;
+ var line = _currentSnapshot.GetLineFromLineNumber(stcLocs[i + 1] - 1);
+ stcLocs[j] = stcLocs[i];
+ stcLocs[j + 1] = line.Start.Position + stcLocs[i + 2];
+ j += 2;
+ }
+ }
+ Array.Resize(ref stcLocs, j);
+ }
+ _stcLocs = stcLocs;
+ _changeCount = changeCount;
+ if (!pending)
+ _pendingSnapshot = null;
+ }
+
+ public virtual IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans)
+ {
+ UpdateStcSpans();
+
+ // Note that the spans argument can contain spans that are sub-spans of lines or intersect multiple lines.
+ if (_stcLocs != null)
+ for (int i = 0; i + 1 < _stcLocs.Length; i += 2)
+ {
+ // need to compare manually as info is on different snapshots
+ int pos = _stcLocs[i + 1];
+ bool intersects = false;
+ foreach (var span in spans)
+ if (span.Start.Position <= pos && pos <= span.End.Position)
+ intersects = true;
+
+ if (intersects)
+ {
+ var point = new SnapshotPoint(spans.First().Snapshot, pos);
+ SnapshotSpan span = new SnapshotSpan(point, 1);
+ yield return new TagSpan(span, new ParamStorageTag(_stcLocs[i]));
+ }
+ }
+ }
+ public event EventHandler TagsChanged;
+
+ #endregion
+
+ ///
+ /// Handle buffer changes. The default implementation expands changes to full lines and sends out
+ /// a event for these lines.
+ ///
+ /// The buffer change arguments.
+ protected virtual void HandleBufferChanged(TextContentChangedEventArgs args)
+ {
+ if (args.Changes.Count == 0)
+ return;
+
+ var temp = TagsChanged;
+ if (temp == null)
+ return;
+
+ // adapt stcSpans, so any unmodified tags get moved with changes
+ if (_stcLocs != null)
+ foreach (var change in args.Changes)
+ for (int i = 0; i + 1 < _stcLocs.Length; i += 2)
+ if (_stcLocs[i + 1] >= change.OldPosition)
+ _stcLocs[i + 1] += change.Delta;
+
+ // Combine all changes into a single span so that
+ // the ITagger<>.TagsChanged event can be raised just once for a compound edit
+ // with many parts.
+ _pendingSnapshot = _currentSnapshot = args.After;
+
+ int start = args.Changes[0].NewPosition;
+ int end = args.Changes[args.Changes.Count - 1].NewEnd;
+
+ SnapshotSpan totalAffectedSpan = new SnapshotSpan(
+ _currentSnapshot.GetLineFromPosition(start).Start,
+ _currentSnapshot.GetLineFromPosition(end).End);
+
+ temp(this, new SnapshotSpanEventArgs(totalAffectedSpan));
+ }
+ }
+
+ ///
+ /// Data tag indicating that the tagged text represents a paramStorage.
+ ///
+ ///
+ /// Note that this tag has nothing directly to do with adornments or other UI.
+ /// This sample's adornments will be produced based on the data provided in these tags.
+ /// This separation provides the potential for other extensions to consume paramStorage tags
+ /// and provide alternative UI or other derived functionality over this data.
+ ///
+ internal class ParamStorageTag : ITag
+ {
+ internal ParamStorageTag(int type)
+ {
+ Type = type;
+ }
+
+ internal readonly int Type;
+ }
+
+ internal sealed class ParamStorageAdornment : TextBlock //Button
+ {
+ internal ParamStorageAdornment(ParamStorageTag paramStorageTag, Brush color)
+ {
+ //Text = "ref";
+ FontSize = FontSize * 0.75;
+
+ //Background = Brushes.AntiqueWhite;
+ Foreground = color;
+ TextAlignment = TextAlignment.Center;
+
+ Update(paramStorageTag);
+ }
+
+ internal void Update(ParamStorageTag paramStorageTag)
+ {
+ var txt = paramStorageTag.Type == 0 ? "ref " : paramStorageTag.Type == 1 ? "out " : "lazy ";
+ Inlines.Clear();
+ Inlines.Add(new Italic(new Run(txt)));
+ }
+ }
+
+//#if STC_ADORNMENT
+ [Export(typeof(ITaggerProvider))]
+ [ContentType("d")]
+ [TagType(typeof(ParamStorageTag))]
+ internal sealed class ParamStorageTaggerProvider : ITaggerProvider
+ {
+ public ITagger CreateTagger(ITextBuffer buffer) where T : ITag
+ {
+ if (buffer == null)
+ throw new ArgumentNullException("buffer");
+
+ return buffer.Properties.GetOrCreateSingletonProperty(() => new ParamStorageTagger(buffer)) as ITagger;
+ }
+ }
+
+ [Export(typeof(IViewTaggerProvider))]
+ [ContentType("d")]
+ [ContentType("projection")]
+ [TagType(typeof(IntraTextAdornmentTag))]
+ internal sealed class ParamStorageAdornmentTaggerProvider : IViewTaggerProvider
+ {
+ [Import]
+ internal IBufferTagAggregatorFactoryService BufferTagAggregatorFactoryService = null;
+
+ [Import]
+ internal IClassificationTypeRegistryService ClassificationRegistry = null;
+
+ [Import]
+ internal IEditorFormatMapService FormatMapService = null;
+
+ [Export(typeof(ClassificationTypeDefinition))]
+ [Name("ParamStorageClassificationVisualD")]
+ internal static ClassificationTypeDefinition paramStorageClassificationType = null;
+
+ private static IClassificationType s_paramStorageClassification;
+
+ public ITagger CreateTagger(ITextView textView, ITextBuffer buffer) where T : ITag
+ {
+ if (s_paramStorageClassification == null)
+ s_paramStorageClassification = ClassificationRegistry.GetClassificationType("ParamStorageClassificationVisualD");
+
+ if (textView == null)
+ throw new ArgumentNullException("textView");
+
+ if (buffer == null)
+ throw new ArgumentNullException("buffer");
+
+ if (buffer != textView.TextBuffer)
+ return null;
+
+ return ParamStorageAdornmentTagger.GetTagger(
+ (IWpfTextView)textView, FormatMapService.GetEditorFormatMap(textView),
+ new Lazy>(
+ () => BufferTagAggregatorFactoryService.CreateTagAggregator(textView.TextBuffer)))
+ as ITagger;
+ }
+ }
+
+ [Export(typeof(EditorFormatDefinition))]
+ [ClassificationType(ClassificationTypeNames = "ParamStorageClassificationVisualD")]
+ [Name("ParamStorageClassificationFormatVisualD")]
+ [UserVisible(true)]
+ [Order(After = Priority.High)]
+ internal sealed class ParamStorageFormatDefinition : ClassificationFormatDefinition
+ {
+ public ParamStorageFormatDefinition()
+ {
+ this.DisplayName = "Visual D Parameter Storage";
+ this.ForegroundColor = System.Windows.Media.Colors.LightSkyBlue;
+ }
+ }
+//#endif
+}
diff --git a/vdextensions/gotodef.cs b/vdextensions/gotodef.cs
index 7680f119..12b44b38 100644
--- a/vdextensions/gotodef.cs
+++ b/vdextensions/gotodef.cs
@@ -166,16 +166,14 @@ public override void PreviewKeyUp(KeyEventArgs args)
[Order(Before = "WordSelection")]
internal sealed class GoToDefMouseHandlerProvider : IMouseProcessorProvider
{
-#pragma warning disable 649 // Field is never assigned to, and will always have its default value null
-
[Import]
- private IClassifierAggregatorService _aggregatorFactory;
+ private IClassifierAggregatorService _aggregatorFactory = null;
[Import]
- private ITextStructureNavigatorSelectorService _navigatorService;
+ private ITextStructureNavigatorSelectorService _navigatorService = null;
[Import]
- private SVsServiceProvider _globalServiceProvider;
+ private SVsServiceProvider _globalServiceProvider = null;
public IMouseProcessor GetAssociatedProcessor(IWpfTextView view)
{
@@ -224,11 +222,11 @@ private IVsUIShell GetVsUIShell()
#endregion
}
-///
-/// Handle ctrl+click on valid elements to send GoToDefinition to the shell. Also handle mouse moves
-/// (when control is pressed) to highlight references for which GoToDefinition will (likely) be valid.
-///
-internal sealed class GoToDefMouseHandler : MouseProcessorBase
+ ///
+ /// Handle ctrl+click on valid elements to send GoToDefinition to the shell. Also handle mouse moves
+ /// (when control is pressed) to highlight references for which GoToDefinition will (likely) be valid.
+ ///
+ internal sealed class GoToDefMouseHandler : MouseProcessorBase
{
private IWpfTextView _view;
private CtrlKeyState _state;
@@ -350,11 +348,11 @@ public override void PostprocessMouseUp(MouseButtonEventArgs e)
}
- #endregion
+ #endregion
- #region Private helpers
+ #region Private helpers
- private Point RelativeToView(Point position)
+ private Point RelativeToView(Point position)
{
return new Point(position.X + _view.ViewportLeft, position.Y + _view.ViewportTop);
}
@@ -467,7 +465,7 @@ private bool DispatchGoToDef()
#endregion
}
- #region Classification type/format exports
+#region Classification type/format exports
[Export(typeof(EditorFormatDefinition))]
[ClassificationType(ClassificationTypeNames = "UnderlineClassificationVisualD")]
@@ -484,24 +482,24 @@ public UnderlineFormatDefinition()
}
}
- #endregion
+#endregion
- #region Provider definition
+#region Provider definition
- [Export(typeof(IViewTaggerProvider))]
+ [Export(typeof(IViewTaggerProvider))]
[ContentType("text")]
[TagType(typeof(ClassificationTag))]
- internal class UnderlineClassifierProvider : IViewTaggerProvider
+ internal class UnderlineClassifierProvider : IViewTaggerProvider
{
[Import]
- internal IClassificationTypeRegistryService ClassificationRegistry;
+ internal IClassificationTypeRegistryService ClassificationRegistry = null;
//[Import]
//private SVsServiceProvider _serviceProvider;
[Export(typeof(ClassificationTypeDefinition))]
[Name("UnderlineClassificationVisualD")]
- internal static ClassificationTypeDefinition underlineClassificationType;
+ internal static ClassificationTypeDefinition underlineClassificationType = null;
private static IClassificationType s_underlineClassification;
public static UnderlineClassifier GetClassifierForView(ITextView view)
@@ -533,9 +531,9 @@ public static UnderlineClassifier GetClassifierForView(ITextView view)
}
}
- #endregion
+#endregion
- internal class UnderlineClassifier : ITagger
+ internal class UnderlineClassifier : ITagger
{
private IClassificationType _classificationType;
private ITextView _textView;
@@ -548,7 +546,7 @@ internal UnderlineClassifier(ITextView textView, IClassificationType classificat
_underlineSpan = null;
}
- #region Private helpers
+#region Private helpers
private void SendEvent(SnapshotSpan span)
{
@@ -557,9 +555,9 @@ private void SendEvent(SnapshotSpan span)
temp(this, new SnapshotSpanEventArgs(span));
}
- #endregion
+#endregion
- #region UnderlineClassification public members
+#region UnderlineClassification public members
public SnapshotSpan? CurrentUnderlineSpan { get { return _underlineSpan; } }
@@ -590,7 +588,7 @@ public void SetUnderlineSpan(SnapshotSpan? span)
}
}
- #endregion
+#endregion
public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans)
{
diff --git a/vdextensions/vdext15.csproj b/vdextensions/vdext15.csproj
index 6996da58..77e4480b 100644
--- a/vdextensions/vdext15.csproj
+++ b/vdextensions/vdext15.csproj
@@ -25,6 +25,7 @@
4
False
false
+ false
full
@@ -140,6 +141,7 @@
+
diff --git a/vdextensions/vdextensions.csproj b/vdextensions/vdextensions.csproj
index 97672944..71ace7ca 100644
--- a/vdextensions/vdextensions.csproj
+++ b/vdextensions/vdextensions.csproj
@@ -22,6 +22,7 @@
prompt
4
False
+ false
full
diff --git a/vdwizard/VisualDWizard.csproj b/vdwizard/VisualDWizard.csproj
index 2b57ff3d..482d55d1 100644
--- a/vdwizard/VisualDWizard.csproj
+++ b/vdwizard/VisualDWizard.csproj
@@ -42,6 +42,7 @@
false
False
False
+ false
pdbonly
diff --git a/visuald/dlangsvc.d b/visuald/dlangsvc.d
index bb8cea80..18da6519 100644
--- a/visuald/dlangsvc.d
+++ b/visuald/dlangsvc.d
@@ -895,6 +895,16 @@ class LanguageService : DisposingComObject,
return true;
}
+ ParameterStorageLoc[] GetParameterStorageLocs(string filename, out bool pending, out int changeCount)
+ {
+ Source src = GetSource(filename);
+ if(!src)
+ return null;
+ pending = src.mHasPendingUpdateModule || src.mModificationCountSemantic != src.mModificationCount;
+ changeCount = src.mModificationCount;
+ return src.mParameterStcLocs;
+ }
+
// QuickInfo callback from C# ///////////////////////////////////
private uint mLastTipIdleTaskScheduled;
@@ -1489,6 +1499,19 @@ class NavigationBarClient : DisposingComObject, IVsDropdownBarClient, IVsCoTaskM
size_t[] mColumn3;
int mCurrentLine;
+ bool columnLess(const ref size_t col1, const ref size_t col2)
+ {
+ auto d1 = mNodes[col1].desc;
+ auto d2 = mNodes[col2].desc;
+ bool i1 = d1.startsWith("__"); // move internal symbols to the end of the list
+ bool i2 = d2.startsWith("__");
+ if (i1 && !i2)
+ return false;
+ if (!i1 && i2)
+ return true;
+ return icmp(d1, d2) < 0;
+ }
+
void UpdateFromSource(string outline)
{
string[] lines = outline.splitLines();
@@ -1535,6 +1558,8 @@ class NavigationBarClient : DisposingComObject, IVsDropdownBarClient, IVsCoTaskM
for (size_t n = 0; n < mNodes.length; n++)
if (mNodes[n].depth <= 1)
mGlobal[cnt++] = n;
+
+ sort!((a, b) => columnLess(a, b))(mGlobal);
}
int getNodeIndex(int iCombo, int index)
@@ -1548,10 +1573,10 @@ class NavigationBarClient : DisposingComObject, IVsDropdownBarClient, IVsCoTaskM
return -1;
}
- int findGlobalIndex(int line)
+ int findLineIndex(size_t[] column, int line)
{
- for (size_t g = 0; g < mGlobal.length; g++)
- if (mNodes[mGlobal[g]].containsLine(line))
+ for (size_t g = 0; g < column.length; g++)
+ if (mNodes[column[g]].containsLine(line))
return g;
return -1;
}
@@ -1569,7 +1594,7 @@ class NavigationBarClient : DisposingComObject, IVsDropdownBarClient, IVsCoTaskM
mCurrentLine = line;
mColumn2 = null;
mColumn3 = null;
- int sel1 = findGlobalIndex(line);
+ int sel1 = findLineIndex(mGlobal, line);
int sel2 = -1;
int sel3 = -1;
if (sel1 >= 0)
@@ -1585,24 +1610,21 @@ class NavigationBarClient : DisposingComObject, IVsDropdownBarClient, IVsCoTaskM
mColumn2 ~= h;
if (mNodes[h].containsLine(line))
{
- sel2 = mColumn2.length - 1;
int hdepth = mNodes[h].depth;
for (int i = h + 1; i < mNodes.length; i++)
{
if (mNodes[i].depth <= hdepth)
break;
if (mNodes[i].depth == hdepth + 1)
- {
mColumn3 ~= i;
- if (mNodes[i].containsLine(line))
- {
- sel3 = mColumn3.length - 1;
- }
- }
}
}
}
}
+ sort!((a, b) => columnLess(a, b))(mColumn2);
+ sort!((a, b) => columnLess(a, b))(mColumn3);
+ sel2 = findLineIndex(mColumn2, line);
+ sel3 = findLineIndex(mColumn3, line);
}
if (mDropdownBar)
{
@@ -1956,6 +1978,7 @@ class Source : DisposingComObject, IVsUserDataEvents, IVsTextLinesEvents,
IdentifierType[][wstring] mIdentifierTypes;
vdc.util.TextPos[] mBinaryIsIn;
NewHiddenRegion[] mOutlineRegions;
+ ParameterStorageLoc[] mParameterStcLocs;
int mOutliningState;
int mModificationCountOutlining;
@@ -4641,13 +4664,14 @@ else
}
extern(D) void OnUpdateModule(uint request, string filename, string parseErrors, vdc.util.TextPos[] binaryIsIn,
- string tasks, string outline)
+ string tasks, string outline, ParameterStorageLoc[] parameterStcLocs)
{
mHasPendingUpdateModule = false;
if (!Package.GetGlobalOptions().showParseErrors)
parseErrors = null;
updateParseErrors(parseErrors);
mBinaryIsIn = binaryIsIn;
+ mParameterStcLocs = parameterStcLocs;
if(IVsTextColorState colorState = qi_cast!IVsTextColorState(mBuffer))
{
scope(exit) release(colorState);
diff --git a/visuald/dllmain.d b/visuald/dllmain.d
index 1b395357..2ba320b7 100644
--- a/visuald/dllmain.d
+++ b/visuald/dllmain.d
@@ -26,6 +26,7 @@ import threadaux = core.sys.windows.threadaux;
import std.conv;
import std.array;
+import sdk.win32.oleauto;
// enable precise scanning of the DATA/TLS sections (dmd 2.075+) and GC (dmd 2.085+)
pragma(msg, "DMD VERSION = ", __VERSION__);
@@ -219,3 +220,38 @@ BOOL GetTooltipResult(uint request, BSTR* btip, BSTR* bfmt, BSTR* blinks)
*blinks = allocwBSTR(links);
return rc;
}
+
+extern(Windows)
+BOOL GetParameterStorageLocs(const(char)* fname, SAFEARRAY** psa, BOOL* pPending, INT* pChangeCount)
+{
+ if (!Package.s_instance)
+ return false; // not yet loaded as a package
+
+ int changeCount;
+ bool pending;
+ string filename = to!string(fname);
+ auto stcLocs = Package.GetLanguageService().GetParameterStorageLocs(filename, pending, changeCount);
+
+ SAFEARRAY *sa = SafeArrayCreateVector(VT_INT, 0, 3 * cast(ULONG) stcLocs.length);
+ if(!sa)
+ return E_OUTOFMEMORY;
+
+ LONG idx = 0;
+ for(LONG index = 0; index < stcLocs.length; index++)
+ {
+ LONG value = stcLocs[index].type;
+ SafeArrayPutElement(sa, &idx, &value);
+ idx++;
+ value = stcLocs[index].line;
+ SafeArrayPutElement(sa, &idx, &value);
+ idx++;
+ value = stcLocs[index].col - 1;
+ SafeArrayPutElement(sa, &idx, &value);
+ idx++;
+ }
+
+ *pPending = pending;
+ *psa = sa;
+ *pChangeCount = changeCount;
+ return true;
+}
diff --git a/visuald/dpackage.d b/visuald/dpackage.d
index ea5f26ab..224b3409 100644
--- a/visuald/dpackage.d
+++ b/visuald/dpackage.d
@@ -1613,6 +1613,7 @@ class GlobalOptions
bool useDParser;
bool mixinAnalysis;
bool UFCSExpansions;
+ bool showParamStorage;
byte sortExpMode; // 0: alphabetically, 1: by type, 2: by declaration and scope
bool exactExpMatch;
ubyte checkUpdatesVisualD; // CheckFrequency: 0: never, 1: daily, 2: weekly, 3: daily prereleases
@@ -1638,6 +1639,7 @@ class GlobalOptions
bool lastColorizeCoverage;
bool lastColorizeVersions;
bool lastShowParseErrors;
+ bool lastShowParamStorage;
bool lastUseDParser;
string lastInstallDirs;
@@ -1991,6 +1993,7 @@ class GlobalOptions
deleteFiles = cast(byte) getIntOpt("deleteFiles", 0);
//parseSource = getBoolOpt("parseSource", true);
showParseErrors = getBoolOpt("showParseErrors", true);
+ showParamStorage = getBoolOpt("showParamStorage", true);
expandFromSemantics = getBoolOpt("expandFromSemantics", true);
//expandFromBuffer = getBoolOpt("expandFromBuffer", true);
expandFromJSON = getBoolOpt("expandFromJSON", true);
@@ -2176,6 +2179,7 @@ class GlobalOptions
lastColorizeVersions = ColorizeVersions;
lastUseDParser = useDParser;
lastShowParseErrors = showParseErrors;
+ lastShowParamStorage = showParamStorage;
updateDefaultColors();
@@ -2268,6 +2272,7 @@ class GlobalOptions
keyToolOpts.Set("deleteFiles", deleteFiles);
//keyToolOpts.Set("parseSource", parseSource);
keyToolOpts.Set("showParseErrors", showParseErrors);
+ keyToolOpts.Set("showParamStorage", showParamStorage);
keyToolOpts.Set("expandFromSemantics", expandFromSemantics);
//keyToolOpts.Set("expandFromBuffer", expandFromBuffer);
keyToolOpts.Set("expandFromJSON", expandFromJSON);
@@ -2348,7 +2353,13 @@ class GlobalOptions
lastShowParseErrors = showParseErrors;
updateColorizer = true;
}
- if(updateColorizer)
+ if (lastShowParamStorage != showParamStorage)
+ {
+ lastShowParamStorage = showParamStorage;
+ if(auto svc = Package.s_instance.mLangsvc)
+ svc.RestartParser();
+ }
+ else if(updateColorizer)
if(auto svc = Package.s_instance.mLangsvc)
svc.UpdateColorizer(true);
diff --git a/visuald/propertypage.d b/visuald/propertypage.d
index 88ba4934..7d5cdba5 100644
--- a/visuald/propertypage.d
+++ b/visuald/propertypage.d
@@ -2983,8 +2983,11 @@ class IntellisensePropertyPage : GlobalPropertyPage
AddTitleLine("Semantic analysis");
AddControl("", mShowParseErrors = new CheckBox(mCanvas, "Show parsing errors (squiggles and markers)"));
version(DParserOption) AddControl("", mUseDmdParser = new CheckBox(mCanvas, "use DMD parsing engine for semantic analysis"));
- AddControl("", mMixinAnalysis = new CheckBox(mCanvas, "Enable mixin analysis"));
- AddControl("", mUFCSExpansions = new CheckBox(mCanvas, "Enable UFCS expansions"));
+ 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("", 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"));
@@ -3010,7 +3013,10 @@ class IntellisensePropertyPage : GlobalPropertyPage
else bool useDParser = true;
mMixinAnalysis.setEnabled(useDParser);
mUFCSExpansions.setEnabled(useDParser);
+ mMixinAnalysis.setVisible(useDParser);
+ mUFCSExpansions.setVisible(useDParser);
mSortExpMode.setEnabled(useDParser);
+ mShowParamStorage.setVisible(!useDParser);
mShowValueInTooltip.setEnabled(mShowTypeInTooltip.isChecked());
}
@@ -3027,6 +3033,7 @@ class IntellisensePropertyPage : GlobalPropertyPage
version(DParserOption) mUseDmdParser.setChecked(!opts.useDParser);
mMixinAnalysis.setChecked(opts.mixinAnalysis);
mUFCSExpansions.setChecked(opts.UFCSExpansions);
+ mShowParamStorage.setChecked(opts.showParamStorage);
mSortExpMode.setSelection(opts.sortExpMode);
mExactExpMatch.setChecked(opts.exactExpMatch);
@@ -3048,6 +3055,7 @@ class IntellisensePropertyPage : GlobalPropertyPage
version(DParserOption) changes += changeOption(!mUseDmdParser.isChecked(), opts.useDParser, refopts.useDParser);
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(cast(ubyte) mSortExpMode.getSelection(), opts.sortExpMode, refopts.sortExpMode);
changes += changeOption(mExactExpMatch.isChecked(), opts.exactExpMatch, refopts.exactExpMatch);
return changes;
@@ -3062,6 +3070,7 @@ class IntellisensePropertyPage : GlobalPropertyPage
CheckBox mShowValueInTooltip;
//CheckBox mSemanticGotoDef;
version(DParserOption) CheckBox mUseDmdParser;
+ CheckBox mShowParamStorage;
CheckBox mUFCSExpansions;
ComboBox mSortExpMode;
CheckBox mExactExpMatch;
diff --git a/visuald/vdserverclient.d b/visuald/vdserverclient.d
index f3108f84..93b895f3 100644
--- a/visuald/vdserverclient.d
+++ b/visuald/vdserverclient.d
@@ -8,6 +8,7 @@
module visuald.vdserverclient;
+import visuald.dpackage;
import visuald.pkgutil;
import visuald.logutil;
@@ -453,7 +454,7 @@ class GetDefinitionCommand : FileCommand
//////////////////////////////////////
alias void delegate(uint request, string filename, string parseErrors,
- TextPos[] binaryIsIn, string tasks, string outline) UpdateModuleCallBack;
+ TextPos[] binaryIsIn, string tasks, string outline, ParameterStorageLoc[] stcLocs) UpdateModuleCallBack;
class UpdateModuleCommand : FileCommand
{
@@ -494,32 +495,38 @@ class UpdateModuleCommand : FileCommand
mErrors = detachBSTR(errors);
- VARIANT locs;
-
- if(gVDServer.GetBinaryIsInLocations(fname, &locs) == S_OK &&
- (locs.vt == (VT_ARRAY | VT_INT) || locs.vt == (VT_ARRAY | VT_I4)))
+ void variantToArray(size_t function(size_t) reorder = n => n, A)(ref VARIANT locs, ref A a)
{
- SAFEARRAY* sa = locs.parray;
- assert(SafeArrayGetDim(sa) == 1);
- LONG lbound, ubound;
- SafeArrayGetLBound(sa, 1, &lbound);
- SafeArrayGetUBound(sa, 1, &ubound);
-
- size_t cnt = (ubound - lbound + 1) / 2;
- mBinaryIsIn.length = cnt;
- for(size_t i = 0; i < cnt; i++)
+ if (locs.vt == (VT_ARRAY | VT_INT) || locs.vt == (VT_ARRAY | VT_I4))
{
- LONG index = lbound + 2 * i;
- int line, col;
- SafeArrayGetElement(sa, &index, &line);
- mBinaryIsIn[i].line = line;
- index++;
- SafeArrayGetElement(sa, &index, &col);
- mBinaryIsIn[i].index = col;
+ SAFEARRAY* sa = locs.parray;
+ assert(SafeArrayGetDim(sa) == 1);
+ LONG lbound, ubound;
+ SafeArrayGetLBound(sa, 1, &lbound);
+ SafeArrayGetUBound(sa, 1, &ubound);
+
+ enum Alen = a[0].tupleof.length;
+ size_t cnt = (ubound - lbound + 1) / Alen;
+ a.length = cnt;
+ LONG index = lbound;
+ int val;
+ for(size_t i = 0; i < cnt; i++)
+ {
+ static foreach(f; 0..Alen)
+ {
+ SafeArrayGetElement(sa, &index, &val);
+ a[i].tupleof[reorder(f)] = val;
+ index++;
+ }
+ }
+ SafeArrayDestroy(sa);
}
- SafeArrayDestroy(sa);
}
+ VARIANT locs;
+ if(gVDServer.GetBinaryIsInLocations(fname, &locs) == S_OK)
+ variantToArray!(n => 1 - n)(locs, mBinaryIsIn); // swap line and column
+
BSTR tasks;
if(gVDServer.GetCommentTasks(fname, &tasks) == S_OK)
mTasks = detachBSTR(tasks);
@@ -528,6 +535,13 @@ class UpdateModuleCommand : FileCommand
if(gVDServer.GetDocumentOutline(fname, &outline) == S_OK)
mOutline = detachBSTR(outline);
+ if (Package.GetGlobalOptions().showParamStorage)
+ {
+ VARIANT stclocs;
+ if(gVDServer.GetParameterStorageLocs(fname, &stclocs) == S_OK)
+ variantToArray(stclocs, mParameterStcLocs);
+ }
+
send(gUITid);
return S_OK;
}
@@ -537,7 +551,7 @@ class UpdateModuleCommand : FileCommand
version(DebugCmd)
dbglog(to!string(mRequest) ~ " forward: " ~ mCommand ~ " " ~ ": " ~ mErrors);
if(mCallback)
- mCallback(mRequest, mFilename, mErrors, cast(TextPos[])mBinaryIsIn, mTasks, mOutline);
+ mCallback(mRequest, mFilename, mErrors, cast(TextPos[])mBinaryIsIn, mTasks, mOutline, mParameterStcLocs);
return true;
}
@@ -548,6 +562,7 @@ class UpdateModuleCommand : FileCommand
string mOutline;
bool mVerbose;
TextPos[] mBinaryIsIn;
+ ParameterStorageLoc[] mParameterStcLocs;
}
//////////////////////////////////////
diff --git a/visuald/visuald.def b/visuald/visuald.def
index d6f017e2..c87fd279 100644
--- a/visuald/visuald.def
+++ b/visuald/visuald.def
@@ -25,3 +25,4 @@ EXPORTS
GenerateGeneralXMLW = GenerateGeneralXMLW PRIVATE
GetTooltip = GetTooltip PRIVATE
GetTooltipResult = GetTooltipResult PRIVATE
+ GetParameterStorageLocs = GetParameterStorageLocs PRIVATE