From e4cf83cc52b3096eaaf1e8e27c08d31bc5923039 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Thu, 1 May 2025 11:55:22 +0200 Subject: [PATCH 1/5] * issue #300: storage class adornments not updated after edits * dmdserver: fixed a couple of assertions causing the server to restart * dmdserver: replaced new location storage to avoid leaking memory --- CHANGES | 7 ++ VERSION | 2 +- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/dmdinit.d | 8 ++- vdc/dmdserver/dmdserver.d | 9 ++- vdc/dmdserver/dmdserver.visualdproj | 3 +- vdc/dmdserver/semanalysis.d | 35 ++++++++++ vdc/dmdserver/semvisitor.d | 36 +++++----- vdextensions/ParamStorageAdornmentTagger.cs | 76 +++++++++++++++------ 9 files changed, 135 insertions(+), 43 deletions(-) diff --git a/CHANGES b/CHANGES index e4df28c3..c7850449 100644 --- a/CHANGES +++ b/CHANGES @@ -1414,3 +1414,10 @@ Version history * mago: fixed display of AA key in expanded view * issue #291: allow overriding the default compiler executable path in the VC project settings * issue #296: VC project integration: added support to build for ARM64 with LDC + +2025-05-01 version 1.4.1-beta2 + * issue #300: storage class adornments not updated after edits + * issue #301: mago: strip modifier from type before detecting arrays + * mago: improved stability when displaying arrays from invalid memory address + * dmdserver: fixed a couple of assertions causing the server to restart + * dmdserver: replaced new location storage to avoid leaking memory diff --git a/VERSION b/VERSION index 1228e30d..39e81088 100644 --- a/VERSION +++ b/VERSION @@ -2,4 +2,4 @@ #define VERSION_MINOR 4 #define VERSION_REVISION 1 #define VERSION_BETA -beta -#define VERSION_BUILD 1 +#define VERSION_BUILD 2 diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index 1c76aff5..4dc84be3 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit 1c76aff562cec901f3fb89e9ae29fcb14c145c4b +Subproject commit 4dc84be3eee010d6524dc679626b373059e9e606 diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d index ba5a27d5..3b515e2d 100644 --- a/vdc/dmdserver/dmdinit.d +++ b/vdc/dmdserver/dmdinit.d @@ -23,11 +23,13 @@ import dmd.dmodule; import dmd.dstruct; import dmd.dsymbol; import dmd.dtemplate; +import dmd.escape; import dmd.expression; import dmd.func; import dmd.globals; import dmd.id; import dmd.identifier; +import dmd.location; import dmd.mtype; import dmd.objc; import dmd.rootobject; @@ -42,6 +44,8 @@ import core.stdc.string; //////////////////////////////////////////////////////////////// alias countersType = uint[uint]; // actually uint[Key] alias EscapeInfer = RootObject[int]; +enum uint_1 : uint { initValue = 1 } + enum string[2][] dmdStatics = [ @@ -108,6 +112,7 @@ enum string[2][] dmdStatics = ["_D3dmd7arrayop7arrayOpFCQw10expression6BinExpPSQBt6dscope5ScopeZQByCQCo9dtemplate19TemplateDeclaration", "TemplateDeclaration"], ["_D3dmd6errors18colorHighlightCodeFNbKSQBk6common9outbuffer9OutBufferZ6nestedi", "int"], ["_D3dmd7dmodule6Module18loadCoreStdcConfigFZ16core_stdc_configCQCiQChQCc", "Module"], + // EscapeState.reset not accessible in package dmd ["_D3dmd6escape11EscapeState17scopeInferFailureHiCQBu10rootobject10RootObject", "EscapeInfer" ], ]; @@ -135,7 +140,7 @@ string genInitDmdStatics() { string s; foreach (decl; dmdStatics) - s ~= cmangled(decl[0]) ~ " = " ~ decl[1] ~ ".init;\n"; + s ~= cmangled(decl[0]) ~ " = (" ~ decl[1] ~ ").init;\n"; return s; } @@ -197,6 +202,7 @@ void dmdInit() //Token._init(); Id.initialize(); Expression._init(); + location_init(); target._init(global.params); // needed by Type._init Type._init(); diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index 7f53e8ca..e1df66d1 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -840,7 +840,7 @@ class DMDServer : ComObject, IVDServer *types = allocBSTR("__pending__"); return S_OK; } - version(DebugServer) if(dbgfh) dbglog("GetIdentifierTypesResult: " ~ firstLine(mLastReferences) ~ "..."); + version(DebugServer) if(dbgfh) dbglog("GetIdentifierTypesResult: " ~ firstLine(mLastIdentifierTypes) ~ "..."); *types = allocBSTR(mLastIdentifierTypes); return S_OK; } @@ -855,14 +855,20 @@ class DMDServer : ComObject, IVDServer { md = findModule(fname, false); if (!md || !md.analyzedModule) + { + version(DebugServer) if(dbgfh) dbglog("GetParameterStorageLocs: " ~ fname ~ " not found"); return S_FALSE; + } } auto stcLoc = findParameterStorageClass(md.analyzedModule); 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)"); return E_OUTOFMEMORY; + } for(LONG index = 0; index < stcLoc.length; index++) { @@ -877,6 +883,7 @@ class DMDServer : ComObject, IVDServer SafeArrayPutElement(sa, &idx, &value); } + version(DebugServer) if(dbgfh) dbglog("GetParameterStorageLocs: " ~ fname ~ " OK (" ~ to!string(stcLoc.length) ~ " entries)"); locs.vt = VT_ARRAY | VT_INT; locs.parray = sa; return S_OK; diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index c01c9f02..80d308be 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -2406,7 +2406,7 @@ - + @@ -2455,6 +2455,7 @@ + 0) if (!references.contains(Reference(loc, ident))) references ~= Reference(loc, ident); } @@ -2510,15 +2512,8 @@ extern(C++) class FindExpansionsVisitor : FindASTVisitor override void visit(DotIdExp de) { if (!found && de.ident) - { if (matchDotIdentifier(de.dotloc, de.identloc, de.ident)) - { - if (!de.type && de.resolvedTo && !de.resolvedTo.isErrorExp()) - foundResolved(de.resolvedTo); - else - foundNode(de); - } - } + foundNode(de); } override void checkScope(ScopeDsymbol sc) @@ -2542,7 +2537,7 @@ extern(C++) class FindExpansionsVisitor : FindASTVisitor string[] findExpansions(Module mod, int line, int index, string tok) { - auto filename = mod.srcfile.toChars(); + auto filename = mod.srcfile.toString().toLocFilename.ptr; scope FindExpansionsVisitor fdv = new FindExpansionsVisitor(filename, line, index, line, index + 1); mod.accept(fdv); @@ -2584,6 +2579,13 @@ string[] findExpansions(Module mod, int line, int index, string tok) if (auto t = getType(e, false)) type = t; } + if (!type) + if (auto sym = fdv.found ? fdv.found.isDsymbol() : null) + if (auto em = sym.isEnumMember()) + type = em.ed.type; + + if (type && type.isTypeEnum()) + flags |= SearchOpt.localsOnly; auto sds = fdv.foundScope; if (type) diff --git a/vdextensions/ParamStorageAdornmentTagger.cs b/vdextensions/ParamStorageAdornmentTagger.cs index 8fcba934..7c977e65 100644 --- a/vdextensions/ParamStorageAdornmentTagger.cs +++ b/vdextensions/ParamStorageAdornmentTagger.cs @@ -3,24 +3,24 @@ //*************************************************************************** using System; -using System.ComponentModel.Composition; using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Globalization; using System.Linq; +using System.Runtime.InteropServices; // DllImport using System.Windows; -using System.Windows.Media; using System.Windows.Controls; using System.Windows.Documents; -using System.Globalization; -using System.Runtime.InteropServices; // DllImport - +using System.Windows.Forms; +using System.Windows.Media; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; 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; +using Microsoft.VisualStudio.Utilities; namespace vdext15 { @@ -42,8 +42,9 @@ internal abstract class IntraTextAdornmentTagger protected Dictionary adornmentCache = new Dictionary(); protected ITextSnapshot snapshot { get; private set; } private readonly List invalidatedSpans = new List(); + protected SnapshotSpan _lastTagSpan; - protected IntraTextAdornmentTagger(IWpfTextView view) + protected IntraTextAdornmentTagger(IWpfTextView view) { this.view = view; snapshot = view.TextBuffer.CurrentSnapshot; @@ -91,7 +92,17 @@ protected void InvalidateSpans(IList spans) if (wasEmpty && this.invalidatedSpans.Count > 0) view.VisualElement.Dispatcher.BeginInvoke(new Action(AsyncUpdate)); } + } + + public void InvokeAsyncUpdate() + { + view.VisualElement.Dispatcher.BeginInvoke(new Action(RedoAsyncUpdate)); } + public void RedoAsyncUpdate() + { + if (snapshot != null) + RaiseTagsChanged(new SnapshotSpan(snapshot, 0, snapshot.Length)); + } private void AsyncUpdate() { @@ -126,7 +137,8 @@ private void AsyncUpdate() var start = translatedSpans.Select(span => span.Start).Min(); var end = translatedSpans.Select(span => span.End).Max(); - RaiseTagsChanged(new SnapshotSpan(start, end)); + _lastTagSpan = new SnapshotSpan(start, end); + RaiseTagsChanged(_lastTagSpan); } /// @@ -323,7 +335,15 @@ private ParamStorageAdornmentTagger(IWpfTextView view, IEditorFormatMap formatMa : base(view) { this.paramStorageTagger = paramStorageTagger; - this.formatMap = formatMap; + ITextBuffer buffer = view.TextBuffer; + if (buffer != null) + { + ParamStorageTagger tagger; + if (buffer.Properties.TryGetProperty(typeof(ParamStorageTagger), out tagger)) + tagger._adornmentTagger = this; + } + + this.formatMap = formatMap; this.formatMap.FormatMappingChanged += (sender, args) => UpdateColors(); UpdateColors(); } @@ -390,7 +410,9 @@ internal class ParamStorageTagger : ITagger int[] _stcLocs; ITextSnapshot _pendingSnapshot; ITextSnapshot _currentSnapshot; - int _changeCount; + public ParamStorageAdornmentTagger _adornmentTagger; + + int _changeCount; public ParamStorageTagger(ITextBuffer buffer) { @@ -413,16 +435,16 @@ public ParamStorageTagger(ITextBuffer buffer) #region ITagger implementation - public void UpdateStcSpans() + public bool UpdateStcSpans() { int[] stcLocs; bool pending; int changeCount; ParamStorageAdornmentTagger.GetParameterStorageLocations(_fileName, out stcLocs, out pending, out changeCount); if (pending && _stcLocs != null) - return; + return pending; if (_pendingSnapshot == null && _changeCount == changeCount) - return; + return false; if (stcLocs != null) { @@ -445,11 +467,12 @@ public void UpdateStcSpans() _changeCount = changeCount; if (!pending) _pendingSnapshot = null; + return pending; } public virtual IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) { - UpdateStcSpans(); + bool pending = UpdateStcSpans(); // Note that the spans argument can contain spans that are sub-spans of lines or intersect multiple lines. if (_stcLocs != null) @@ -469,7 +492,18 @@ public virtual IEnumerable> GetTags(NormalizedSnapshot yield return new TagSpan(span, new ParamStorageTag(_stcLocs[i])); } } - } + + if (pending) + { + System.Threading.Timer timer = null; + timer = new System.Threading.Timer((obj) => + { + timer.Dispose(); + if (_adornmentTagger != null) + _adornmentTagger.InvokeAsyncUpdate(); + }, null, 1000, System.Threading.Timeout.Infinite); + } + } public event EventHandler TagsChanged; #endregion @@ -484,8 +518,7 @@ protected virtual void HandleBufferChanged(TextContentChangedEventArgs args) if (args.Changes.Count == 0) return; - var temp = TagsChanged; - if (temp == null) + if (TagsChanged == null) return; // adapt stcSpans, so any unmodified tags get moved with changes @@ -503,11 +536,12 @@ protected virtual void HandleBufferChanged(TextContentChangedEventArgs args) int start = args.Changes[0].NewPosition; int end = args.Changes[args.Changes.Count - 1].NewEnd; - SnapshotSpan totalAffectedSpan = new SnapshotSpan( + SnapshotSpan totalAffectedSpan = new SnapshotSpan( _currentSnapshot.GetLineFromPosition(start).Start, _currentSnapshot.GetLineFromPosition(end).End); - temp(this, new SnapshotSpanEventArgs(totalAffectedSpan)); + if (TagsChanged != null) + TagsChanged(this, new SnapshotSpanEventArgs(totalAffectedSpan)); } } From ff8875bc2bb1f5ec573c34ff5a9e71848f4f3c8d Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Thu, 1 May 2025 11:56:48 +0200 Subject: [PATCH 2/5] add missing file dmdlocation.d --- vdc/dmdserver/dmdlocation.d | 353 ++++++++++++++++++++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 vdc/dmdserver/dmdlocation.d diff --git a/vdc/dmdserver/dmdlocation.d b/vdc/dmdserver/dmdlocation.d new file mode 100644 index 00000000..f6b6b39b --- /dev/null +++ b/vdc/dmdserver/dmdlocation.d @@ -0,0 +1,353 @@ +// replace dmd.location for faster line/file lookup and incremental updates + +module dmd.location; + +import core.stdc.stdio; + +import dmd.common.outbuffer; +import dmd.root.array; +import dmd.root.filename; +import dmd.root.rmem : xarraydup; +import dmd.root.string: toDString; +import dmd.root.stringtable; + +/// How code locations are formatted for diagnostic reporting +enum MessageStyle : ubyte +{ + digitalmars, /// filename.d(line): message + gnu, /// filename.d:line: message, see https://www.gnu.org/prep/standards/html_node/Errors.html + sarif /// JSON SARIF output, see https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html +} +/** +A source code location + +Used for error messages, `__FILE__` and `__LINE__` tokens, `__traits(getLocation, XXX)`, +debug info etc. +*/ +struct Loc +{ + private ulong data = 0; // bitfield of file, line and column + + static immutable Loc initial; /// use for default initialization of Loc's + + extern (C++) __gshared bool showColumns; + extern (C++) __gshared MessageStyle messageStyle; + +nothrow: + /******************************* + * Configure how display is done + * Params: + * showColumns = when to display columns + * messageStyle = digitalmars or gnu style messages + */ + extern (C++) static void set(bool showColumns, MessageStyle messageStyle) + { + this.showColumns = showColumns; + this.messageStyle = messageStyle; + } + + /// Returns: a Loc that simply holds a filename, with no line / column info + extern (C++) static Loc singleFilename(const char* filename) + { + return singleFilename(filename.toDString); + } + + /// Returns: a Loc that simply holds a filename, with no line / column info + static Loc singleFilename(const(char)[] filename) + { + ulong fileIndex = toLocFileIndex(filename); + return Loc((fileIndex << 48) | 1); // default to charnum 1 + } + + /// utf8 code unit index relative to start of line, starting from 1 + extern (C++) uint charnum() const @nogc @safe + { + return data & 0xffff; + } + + /// line number, starting from 1 + extern (C++) uint linnum() const @nogc @trusted + { + return (data >> 16) & 0xffff_ffff; + } + + /*** + * Returns: filename for this location, null if none + */ + extern (C++) const(char)* filename() const @nogc + { + return locFileName[data >> 48].ptr; + } + + /// Advance this location to the first column of the next line + void nextLine() @safe pure @nogc + { + data = (data & ~0xffffL) + 0x10001; + } + + bool isValid() const pure @safe + { + return data != 0; + } + + extern (C++) const(char)* toChars(bool showColumns = Loc.showColumns, + MessageStyle messageStyle = Loc.messageStyle) const nothrow + { + return SourceLoc(this).toChars(showColumns, messageStyle); + } + /** + * Checks for equivalence by comparing the filename contents (not the pointer) and character location. + * + * Note: + * - Uses case-insensitive comparison on Windows + * - Ignores `charnum` if `Columns` is false. + */ + extern (C++) bool equals(Loc loc) const + { + auto this_data = showColumns ? data : data & ~0xffff; + auto loc_data = showColumns ? loc.data : loc.data & ~0xffff; + return this_data == loc_data; + } + + /** + * `opEquals()` / `toHash()` for AA key usage + * + * Compare filename contents (case-sensitively on Windows too), not + * the pointer - a static foreach loop repeatedly mixing in a mixin + * may lead to multiple equivalent filenames (`foo.d-mixin-`), + * e.g., for test/runnable/test18880.d. + */ + extern (D) bool opEquals(ref const(Loc) loc) const @trusted nothrow @nogc + { + return this.data == loc.data; + } + + /// ditto + extern (D) size_t toHash() const @trusted nothrow + { + return hashOf(this.data); + } +} + +/** + * Format a source location for error messages + * + * Params: + * buf = buffer to write string into + * loc = source location to write + * showColumns = include column number in message + * messageStyle = select error message format + */ +void writeSourceLoc(ref OutBuffer buf, SourceLoc loc, bool showColumns, MessageStyle messageStyle) nothrow +{ + auto filename = loc.filename; + if (filename is null) + return; + buf.writestring(loc.filename); + if (loc.linnum == 0) + return; + + final switch (messageStyle) + { + case MessageStyle.digitalmars: + buf.writeByte('('); + buf.print(loc.linnum); + if (showColumns && loc.charnum) + { + buf.writeByte(','); + buf.print(loc.charnum); + } + buf.writeByte(')'); + break; + case MessageStyle.gnu: // https://www.gnu.org/prep/standards/html_node/Errors.html + buf.writeByte(':'); + buf.print(loc.linnum); + if (showColumns && loc.charnum) + { + buf.writeByte(':'); + buf.print(loc.charnum); + } + break; + case MessageStyle.sarif: // https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html + // No formatting needed here for SARIF + break; + } +} + +// Global string table to make file names comparable via `is` +private __gshared StringTable!(size_t) locFileNameIndex; +private __gshared const(char)[][] locFileName; + +size_t toLocFileIndex(const(char)[] fname) nothrow @trusted +{ + if (locFileName.length == 0) + { + locFileNameIndex.reset(); + locFileName ~= null; + locFileNameIndex.insert("", 0); // for loc.initial + } + if (auto p = locFileNameIndex.lookup(fname)) + return p.value; + size_t idx = locFileName.length; + locFileName ~= fname.xarraydup; + locFileNameIndex.insert(fname, idx); + return idx; +} + +const(char)[] toLocFilename(const(char)[] fname) nothrow +{ + return locFileName[toLocFileIndex(fname)]; +} + +const(char)[] toLocFilename(const(char)* fname) nothrow +{ + return toLocFilename(fname.toDString); +} + +void location_init() +{ + locFileName = null; + locFileNameIndex.reset(); +} + +struct SourceLoc +{ + Loc loc; + + //alias loc this; + + // aliases for backwards compatibility + alias linnum = loc.linnum; + alias line = loc.linnum; + alias charnum = loc.charnum; + alias column = loc.charnum; + + this(Loc oloc) nothrow @safe + { + loc = oloc; + } + + this(const(char)[] filename, uint line, uint column, + uint fileOffset = 0, const(char)[] fileContent = null) nothrow @safe + { + if (column > 0xffff) + column = 0xffff; + ulong fileIndex = toLocFileIndex(filename); + loc.data = (fileIndex << 48) | (line << 16) | column; + } + + void filename(const(char)[] fname) nothrow + { + ulong fileIndex = toLocFileIndex(fname); + loc.data = (loc.data & ((1L << 48) - 1)) | (fileIndex << 48); + } + const(char)[] filename() const nothrow @nogc + { + return loc.filename.toDString; + } + uint xline() const nothrow + { + return loc.linnum(); + } + uint xcolumn() const nothrow + { + return loc.charnum(); + } + const(char)[] fileContent() const nothrow + { + return null; // only for error messages with context + } + uint fileOffset() const nothrow + { + return 0; // only for error messages with context + } + + bool opEquals(SourceLoc other) const nothrow + { + return loc == other.loc; + } + + extern (C++) const(char)* toChars(bool showColumns = Loc.showColumns, + MessageStyle messageStyle = Loc.messageStyle) const nothrow + { + OutBuffer buf; + writeSourceLoc(buf, this, showColumns, messageStyle); + return buf.extractChars(); + } +} + +struct BaseLoc +{ + SourceLoc loc; + + uint startLine; + uint startOffset; + uint lastLineOffset; + BaseLoc[] substitutions; /// Substitutions from #line / #file directives + + alias loc this; + +nothrow: + this(const(char)[] filename, uint startLine) + { + this.loc = SourceLoc(filename, 1, 1); + this.startLine = startLine; + } + + Loc getLoc(uint offset) @nogc + { + Loc nloc; + nloc.data = loc.loc.data + offset - lastLineOffset; // add char offset + return nloc; + } + + /** + * Register a new file/line mapping from #file and #line directives + * Params: + * offset = byte offset in the source file at which the substitution starts + * filename = new filename from this point on (null = unchanged) + * line = line number from this point on + */ + void addSubstitution(uint offset, const(char)* filename, uint line) @system + { + auto fname = filename.toDString; + if (substitutions.length == 0) + substitutions ~= BaseLoc(this.filename, 0); + + if (fname.length == 0) + fname = substitutions[$ - 1].filename; + substitutions ~= BaseLoc(fname, startLine + line); // cast(int) (line - lines.length + startLine - 2)); + } + + /// Returns: `loc` modified by substitutions from #file / #line directives + SourceLoc substitute(SourceLoc loc) + { + if (substitutions.length == 0) + return loc; + + const i = 0; // todo: getSubstitutionIndex(loc.fileOffset); + if (substitutions[i].filename.length > 0) + loc.filename = substitutions[i].filename; + return SourceLoc(loc.filename, loc.line + substitutions[i].startLine, loc.column); + } + void newLine(uint offset) @safe + { + lastLineOffset = offset; + loc.loc.nextLine(); + } +} + +BaseLoc* newBaseLoc(const(char)* filename, const(char)[] fileContent) nothrow +{ + return new BaseLoc(filename.toDString, 0); +} + +// for a language server, lowered expression should not reuse the original source location +// as internal names might get exposed to the user +ref const(Loc) loweredLoc(return ref const Loc loc) +{ + version(LanguageServer) + return Loc.initial; + else + return loc; +} From 368bc91d00f782fcfe4694c2e71d9d379ed9d03d Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 2 May 2025 08:27:03 +0200 Subject: [PATCH 3/5] init compileEnv to fix crash with unicode remove \r from tip text --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/dmdinit.d | 57 ++++++++++++++++++++++++++++++++++++++ vdc/dmdserver/semvisitor.d | 2 +- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index 4dc84be3..194c51e4 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit 4dc84be3eee010d6524dc679626b373059e9e606 +Subproject commit 194c51e4bb02ab4fbaa232f3d56d38f7794c0c2a diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d index 3b515e2d..c22613ea 100644 --- a/vdc/dmdserver/dmdinit.d +++ b/vdc/dmdserver/dmdinit.d @@ -400,6 +400,63 @@ void dmdSetupParams(const ref Options opts) global.filePath.setDim(0); foreach(i; opts.stringImportDirs) global.filePath.push(toStringz(i)); + + dmdSetupCompileEnv(); +} + +void dmdSetupCompileEnv() +{ + import dmd.common.charactertables; + + global.compileEnv.previewIn = global.params.previewIn; + global.compileEnv.transitionIn = global.params.v.vin; + global.compileEnv.ddocOutput = global.params.ddoc.doOutput; + + final switch(global.params.cIdentifierTable) + { + case CLIIdentifierTable.C99: + global.compileEnv.cCharLookupTable = IdentifierCharLookup.forTable(IdentifierTable.C99); + break; + + case CLIIdentifierTable.C11: + case CLIIdentifierTable.default_: + // ImportC is defined against C11, not C23. + // If it was C23 this needs to be changed to UAX31 instead. + global.compileEnv.cCharLookupTable = IdentifierCharLookup.forTable(IdentifierTable.C11); + break; + + case CLIIdentifierTable.UAX31: + global.compileEnv.cCharLookupTable = IdentifierCharLookup.forTable(IdentifierTable.UAX31); + break; + + case CLIIdentifierTable.All: + global.compileEnv.cCharLookupTable = IdentifierCharLookup.forTable(IdentifierTable.LR); + break; + } + + final switch(global.params.dIdentifierTable) + { + case CLIIdentifierTable.C99: + global.compileEnv.dCharLookupTable = IdentifierCharLookup.forTable(IdentifierTable.C99); + break; + + case CLIIdentifierTable.C11: + global.compileEnv.dCharLookupTable = IdentifierCharLookup.forTable(IdentifierTable.C11); + break; + + case CLIIdentifierTable.UAX31: + global.compileEnv.dCharLookupTable = IdentifierCharLookup.forTable(IdentifierTable.UAX31); + break; + + case CLIIdentifierTable.All: + case CLIIdentifierTable.default_: + // @@@DEPRECATED_2.119@@@ + // Change the default to UAX31, + // this is a breaking change as C99 (what D used for ~23 years), + // has characters that are not in UAX31. + global.compileEnv.dCharLookupTable = IdentifierCharLookup.forTable(IdentifierTable.LR); + break; + } } // initialization that are necessary before restarting an analysis (which might run diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 85f15b9f..bd824600 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -2343,7 +2343,7 @@ string symbol2ExpansionLine(Dsymbol sym) { string type = symbol2ExpansionType(sym); string tip = tipForObject(sym); - return type ~ ":" ~ tip.replace("\n", "\a"); + return type ~ ":" ~ tip.replace("\n", "\a").replace("\r", ""); } string[string] initSymbolProperties(int kind) From b9d817dcd7979c0edac919e0482ee64f9be1401d Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 2 May 2025 10:05:07 +0200 Subject: [PATCH 4/5] fix dmd builds --- vdc/dmdserver/dmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index 194c51e4..1ce5bf17 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit 194c51e4bb02ab4fbaa232f3d56d38f7794c0c2a +Subproject commit 1ce5bf171d70dce5312e001e5276cbdc359ac201 From 1f35707e8553471b421cd715bd6c802a920216b5 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 2 May 2025 10:40:26 +0200 Subject: [PATCH 5/5] fix tests --- vdc/dmdserver/semanalysis.d | 5 +++-- vdextensions/ParamStorageAdornmentTagger.cs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index fe4e52f0..cbb99e19 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -720,7 +720,7 @@ void do_unittests() "14,2,14,3:Error: identifier or `new` expected following `.`, not `}`\n" ~ "14,2,14,3:Error: semicolon needed to end declaration of `y`, instead of `}`\a" ~ "source.d(13): `y` declared here\n" ~ - "12,15,12,16:Error: no property `f` for type `source.S`\a" ~ + "12,15,12,16:Error: no property `f` for `anS` of type `source.S`\a" ~ "source.d(2): struct `S` defined here\n"); //dumpAST(m); string[] structProperties = [ "init", "sizeof", "alignof", "mangleof", "stringof", "tupleof" ]; @@ -745,7 +745,8 @@ void do_unittests() } }; m = checkErrors(source, - "12,11,12,12:Error: no property `fool` for type `source.S`\a" ~ + "12,11,12,12:Error: no property `fool` for `anS` of type `source.S`\a" ~ + "source.d(9): did you mean function `foo`?\a" ~ "source.d(2): struct `S` defined here\n" ~ "13,10,13,11:Error: undefined identifier `fok`, did you mean function `foo`?\n"); //dumpAST(m); diff --git a/vdextensions/ParamStorageAdornmentTagger.cs b/vdextensions/ParamStorageAdornmentTagger.cs index 7c977e65..bab69443 100644 --- a/vdextensions/ParamStorageAdornmentTagger.cs +++ b/vdextensions/ParamStorageAdornmentTagger.cs @@ -501,7 +501,7 @@ public virtual IEnumerable> GetTags(NormalizedSnapshot timer.Dispose(); if (_adornmentTagger != null) _adornmentTagger.InvokeAsyncUpdate(); - }, null, 1000, System.Threading.Timeout.Infinite); + }, null, 200, System.Threading.Timeout.Infinite); } } public event EventHandler TagsChanged;