From 97d05be481ce8511aeadca1e4f1e18631240efed Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 6 Sep 2019 17:33:09 +0200 Subject: [PATCH 01/73] add vdext15 with Ctrl+Click -> Goto Definition --- CHANGES | 3 + Makefile | 5 +- TODO | 79 +++ VERSION | 8 +- msbuild/dbuild/dbuild.sln | 19 +- nsis/Extensions_vs15/extension.vsixmanifest | 36 ++ nsis/visuald.nsi | 5 +- sdk/vsi.visualdproj | 5 + tools/build_dcxxfilt.bat | 2 +- vdextensions/gotodef.cs | 574 ++++++++++++++++++++ vdextensions/vdext15.cs | 38 ++ vdextensions/vdext15.csproj | 130 +++++ vdextensions/vdextensions.sln | 58 +- visuald_vs10.sln | 12 + 14 files changed, 948 insertions(+), 26 deletions(-) create mode 100644 nsis/Extensions_vs15/extension.vsixmanifest create mode 100644 vdextensions/gotodef.cs create mode 100644 vdextensions/vdext15.cs create mode 100644 vdextensions/vdext15.csproj diff --git a/CHANGES b/CHANGES index c125eda5..724fa7b3 100644 --- a/CHANGES +++ b/CHANGES @@ -1174,3 +1174,6 @@ Version history * don't highlight asm keywords/mnemonics/registers from semantic information * VS 2019 16.2: command line options no longer read correctly from the VC project for Compile and Run/Debug/Disassemble, dbuild refactored to not rely on msbuild DLLs for that + +unreleased Version 0.51.0 + * Ctrl+Click goto definition added for VS2017+ diff --git a/Makefile b/Makefile index 5370280a..c35dd220 100644 --- a/Makefile +++ b/Makefile @@ -81,6 +81,9 @@ fake_dparser: vdextension: cd vdextensions && $(MSBUILD) vdextensions.csproj /p:Configuration=Release;Platform=x86 /t:Rebuild +vdext15: + cd vdextensions && $(MSBUILD) vdext15.csproj /p:Configuration=Release;Platform=x86 /t:Rebuild + visualdwizard: cd vdwizard && $(MSBUILD) VisualDWizard.csproj /p:Configuration=Release;Platform=AnyCPU /t:Rebuild @@ -163,7 +166,7 @@ install_vs_no_vs2017: install_modules fake_dparser cv2pdb mago dbuild12 dbuild install_vs_only_vs2017: install_modules dparser dparser_test cv2pdb_vs15 mago_vs15 fake_dbuild12 fake_dbuild14 dbuild15 install_only -install_modules: prerequisites visuald_vs vdserver vdextension visualdwizard dcxxfilt +install_modules: prerequisites visuald_vs vdserver vdextension vdext15 visualdwizard dcxxfilt install_only: if not exist ..\downloads\nul md ..\downloads diff --git a/TODO b/TODO index 915dcb4b..92d6fd92 100644 --- a/TODO +++ b/TODO @@ -229,7 +229,86 @@ Unsorted - dparser: doesn't support qualified name in catch(fqn) +- dpp support + 0.45.0 ====== - exception on vdextensions: The Visual Studio component cache is out of date +0.49.0 +====== +- DParser: + + static if (is(__traits(parent, target) : __traits(parent, rest[0]))) + + static if (is(T == __vector) ) + - needs too much CPU +- Documentation: + - installation (VC required) + - move newer VS versions to top ++ colors +- tooltips +- exceptions while VC project loaded? +- VS2019: + - new project: D templates hardly accessible + + vcxproj: DCompiler not selectable +- mago: + - toDebug + - context 'this' and members of 'this' shown +- pasting large code snippet is slow with auto-indent + +0.50.0 +====== ++ VS 16.2: pdb newer than exe ++ Deprecation shown as error + +- search files/symbols sometimes blank: columns have width 0 +- new D module: adjust module name + ++ VC project: simpler opt-in for -mixin, per package filename ++ -extern-std= + +- dark scheme: colors wrong after install (also happens for C#?), colors still too dark +- reference highlight: wrong color, not shown in scroll margin +- download: no update for the status bar in VS2017 ++ display html error ++ update message "DMD 2.086.1 Goto Page"? ++ VC projects: DMD/LDC switch not visible in non-english? + ++ vtbl for C++ classes +- mago: call update in VS2019 ++ mago: VS2019, dragging a variable from the autos, locals, or watches copies the whole line (C++, too?) ++ mago: breakpoint conditions no longer supported? +- mago: debug info with different cased filenames opened twice in VS ++ mago: limit array exansions ++ mago: AA with impl, but without elements? +- mago: start class expansions for derived type + ++ support -lowmem ++ show message if compiler path wrong + +- LDC: options for debug-lib and LTO + +- HiDPI: + + edit line in search dialog + + edit line in profiler dialog + + search and replace token dialog + + C++ conversion wizard + - toolbar bitmaps don't scale +- adapt tool window color to theme + +- semantic coloring: + - x in foreach(x; range) + - x in if(auto x = ptr) + - goto labels + - exit in scope(exit) + - x in extern(x) + - public imports in imports + + +0.50.1 +====== ++ reset settings to default ++ msbuild doesn't work after first full instllation, still needs to open+close settings +- vd reported as "unresponsive" when loading project (> 7 sec) ++ VC parallel build + +- compile & disassemble: VC projects output dir always Win32/Debug \ No newline at end of file diff --git a/VERSION b/VERSION index c4e5d5d5..e4dee504 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ #define VERSION_MAJOR 0 -#define VERSION_MINOR 50 -#define VERSION_REVISION 1 -#define VERSION_BETA -#define VERSION_BUILD 0 +#define VERSION_MINOR 51 +#define VERSION_REVISION 0 +#define VERSION_BETA -alpha +#define VERSION_BUILD 1 diff --git a/msbuild/dbuild/dbuild.sln b/msbuild/dbuild/dbuild.sln index d99e23b0..1af84bda 100644 --- a/msbuild/dbuild/dbuild.sln +++ b/msbuild/dbuild/dbuild.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29215.179 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dbuild", "dbuild.csproj", "{45508B90-440B-46DD-82CC-178196D9794E}" EndProject @@ -10,13 +10,13 @@ Global Debug|Any CPU = Debug|Any CPU Debug-v14|Any CPU = Debug-v14|Any CPU Debug-v15|Any CPU = Debug-v15|Any CPU - Debug-v16|Any CPU = Debug-v16|Any CPU Debug-v16_1|Any CPU = Debug-v16_1|Any CPU + Debug-v16|Any CPU = Debug-v16|Any CPU Release|Any CPU = Release|Any CPU Release-v14|Any CPU = Release-v14|Any CPU Release-v15|Any CPU = Release-v15|Any CPU - Release-v16|Any CPU = Release-v16|Any CPU Release-v16_1|Any CPU = Release-v16_1|Any CPU + Release-v16|Any CPU = Release-v16|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {45508B90-440B-46DD-82CC-178196D9794E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -25,22 +25,25 @@ Global {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v14|Any CPU.Build.0 = Debug-v14|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v15|Any CPU.ActiveCfg = Debug-v15|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v15|Any CPU.Build.0 = Debug-v15|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|Any CPU.ActiveCfg = Debug-v16|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|Any CPU.Build.0 = Debug-v16|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16_1|Any CPU.ActiveCfg = Debug-v16_1|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16_1|Any CPU.Build.0 = Debug-v16_1|Any CPU + {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|Any CPU.ActiveCfg = Debug-v16|Any CPU + {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|Any CPU.Build.0 = Debug-v16|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release|Any CPU.ActiveCfg = Release|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release|Any CPU.Build.0 = Release|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release-v14|Any CPU.ActiveCfg = Release-v14|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release-v14|Any CPU.Build.0 = Release-v14|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release-v15|Any CPU.ActiveCfg = Release-v15|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release-v15|Any CPU.Build.0 = Release-v15|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Release-v16|Any CPU.ActiveCfg = Release-v16|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Release-v16|Any CPU.Build.0 = Release-v16|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release-v16_1|Any CPU.ActiveCfg = Release-v16_1|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release-v16_1|Any CPU.Build.0 = Release-v16_1|Any CPU + {45508B90-440B-46DD-82CC-178196D9794E}.Release-v16|Any CPU.ActiveCfg = Release-v16|Any CPU + {45508B90-440B-46DD-82CC-178196D9794E}.Release-v16|Any CPU.Build.0 = Release-v16|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7C482A9E-BE25-4FF5-A5A0-8625D1BB01DD} + EndGlobalSection EndGlobal diff --git a/nsis/Extensions_vs15/extension.vsixmanifest b/nsis/Extensions_vs15/extension.vsixmanifest new file mode 100644 index 00000000..10c24ecb --- /dev/null +++ b/nsis/Extensions_vs15/extension.vsixmanifest @@ -0,0 +1,36 @@ + + + + + vdlogo.ico + vdlogo.ico + Visual D + Extension to provide support for the D programming language + + + + + + + + + + + + + + + + + + + NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + NuGet.VisualStudio.TemplateWizard + + + + + + + + diff --git a/nsis/visuald.nsi b/nsis/visuald.nsi index 36666884..43768476 100644 --- a/nsis/visuald.nsi +++ b/nsis/visuald.nsi @@ -257,6 +257,7 @@ Section "Visual Studio package" SecPackage !ifdef VDEXTENSIONS ${File} ..\bin\Release\vdextensions\ vdextensions.dll + ${File} ..\bin\Release\vdext15\ vdext15.dll !endif !ifdef DPARSER @@ -548,7 +549,7 @@ ${MementoSection} "Install in VS 2017" SecVS2017 ${AddItem} "$1${EXTENSION_DIR}\visuald.pkgdef" ${SetOutPath} "$1${EXTENSION_DIR}" - ${File} ..\nsis\Extensions_vs12\ extension.vsixmanifest + ${File} ..\nsis\Extensions_vs15\ extension.vsixmanifest ${File} ..\nsis\Extensions\ vdlogo.ico ${AddItem} "$1${EXTENSION_DIR}" @@ -596,7 +597,7 @@ ${MementoSection} "Install in VS 2019" SecVS2019 ${AddItem} "$1${EXTENSION_DIR}\visuald.pkgdef" ${SetOutPath} "$1${EXTENSION_DIR}" - ${File} ..\nsis\Extensions_vs12\ extension.vsixmanifest + ${File} ..\nsis\Extensions_vs15\ extension.vsixmanifest ${File} ..\nsis\Extensions\ vdlogo.ico ${AddItem} "$1${EXTENSION_DIR}" diff --git a/sdk/vsi.visualdproj b/sdk/vsi.visualdproj index 7efb384d..48f433b4 100644 --- a/sdk/vsi.visualdproj +++ b/sdk/vsi.visualdproj @@ -1939,6 +1939,8 @@ + + @@ -1999,6 +2001,9 @@ + + + diff --git a/tools/build_dcxxfilt.bat b/tools/build_dcxxfilt.bat index 41102a65..936615d6 100644 --- a/tools/build_dcxxfilt.bat +++ b/tools/build_dcxxfilt.bat @@ -3,7 +3,7 @@ rem unpack and configure binutils 2.25+ rem don't use spaces in path names! setlocal -if "%DMDINSTALLDIR%" == "" set DMDINSTALLDIR=c:\s\d\rainers +if "%DMDINSTALLDIR%" == "" set DMDINSTALLDIR=c:\d\dmd-2.087.0 set DMD=%DMDINSTALLDIR%\windows\bin\dmd if "%BINUTILS%" == "" set BINUTILS=c:\s\cpp\cxxfilt diff --git a/vdextensions/gotodef.cs b/vdextensions/gotodef.cs new file mode 100644 index 00000000..f3c9a96e --- /dev/null +++ b/vdextensions/gotodef.cs @@ -0,0 +1,574 @@ +// adapted from +// https://github.com/Microsoft/VS-PPT/blob/master/src/GoToDef/GoToDefMouseHandler.cs +// +// Productivity Power Tools for Visual Studio +// +// Copyright(c) Microsoft Corporation +// +// All rights reserved. +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software +// and associated documentation files (the "Software"), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial +// portions of the Software. +// +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.OLE.Interop; +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.Operations; +using Microsoft.VisualStudio.Text.Tagging; +using Microsoft.VisualStudio.Utilities; +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Windows; +using System.Windows.Input; + +namespace vdext15 +{ + public static class PredefinedTextViewRoles14 + { + // not in older versions of PredefinedTextViewRoles + public const string PreviewTextView = "ENHANCED_SCROLLBAR_PREVIEW"; + public const string EmbeddedPeekTextView = "EMBEDDED_PEEK_TEXT_VIEW"; + public const string CodeDefinitionView = "CODEDEFINITION"; + public const string Printable = "PRINTABLE"; + } + + [Export(typeof(IKeyProcessorProvider))] + [TextViewRole(PredefinedTextViewRoles.Document)] + [TextViewRole(PredefinedTextViewRoles14.EmbeddedPeekTextView)] + [ContentType("code")] + [Name("GotoDefVisualD")] + [Order(Before = "VisualStudioKeyboardProcessor")] + internal sealed class GoToDefKeyProcessorProvider : IKeyProcessorProvider + { + //[Import] + //private SVsServiceProvider _serviceProvider; + + public KeyProcessor GetAssociatedProcessor(IWpfTextView view) + { + //IVsExtensionManager manager = _serviceProvider.GetService(typeof(SVsExtensionManager)) as IVsExtensionManager; + //if (manager == null) + // return null; + // + //IInstalledExtension extension; + //manager.TryGetInstalledExtension("GoToDef", out extension); + //if (extension != null) + // return null; + + return view.Properties.GetOrCreateSingletonProperty(typeof(GoToDefKeyProcessor), + () => new GoToDefKeyProcessor(CtrlKeyState.GetStateForView(view))); + } + } + + [Export(typeof(EditorOptionDefinition))] + [Name(ControlClickOpensPeekOption.OptionName)] + public sealed class ControlClickOpensPeekOption : WpfViewOptionDefinition + { + public const string OptionName = "ControlClickOpensPeek"; + public readonly static EditorOptionKey OptionKey = new EditorOptionKey(ControlClickOpensPeekOption.OptionName); + + public override bool Default { get { return true; } } + + public override EditorOptionKey Key { get { return ControlClickOpensPeekOption.OptionKey; } } + } + + /// + /// The state of the control key for a given view, which is kept up-to-date by a combination of the + /// key processor and the mouse processor. + /// + internal sealed class CtrlKeyState + { + internal static CtrlKeyState GetStateForView(ITextView view) + { + return view.Properties.GetOrCreateSingletonProperty(typeof(CtrlKeyState), () => new CtrlKeyState()); + } + + private bool _enabled; + + internal bool Enabled + { + get + { + // Check and see if ctrl is down but we missed it somehow. + bool ctrlDown = (Keyboard.Modifiers & ModifierKeys.Control) != 0; + if (ctrlDown != _enabled) + Enabled = ctrlDown; + + return _enabled; + } + set + { + bool oldVal = _enabled; + _enabled = value; + if (oldVal != _enabled) + { + var temp = CtrlKeyStateChanged; + if (temp != null) + temp(this, new EventArgs()); + } + } + } + + internal event EventHandler CtrlKeyStateChanged; + } + + /// + /// Listen for the control key being pressed or released to update the CtrlKeyStateChanged for a view. + /// + internal sealed class GoToDefKeyProcessor : KeyProcessor + { + private CtrlKeyState _state; + + public GoToDefKeyProcessor(CtrlKeyState state) + { + _state = state; + } + + private void UpdateState(KeyEventArgs args) + { + _state.Enabled = (args.KeyboardDevice.Modifiers & ModifierKeys.Control) != 0; + } + + public override void PreviewKeyDown(KeyEventArgs args) + { + UpdateState(args); + } + + public override void PreviewKeyUp(KeyEventArgs args) + { + UpdateState(args); + } + } + + [Export(typeof(IMouseProcessorProvider))] + [TextViewRole(PredefinedTextViewRoles.Document)] + [TextViewRole(PredefinedTextViewRoles14.EmbeddedPeekTextView)] + [ContentType("code")] + [Name("GotoDefVisualD")] + [Order(Before = "WordSelection")] + internal sealed class GoToDefMouseHandlerProvider : IMouseProcessorProvider + { + [Import] + private IClassifierAggregatorService _aggregatorFactory; + + [Import] + private ITextStructureNavigatorSelectorService _navigatorService; + + [Import] + private SVsServiceProvider _globalServiceProvider; + + public IMouseProcessor GetAssociatedProcessor(IWpfTextView view) + { + var buffer = view.TextBuffer; + + IOleCommandTarget shellCommandDispatcher = GetShellCommandDispatcher(view); + + if (shellCommandDispatcher == null) + return null; + + //IInstalledExtension extension; + //manager.TryGetInstalledExtension("GoToDef", out extension); + //if (extension != null) + // return null; + + if (!view.TextBuffer.ContentType.IsOfType("d")) + return null; + + return new GoToDefMouseHandler(view, + shellCommandDispatcher, + _aggregatorFactory.GetClassifier(buffer), + _navigatorService.GetTextStructureNavigator(buffer), + CtrlKeyState.GetStateForView(view)); + } + + #region Private helpers + + /// + /// Get the SUIHostCommandDispatcher from the global service provider. + /// + private IOleCommandTarget GetShellCommandDispatcher(ITextView view) + { + return _globalServiceProvider.GetService(typeof(SUIHostCommandDispatcher)) as IOleCommandTarget; + } + + #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 + { + private IWpfTextView _view; + private CtrlKeyState _state; + private IClassifier _aggregator; + private ITextStructureNavigator _navigator; + private IOleCommandTarget _commandTarget; + + public GoToDefMouseHandler(IWpfTextView view, IOleCommandTarget commandTarget, + IClassifier aggregator, ITextStructureNavigator navigator, CtrlKeyState state) + { + _view = view; + _commandTarget = commandTarget; + _state = state; + _aggregator = aggregator; + _navigator = navigator; + + _state.CtrlKeyStateChanged += (sender, args) => + { + if (_state.Enabled) + this.TryHighlightItemUnderMouse(RelativeToView(Mouse.PrimaryDevice.GetPosition(_view.VisualElement))); + else + this.SetHighlightSpan(null); + }; + + // Some other points to clear the highlight span. + _view.LostAggregateFocus += (sender, args) => this.SetHighlightSpan(null); + _view.VisualElement.MouseLeave += (sender, args) => this.SetHighlightSpan(null); + } + + #region Mouse processor overrides + + // Remember the location of the mouse on left button down, so we only handle left button up + // if the mouse has stayed in a single location. + private Point? _mouseDownAnchorPoint; + + public override void PostprocessMouseLeftButtonDown(MouseButtonEventArgs e) + { + //register the mouse down only if control is being pressed + if (_state.Enabled) + { + _mouseDownAnchorPoint = RelativeToView(e.GetPosition(_view.VisualElement)); + } + } + + public override void PreprocessMouseMove(MouseEventArgs e) + { + if (!_mouseDownAnchorPoint.HasValue && _state.Enabled && e.LeftButton == MouseButtonState.Released) + { + TryHighlightItemUnderMouse(RelativeToView(e.GetPosition(_view.VisualElement))); + } + else if (_mouseDownAnchorPoint.HasValue) + { + // Check and see if this is a drag; if so, clear out the highlight. + var currentMousePosition = RelativeToView(e.GetPosition(_view.VisualElement)); + if (InDragOperation(_mouseDownAnchorPoint.Value, currentMousePosition)) + { + _mouseDownAnchorPoint = null; + this.SetHighlightSpan(null); + } + } + } + + private bool InDragOperation(Point anchorPoint, Point currentPoint) + { + // If the mouse up is more than a drag away from the mouse down, this is a drag + //the drag can happen also on the same row so just one of these condition should make the movement a drag + return Math.Abs(anchorPoint.X - currentPoint.X) >= SystemParameters.MinimumHorizontalDragDistance || + Math.Abs(anchorPoint.Y - currentPoint.Y) >= SystemParameters.MinimumVerticalDragDistance; + } + + public override void PreprocessMouseLeave(MouseEventArgs e) + { + _mouseDownAnchorPoint = null; + } + + public override void PreprocessMouseUp(MouseButtonEventArgs e) + { + if (_mouseDownAnchorPoint.HasValue && _state.Enabled) + { + var currentMousePosition = RelativeToView(e.GetPosition(_view.VisualElement)); + + if (!InDragOperation(_mouseDownAnchorPoint.Value, currentMousePosition)) + { + _state.Enabled = false; + + this.SetHighlightSpan(null); + _view.Selection.Clear(); + this.DispatchGoToDef(); + + e.Handled = true; + } + } + + _mouseDownAnchorPoint = null; + } + + + #endregion + + #region Private helpers + + private Point RelativeToView(Point position) + { + return new Point(position.X + _view.ViewportLeft, position.Y + _view.ViewportTop); + } + + private bool TryHighlightItemUnderMouse(Point position) + { + bool updated = false; + + try + { + var line = _view.TextViewLines.GetTextViewLineContainingYCoordinate(position.Y); + if (line == null) + return false; + + var bufferPosition = line.GetBufferPositionFromXCoordinate(position.X); + + if (!bufferPosition.HasValue) + return false; + + // Quick check - if the mouse is still inside the current underline span, we're already set. + var currentSpan = CurrentUnderlineSpan; + if (currentSpan.HasValue && currentSpan.Value.Contains(bufferPosition.Value)) + { + updated = true; + return true; + } + + + var extent = _navigator.GetExtentOfWord(bufferPosition.Value); + if (!extent.IsSignificant) + return false; + + // For C#, we ignore namespaces after using statements - GoToDef will fail for those. + if (_view.TextBuffer.ContentType.IsOfType("csharp")) + { + string lineText = bufferPosition.Value.GetContainingLine().GetText().Trim(); + if (lineText.StartsWith("using", StringComparison.OrdinalIgnoreCase)) + return false; + } + + // Now, check for valid classification type. C# and C++ (at least) classify the things we are interested + // in as either "identifier" or "user types" (though "identifier" will yield some false positives). VB, unfortunately, + // doesn't classify identifiers. + foreach (var classification in _aggregator.GetClassificationSpans(extent.Span)) + { + var name = classification.ClassificationType.Classification.ToLower(); + if ((name.Contains("identifier") || name.Contains("user types")) && + SetHighlightSpan(classification.Span)) + { + updated = true; + return true; + } + } + + // No update occurred, so return false. + return false; + } + finally + { + if (!updated) + SetHighlightSpan(null); + } + } + + private SnapshotSpan? CurrentUnderlineSpan + { + get + { + var classifier = UnderlineClassifierProvider.GetClassifierForView(_view); + if (classifier != null && classifier.CurrentUnderlineSpan.HasValue) + return classifier.CurrentUnderlineSpan.Value.TranslateTo(_view.TextSnapshot, SpanTrackingMode.EdgeExclusive); + else + return null; + } + } + + private bool SetHighlightSpan(SnapshotSpan? span) + { + var classifier = UnderlineClassifierProvider.GetClassifierForView(_view); + if (classifier != null) + { + if (span.HasValue) + Mouse.OverrideCursor = Cursors.Hand; + else + Mouse.OverrideCursor = null; + + classifier.SetUnderlineSpan(span); + return true; + } + + return false; + } + + private bool DispatchGoToDef() + { + bool showDefinitionsPeek = false; // _view.Options.GetOptionValue(ControlClickOpensPeekOption.OptionKey); + Guid cmdGroup = showDefinitionsPeek ? VSConstants.VsStd12 : VSConstants.GUID_VSStandardCommandSet97; + uint cmdID = showDefinitionsPeek ? (uint)VSConstants.VSStd12CmdID.PeekDefinition : (uint)VSConstants.VSStd97CmdID.GotoDefn; + + // Don't block until we've finished executing the command + int hr = _commandTarget.Exec(ref cmdGroup, + cmdID, + (uint)OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, + System.IntPtr.Zero, + System.IntPtr.Zero); + + return ErrorHandler.Succeeded(hr); + } + + #endregion + } + + #region Classification type/format exports + + [Export(typeof(EditorFormatDefinition))] + [ClassificationType(ClassificationTypeNames = "UnderlineClassificationVisualD")] + [Name("UnderlineClassificationFormatVisualD")] + [UserVisible(true)] + [Order(After = Priority.High)] + internal sealed class UnderlineFormatDefinition : ClassificationFormatDefinition + { + public UnderlineFormatDefinition() + { + this.DisplayName = "Visual D Goto Definition"; + this.TextDecorations = System.Windows.TextDecorations.Underline; + this.ForegroundColor = System.Windows.Media.Colors.LightSkyBlue; + } + } + + #endregion + + #region Provider definition + + [Export(typeof(IViewTaggerProvider))] + [ContentType("text")] + [TagType(typeof(ClassificationTag))] + internal class UnderlineClassifierProvider : IViewTaggerProvider + { + [Import] + internal IClassificationTypeRegistryService ClassificationRegistry; + + //[Import] + //private SVsServiceProvider _serviceProvider; + + [Export(typeof(ClassificationTypeDefinition))] + [Name("UnderlineClassificationVisualD")] + internal static ClassificationTypeDefinition underlineClassificationType; + + private static IClassificationType s_underlineClassification; + public static UnderlineClassifier GetClassifierForView(ITextView view) + { + if (s_underlineClassification == null) + return null; + + return view.Properties.GetOrCreateSingletonProperty(() => new UnderlineClassifier(view, s_underlineClassification)); + } + + public ITagger CreateTagger(ITextView textView, ITextBuffer buffer) where T : ITag + { + if (s_underlineClassification == null) + s_underlineClassification = ClassificationRegistry.GetClassificationType("UnderlineClassificationVisualD"); + + if (textView.TextBuffer != buffer) + return null; + + //IVsExtensionManager manager = _serviceProvider.GetService(typeof(SVsExtensionManager)) as IVsExtensionManager; + //if (manager == null) + // return null; + // + //IInstalledExtension extension; + //manager.TryGetInstalledExtension("GoToDef", out extension); + //if (extension != null) + // return null; + + return GetClassifierForView(textView) as ITagger; + } + } + + #endregion + + internal class UnderlineClassifier : ITagger + { + private IClassificationType _classificationType; + private ITextView _textView; + private SnapshotSpan? _underlineSpan; + + internal UnderlineClassifier(ITextView textView, IClassificationType classificationType) + { + _textView = textView; + _classificationType = classificationType; + _underlineSpan = null; + } + + #region Private helpers + + private void SendEvent(SnapshotSpan span) + { + var temp = this.TagsChanged; + if (temp != null) + temp(this, new SnapshotSpanEventArgs(span)); + } + + #endregion + + #region UnderlineClassification public members + + public SnapshotSpan? CurrentUnderlineSpan { get { return _underlineSpan; } } + + public void SetUnderlineSpan(SnapshotSpan? span) + { + var oldSpan = _underlineSpan; + _underlineSpan = span; + + if (!oldSpan.HasValue && !_underlineSpan.HasValue) + return; + + else if (oldSpan.HasValue && _underlineSpan.HasValue && oldSpan == _underlineSpan) + return; + + if (!_underlineSpan.HasValue) + { + this.SendEvent(oldSpan.Value); + } + else + { + SnapshotSpan updateSpan = _underlineSpan.Value; + if (oldSpan.HasValue) + updateSpan = new SnapshotSpan(updateSpan.Snapshot, + Span.FromBounds(Math.Min(updateSpan.Start, oldSpan.Value.Start), + Math.Max(updateSpan.End, oldSpan.Value.End))); + + this.SendEvent(updateSpan); + } + } + + #endregion + + public IEnumerable> GetTags(NormalizedSnapshotSpanCollection spans) + { + if (!_underlineSpan.HasValue || spans.Count == 0) + yield break; + + SnapshotSpan request = new SnapshotSpan(spans[0].Start, spans[spans.Count - 1].End); + SnapshotSpan underline = _underlineSpan.Value.TranslateTo(request.Snapshot, SpanTrackingMode.EdgeInclusive); + if (underline.IntersectsWith(request)) + { + yield return new TagSpan(underline, new ClassificationTag(_classificationType)); + } + } + + public event EventHandler TagsChanged; + } +} diff --git a/vdextensions/vdext15.cs b/vdextensions/vdext15.cs new file mode 100644 index 00000000..db96b2d8 --- /dev/null +++ b/vdextensions/vdext15.cs @@ -0,0 +1,38 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2016 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +using System; +using System.Runtime.InteropServices; // DllImport + +namespace vdext15 +{ + public class IID + { + public const string IVisualDHelper15 = "002a2de9-8bb6-484d-9915-7e4ad4084715"; + public const string VisualDHelper15 = "002a2de9-8bb6-484d-AA15-7e4ad4084715"; + } + + [ComVisible(true), Guid(IID.IVisualDHelper15)] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IVisualDHelper15 + { + } + + [ComVisible(true), Guid(IID.VisualDHelper15)] + [ClassInterface(ClassInterfaceType.None)] + public partial class VisualDHelper15 : IVisualDHelper15 + { + public VisualDHelper15() + { + } + + public void Dispose() + { + } + } +} diff --git a/vdextensions/vdext15.csproj b/vdextensions/vdext15.csproj new file mode 100644 index 00000000..a5e85fac --- /dev/null +++ b/vdextensions/vdext15.csproj @@ -0,0 +1,130 @@ + + + + Debug + AnyCPU + 10.0.0 + 2.0 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3} + Library + vdext15 + vdext15 + assembly + c:\Windows\Microsoft.NET\assembly\GAC_MSIL + ..\bin\$(Configuration)\$(MSBuildProjectName)\obj\ + v4.6 + + + + True + full + False + ..\bin\Debug\vdext15\any\ + DEBUG; + prompt + 4 + False + false + + + full + True + ..\bin\Release\vdext15\any\ + prompt + 4 + False + true + false + + + true + ..\bin\Debug\vdext15\ + DEBUG; + full + x86 + prompt + MinimumRecommendedRules.ruleset + false + + + true + ..\bin\Release\vdext15\ + true + full + x86 + prompt + MinimumRecommendedRules.ruleset + false + + + + False + + + + False + $(GAC_HintPath)\Microsoft.VisualStudio.CoreUtility\vs15\Microsoft.VisualStudio.CoreUtility.dll + + + False + $(GAC_HintPath)\Microsoft.VisualStudio.Editor\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Editor.dll + + + False + $(GAC_HintPath)\Microsoft.VisualStudio.Shell.15.0\vs15\Microsoft.VisualStudio.Shell.15.0.dll + + + False + $(GAC_HintPath)\Microsoft.VisualStudio.Shell.Framework\vs15\Microsoft.VisualStudio.Shell.Framework.dll + + + False + $(GAC_HintPath)\Microsoft.VisualStudio.Text.Data\vs15\Microsoft.VisualStudio.Text.Data.dll + + + False + $(GAC_HintPath)\Microsoft.VisualStudio.Text.Logic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Text.Logic.dll + + + False + $(GAC_HintPath)\Microsoft.VisualStudio.Text.UI\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Text.UI.dll + + + False + $(GAC_HintPath)\Microsoft.VisualStudio.Text.UI.Wpf\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Text.UI.Wpf.dll + + + False + $(GAC_HintPath)\Microsoft.VisualStudio.Utilities\vs15\Microsoft.VisualStudio.Utilities.dll + + + + + + + + + + + + + + + + C:\Windows\assembly\GAC\Microsoft.VisualStudio.TextManager.Interop\7.1.40304.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.TextManager.Interop.dll + + + C:\Windows\assembly\GAC\Microsoft.VisualStudio.OLE.Interop\7.1.40304.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.OLE.Interop.dll + + + C:\Windows\assembly\GAC\Microsoft.VisualStudio.Shell.Interop\7.1.40304.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Shell.Interop.dll + + + + + + + + + + \ No newline at end of file diff --git a/vdextensions/vdextensions.sln b/vdextensions/vdextensions.sln index 1fae8c70..3dcc769a 100644 --- a/vdextensions/vdextensions.sln +++ b/vdextensions/vdextensions.sln @@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DParser2", "..\vdc\abothe\P EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisualDWizard", "..\vdwizard\VisualDWizard.csproj", "{32171DBC-DB3B-401A-B3F7-06356D6167EE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vdext15", "vdext15.csproj", "{64534E86-A08A-4F9A-8DB1-A5C280773BA3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -75,8 +77,8 @@ Global {45508B90-440B-46DD-82CC-178196D9794E}.Debug|Any CPU.Build.0 = Debug|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Debug|x86.ActiveCfg = Debug|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Debug|x86.Build.0 = Debug|Any CPU + {45508B90-440B-46DD-82CC-178196D9794E}.Debug|x86.ActiveCfg = Debug|x86 + {45508B90-440B-46DD-82CC-178196D9794E}.Debug|x86.Build.0 = Debug|x86 {45508B90-440B-46DD-82CC-178196D9794E}.Debug-Linux|Any CPU.ActiveCfg = Debug-v14|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug-Linux|Any CPU.Build.0 = Debug-v14|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug-Linux|Mixed Platforms.ActiveCfg = Debug-v14|Any CPU @@ -86,26 +88,26 @@ Global {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v14|Any CPU.Build.0 = Debug-v14|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v14|Mixed Platforms.ActiveCfg = Debug-v14|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v14|Mixed Platforms.Build.0 = Debug-v14|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v14|x86.ActiveCfg = Debug-v14|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v14|x86.Build.0 = Debug-v14|Any CPU + {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v14|x86.ActiveCfg = Debug-v14|x86 + {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v14|x86.Build.0 = Debug-v14|x86 {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|Any CPU.ActiveCfg = Debug-v16|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|Any CPU.Build.0 = Debug-v16|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|Mixed Platforms.ActiveCfg = Debug-v14|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|Mixed Platforms.Build.0 = Debug-v14|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|x86.ActiveCfg = Debug-v14|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|x86.Build.0 = Debug-v14|Any CPU + {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|x86.ActiveCfg = Debug-v16|x86 + {45508B90-440B-46DD-82CC-178196D9794E}.Debug-v16|x86.Build.0 = Debug-v16|x86 {45508B90-440B-46DD-82CC-178196D9794E}.Release|Any CPU.ActiveCfg = Release|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release|Any CPU.Build.0 = Release|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Release|x86.ActiveCfg = Release|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Release|x86.Build.0 = Release|Any CPU + {45508B90-440B-46DD-82CC-178196D9794E}.Release|x86.ActiveCfg = Release|x86 + {45508B90-440B-46DD-82CC-178196D9794E}.Release|x86.Build.0 = Release|x86 {45508B90-440B-46DD-82CC-178196D9794E}.Release-v14|Any CPU.ActiveCfg = Release-v14|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release-v14|Any CPU.Build.0 = Release-v14|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release-v14|Mixed Platforms.ActiveCfg = Release-v14|Any CPU {45508B90-440B-46DD-82CC-178196D9794E}.Release-v14|Mixed Platforms.Build.0 = Release-v14|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Release-v14|x86.ActiveCfg = Release-v14|Any CPU - {45508B90-440B-46DD-82CC-178196D9794E}.Release-v14|x86.Build.0 = Release-v14|Any CPU + {45508B90-440B-46DD-82CC-178196D9794E}.Release-v14|x86.ActiveCfg = Release-v14|x86 + {45508B90-440B-46DD-82CC-178196D9794E}.Release-v14|x86.Build.0 = Release-v14|x86 {7B4FB722-905A-4851-8399-1E0F3361CCD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B4FB722-905A-4851-8399-1E0F3361CCD8}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B4FB722-905A-4851-8399-1E0F3361CCD8}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 @@ -214,6 +216,42 @@ Global {32171DBC-DB3B-401A-B3F7-06356D6167EE}.Release-v14|Mixed Platforms.Build.0 = Release|Any CPU {32171DBC-DB3B-401A-B3F7-06356D6167EE}.Release-v14|x86.ActiveCfg = Release|Any CPU {32171DBC-DB3B-401A-B3F7-06356D6167EE}.Release-v14|x86.Build.0 = Release|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|x86.ActiveCfg = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug|x86.Build.0 = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-Linux|Any CPU.ActiveCfg = Debug|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-Linux|Any CPU.Build.0 = Debug|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-Linux|Mixed Platforms.ActiveCfg = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-Linux|Mixed Platforms.Build.0 = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-Linux|x86.ActiveCfg = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-Linux|x86.Build.0 = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v14|Any CPU.ActiveCfg = Debug|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v14|Any CPU.Build.0 = Debug|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v14|Mixed Platforms.ActiveCfg = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v14|Mixed Platforms.Build.0 = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v14|x86.ActiveCfg = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v14|x86.Build.0 = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v16|Any CPU.ActiveCfg = Debug|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v16|Any CPU.Build.0 = Debug|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v16|Mixed Platforms.ActiveCfg = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v16|Mixed Platforms.Build.0 = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v16|x86.ActiveCfg = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Debug-v16|x86.Build.0 = Debug|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|Any CPU.Build.0 = Release|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|Mixed Platforms.Build.0 = Release|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|x86.ActiveCfg = Release|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release|x86.Build.0 = Release|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release-v14|Any CPU.ActiveCfg = Release|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release-v14|Any CPU.Build.0 = Release|Any CPU + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release-v14|Mixed Platforms.ActiveCfg = Release|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release-v14|Mixed Platforms.Build.0 = Release|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release-v14|x86.ActiveCfg = Release|x86 + {64534E86-A08A-4F9A-8DB1-A5C280773BA3}.Release-v14|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/visuald_vs10.sln b/visuald_vs10.sln index 8de0849d..9fd41e75 100644 --- a/visuald_vs10.sln +++ b/visuald_vs10.sln @@ -299,6 +299,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VCItems", "VCItems", "{1F0F visuald\Templates\VCItems\ditems.vsdir = visuald\Templates\VCItems\ditems.vsdir EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions_vs12", "Extensions_vs12", "{BDE81C48-A33E-4852-A49F-AD0080C4B400}" + ProjectSection(SolutionItems) = preProject + nsis\Extensions_vs12\extension.vsixmanifest = nsis\Extensions_vs12\extension.vsixmanifest + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions_vs15", "Extensions_vs15", "{8A87ACE9-7B7C-4BC6-B9BD-3664429A8A5E}" + ProjectSection(SolutionItems) = preProject + nsis\Extensions_vs15\extension.vsixmanifest = nsis\Extensions_vs15\extension.vsixmanifest + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug COFF32|Win32 = Debug COFF32|Win32 @@ -655,6 +665,8 @@ Global {6DE93AA1-4EBB-40DF-8C3D-6B060F2F045A} = {1F473A70-B5E1-4D56-A9F3-E87D69886621} {6FDF165B-4643-4059-8B50-70B6E4A2D99C} = {AC054091-8D8F-4393-B3C5-AB67980B80EE} {1F0F6731-D58B-4F54-A330-C4C1011F76EE} = {AC054091-8D8F-4393-B3C5-AB67980B80EE} + {BDE81C48-A33E-4852-A49F-AD0080C4B400} = {7F391DE3-9620-4A98-B05D-4181924A9D15} + {8A87ACE9-7B7C-4BC6-B9BD-3664429A8A5E} = {7F391DE3-9620-4A98-B05D-4181924A9D15} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BAF35E81-511D-4170-B7D0-594E5DE3886A} From 6edab7ec93ed44e9e5a078c4f38f44df7f52ef02 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 6 Sep 2019 17:48:58 +0200 Subject: [PATCH 02/73] add missing file, add some folders to .gitignore --- .gitignore | 2 ++ vdc/abothe/VDServer.sln | 3 --- vdextensions/Properties/AssemblyInfo15.cs | 33 +++++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 vdextensions/Properties/AssemblyInfo15.cs diff --git a/.gitignore b/.gitignore index ee88d51d..7e619a34 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ vdextensions/obj /msbuild/dbuild/.vs /test .vs +/msbuild/dbuild/assemblies +/vdextensions/assembly diff --git a/vdc/abothe/VDServer.sln b/vdc/abothe/VDServer.sln index 6c7fe83a..bf70e853 100644 --- a/vdc/abothe/VDServer.sln +++ b/vdc/abothe/VDServer.sln @@ -70,7 +70,4 @@ Global GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {62BBA23E-674A-4160-8500-54A307388C95} EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = vdcomserver\vdcomserver.csproj - EndGlobalSection EndGlobal diff --git a/vdextensions/Properties/AssemblyInfo15.cs b/vdextensions/Properties/AssemblyInfo15.cs new file mode 100644 index 00000000..668f0b3c --- /dev/null +++ b/vdextensions/Properties/AssemblyInfo15.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("vdext15")] +[assembly: AssemblyDescription("Extension to the Visual D package for Visual Studio 2017 and later")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Rainer Schuetze")] +[assembly: AssemblyProduct("vdext15")] +[assembly: AssemblyCopyright("Copyright 2019 Rainer Schuetze")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] From 8f276214167197ffb06c150b2e3d99f7830f88c3 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 20 Oct 2017 13:51:21 +0200 Subject: [PATCH 03/73] use dmd for semantic analysis --- tools/tracegc.d | 1091 +++++++++++++++++++++++ vdc/ast/mod.d | 65 +- vdc/ddmderrors.d | 197 +++++ vdc/ddmdlib.d | 5 + vdc/ddmdmars.d | 23 + vdc/ddmdrmem.d | 46 + vdc/dmdicon.ico | Bin 0 -> 34494 bytes vdc/dmdserver.d | 1734 +++++++++++++++++++++++++++++++++++++ vdc/dmdserver.idl | 25 + vdc/dmdserver.rc | 85 ++ vdc/dmdserver.visualdproj | 1223 ++++++++++++++++++++++++++ vdc/ivdserver.idl | 42 + vdc/parser.visualdproj | 4 +- vdc/semantic.d | 205 +---- vdc/semanticopt.d | 238 +++++ vdc/vdserver.d | 2 +- vdc/vdserver.idl | 31 +- vdc/vdserver.visualdproj | 5 +- vdc/vdserverfactory.d | 27 +- visuald/dllmain.d | 1 + visuald/dpackage.d | 2 +- visuald/vdserverclient.d | 2 + visuald_vs10.sln | 50 +- 23 files changed, 4820 insertions(+), 283 deletions(-) create mode 100644 tools/tracegc.d create mode 100644 vdc/ddmderrors.d create mode 100644 vdc/ddmdlib.d create mode 100644 vdc/ddmdmars.d create mode 100644 vdc/ddmdrmem.d create mode 100644 vdc/dmdicon.ico create mode 100644 vdc/dmdserver.d create mode 100644 vdc/dmdserver.idl create mode 100644 vdc/dmdserver.rc create mode 100644 vdc/dmdserver.visualdproj create mode 100644 vdc/ivdserver.idl create mode 100644 vdc/semanticopt.d diff --git a/tools/tracegc.d b/tools/tracegc.d new file mode 100644 index 00000000..0f22db9b --- /dev/null +++ b/tools/tracegc.d @@ -0,0 +1,1091 @@ +module tracegc; + +import core.stdc.string; + +//version = traceGC; + +// tiny helper to clear a page of the stack below the current stack pointer to avoid false pointers there +void wipeStack() +{ + char[4096] data = void; + memset (data.ptr, 0xff, 4096); +} + +version(traceGC): +import core.sys.windows.windows; +import core.stdc.stdio; +import gc.impl.conservative.gc; +import core.thread; + +extern(C) alias _CRT_ALLOC_HOOK = int function(int, void *, size_t, int, long, const(char) *, int); + +extern(C) _CRT_ALLOC_HOOK _CrtSetAllocHook(_CRT_ALLOC_HOOK _PfnNewHook); + +__gshared _CRT_ALLOC_HOOK _prevHook; + +extern(C) int _CRT_allocHook(int op, void *p, size_t size, int nBlockUse, long lRequest, const(char) *filename, int line) +{ + import core.sys.windows.stacktrace; + + if (!filename && op == 1) // alloc hook + { + if (StackAddrInfo* ai = traceAndResolve(4)) + { + filename = stringBuffer.ptr + ai.filenameOff; + line = ai.line; + + version(Win64) + { + // tweaked to the VC2013 debug runtime + const(char)** patchFilename = &filename + 11; + *patchFilename = filename; + + int* patchLine = &line + 22; + *patchLine = line; + } + } + } + if (_prevHook) + return _prevHook(op, p, size, nBlockUse, lRequest, filename, line); + return 1; +} + +extern(Windows) void OutputDebugStringA(LPCSTR) nothrow; + +alias RtlCaptureStackBackTraceFunc = extern(Windows) USHORT function(ULONG FramesToSkip, ULONG FramesToCapture, PVOID *BackTrace, PULONG BackTraceHash) nothrow; + +private __gshared RtlCaptureStackBackTraceFunc RtlCaptureStackBackTrace; + +extern(Windows) USHORT NoCaptureStackBackTrace(ULONG FramesToSkip, ULONG FramesToCapture, PVOID *BackTrace, PULONG BackTraceHash) nothrow +{ + return 0; +} + +void initRtlCaptureStackBackTrace() +{ + if (RtlCaptureStackBackTrace is null) + { + RtlCaptureStackBackTrace = &NoCaptureStackBackTrace; + + import core.sys.windows.dbghelp; + auto dbghelp = DbgHelp.get(); + if(dbghelp is null) + return; // dbghelp.dll not available + + if (auto kernel32Handle = LoadLibraryA("kernel32.dll")) + RtlCaptureStackBackTrace = cast(RtlCaptureStackBackTraceFunc) GetProcAddress(kernel32Handle, "RtlCaptureStackBackTrace"); + + HANDLE hProcess = GetCurrentProcess(); + + DWORD symOptions = dbghelp.SymGetOptions(); + symOptions |= SYMOPT_LOAD_LINES; + symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS; + symOptions |= SYMOPT_DEFERRED_LOAD; + symOptions = dbghelp.SymSetOptions( symOptions ); + + debug(PRINTF) printf("Search paths: %s\n", generateSearchPath().ptr); + + if (!dbghelp.SymInitialize(hProcess, null, TRUE)) + return; + + //dbghelp.SymRegisterCallback64(hProcess, &FixupDebugHeader, 0); + } +} + +StackAddrInfo* traceAndResolve(size_t skip) +{ + initRtlCaptureStackBackTrace(); + + size_t[63] buffer = void; // On windows xp the sum of "frames to skip" and "frames to capture" can't be greater then 63 + auto backtraceLength = RtlCaptureStackBackTrace(cast(ULONG)skip, cast(ULONG)(buffer.length - skip), cast(void**)buffer.ptr, null); + + for (size_t p = 0; p < backtraceLength; p++) + { + StackAddrInfo* ai = resolveAddr(buffer[p]); + if (ai.line != uint.max) + return ai; + } + return null; +} + +void initTraceMalloc() +{ + version(CRuntime_Microsoft) + _prevHook = _CrtSetAllocHook(&_CRT_allocHook); +} + +__gshared char[1 << 20] stringBuffer; +__gshared size_t stringBufferPos; + +uint findOrAddString(const char* str) +{ + size_t len = strlen(str); + uint p = 0; + while (p < stringBufferPos) + { + size_t plen = strlen(stringBuffer.ptr + p); + if (plen == len && strcmp (stringBuffer.ptr + p, str) == 0) + return p; + p += plen + 1; + } + + stringBufferPos += len + 1; + assert(stringBufferPos <= stringBuffer.length); + + stringBuffer[p .. stringBufferPos] = str[0 .. len + 1]; + return p; +} + +struct StackAddrInfo +{ + size_t pc; + uint filenameOff; + uint line; +} + +__gshared StackAddrInfo addrInfo[1 << 16]; +__gshared size_t addrInfoPos; + +StackAddrInfo* findOrAddAddr(size_t pc) nothrow +{ + for (size_t p = 0; p < addrInfoPos; p++) + if (addrInfo[p].pc == pc) + return addrInfo.ptr + p; + assert(addrInfoPos < addrInfo.length); + addrInfo[addrInfoPos].pc = pc; + return addrInfo.ptr + addrInfoPos++; +} + +StackAddrInfo* resolveAddr(size_t pc) nothrow +{ + StackAddrInfo* ai = findOrAddAddr(pc); + if (ai.line) + return ai; + + ai.line = uint.max; + + try + { + import core.sys.windows.dbghelp; + auto dbghelp = DbgHelp.get(); + assert(dbghelp); + + HANDLE hProcess = GetCurrentProcess(); + + DWORD disp; + IMAGEHLP_LINEA64 line = void; + line.SizeOfStruct = IMAGEHLP_LINEA64.sizeof; + + if (dbghelp.SymGetLineFromAddr64(hProcess, pc, &disp, &line)) + { + if (validFilename(line.FileName)) + { + ai.filenameOff = findOrAddString(line.FileName); + ai.line = line.LineNumber > 0 ? line.LineNumber : 1; + } + } + } + catch(Exception) + { + } + return ai; +} + +bool validFilename(const(char)* fn) +{ + if (!fn || fn[0] == 'f') + return false; + + size_t flen = strlen(fn); + static immutable string[] excl = + [ + r"\object.d", + r"\rt\lifetime.d", + r"\rt\aaA.d", + r"\rt\util\container\common.d", + r"\rt\util\container\treap.d", + r"\gc\proxy.d", + r"\core\memory.d", + r"\std\array.d", + r"\ddmd\root\rmem.d", + r"\ddmd\root\array.d", + r"\ddmd\root\aav.d", + r"\ddmd\root\outbuffer.d", + r"\ddmd\root\stringtable.d", + r"\stdext\com.d", + r"\ddmdrmem.d", + ]; + foreach (ex; excl) + if (flen > ex.length && fn[flen - ex.length .. flen] == ex) + return false; + + return true; +} + +//////////////////////////////////////////////////////////// + +import gc.gcinterface; +import gc.os; +import core.exception; + +class GCTraceProxy : GC +{ + GC gc; + + void Dtor() + { + gc.Dtor(); + } + + void enable() + { + gc.enable(); + } + + void disable() + { + gc.disable(); + } + + void collect() nothrow + { + gc.collect(); + } + + void collectNoStack() nothrow + { + gc.collectNoStack(); + } + + void minimize() nothrow + { + gc.minimize(); + } + + uint getAttr(void* p) nothrow + { + return gc.getAttr(p); + } + + uint setAttr(void* p, uint mask) nothrow + { + return gc.setAttr(p, mask); + } + + uint clrAttr(void* p, uint mask) nothrow + { + return gc.clrAttr(p, mask); + } + + void* malloc(size_t size, uint bits, const TypeInfo ti) nothrow + { + void* p = gc.malloc(size, bits, ti); + traceAlloc(p); + return p; + } + + BlkInfo qalloc(size_t size, uint bits, const TypeInfo ti) nothrow + { + BlkInfo bi = gc.qalloc(size, bits, ti); + traceAlloc(bi.base); + return bi; + } + + void* calloc(size_t size, uint bits, const TypeInfo ti) nothrow + { + void* p = gc.calloc(size, bits, ti); + traceAlloc(p); + return p; + } + + void* realloc(void* p, size_t size, uint bits, const TypeInfo ti) nothrow + { + void* q = gc.realloc(p, size, bits, ti); + traceAlloc(q); + return q; + } + + size_t extend(void* p, size_t minsize, size_t maxsize, const TypeInfo ti) nothrow + { + return gc.extend(p, minsize, maxsize, ti); + } + + size_t reserve(size_t size) nothrow + { + return gc.reserve(size); + } + + void free(void* p) nothrow + { + gc.free(p); + } + + void* addrOf(void* p) nothrow + { + return gc.addrOf(p); + } + + size_t sizeOf(void* p) nothrow + { + return gc.sizeOf(p); + } + + BlkInfo query(void* p) nothrow + { + return gc.query(p); + } + + core.memory.GC.Stats stats() nothrow + { + return gc.stats(); + } + + void addRoot(void* p) nothrow @nogc + { + return gc.addRoot(p); + } + + void removeRoot(void* p) nothrow @nogc + { + return gc.removeRoot(p); + } + + @property RootIterator rootIter() @nogc + { + return gc.rootIter(); + } + + void addRange(void* p, size_t sz, const TypeInfo ti) nothrow @nogc + { + return gc.addRange(p, sz, ti); + } + + void removeRange(void* p) nothrow @nogc + { + return gc.removeRange(p); + } + + @property RangeIterator rangeIter() @nogc + { + return gc.rangeIter(); + } + + void runFinalizers(in void[] segment) nothrow + { + return gc.runFinalizers(segment); + } + + bool inFinalizer() nothrow + { + return gc.inFinalizer(); + } + + TraceBuffer traceBuffer; +} + +/////////////////////////////////////////////////////////// +static struct TraceEntry +{ + void* addr; + size_t[15] buffer; + + StackAddrInfo* resolve() nothrow + { + for (size_t sp = 0; sp < buffer.length && buffer[sp]; sp++) + { + StackAddrInfo* ai = resolveAddr(buffer[sp]); + if (ai.line != uint.max) + return ai; + } + return null; + } +} + +static struct Range +{ + TraceEntry* _entries; + size_t _length; + size_t _capacity; +} + +static struct AddrTracePair +{ + void* addr; + TraceEntry* entry; +} + +size_t addrHash(void* addr, size_t mask) nothrow +{ + size_t hash = cast(size_t)addr; + hash = (hash >> 4) ^ (hash >> 20) ^ (hash >> 30); + return hash & mask; +} + +static struct TraceBuffer +{ +nothrow: + void reset() + { + _length = 0; + os_mem_unmap(_p, _cap * Range.sizeof); + _p = null; + _cap = 0; + } + + void pushEntry(ref TraceEntry te) + { + if (!_length || _p[_length-1]._length >= _p[_length-1]._capacity) + newRange(); + + _p[_length-1]._entries[_p[_length-1]._length++] = te; + } + + TraceEntry* findTraceEntry(void* addr) + { + foreach_reverse (ref rng; _p[0.._length]) + foreach_reverse (ref te; rng._entries[0..rng._length]) + if (te.addr == addr) + return &te; + return null; + } + + AddrTracePair[] createTraceMap() + { + size_t n = numEntries(); + if (!n) + return null; + // next or same power of 2 + while (n & (n - 1)) + n += (n & -n); // add lowest bit + n = n + n; + auto arr = cast(AddrTracePair*)os_mem_map(n * AddrTracePair.sizeof); + if (!arr) + onOutOfMemoryErrorNoGC(); + memset(arr, 0, n * AddrTracePair.sizeof); + + foreach_reverse (ref rng; _p[0.._length]) + foreach_reverse (ref te; rng._entries[0..rng._length]) + { + // insert with quadratic probing + size_t k = addrHash(te.addr, n - 1); + for (size_t j = 1; arr[k].addr !is te.addr; j++) + { + if (arr[k].addr is null) + { + arr[k].addr = te.addr; + arr[k].entry = &te; + break; + } + k = (k + j) & (n - 1); + } + } + return arr[0..n]; + } + + void deleteTraceMap(AddrTracePair[] arr) + { + if (arr.ptr) + os_mem_unmap(arr.ptr, arr.length * AddrTracePair.sizeof); + } + + TraceEntry* findTraceEntry(AddrTracePair[] arr, void* addr) + { + // search with quadratic probing + size_t k = addrHash(addr, arr.length - 1); + size_t j = 1; + while (arr[k].addr != addr) + { + if (arr[k].addr is null) + return null; + k = (k + j) & (arr.length - 1); + j++; + } + return arr[k].entry; + } + + void newRange() + { + if (_length == _cap) + grow(); + + enum entriesPerRange = 64 * 1024; // Windows VirtualAlloc granularity + _p[_length]._entries = cast(TraceEntry*)os_mem_map(entriesPerRange * TraceEntry.sizeof); + _p[_length]._capacity = entriesPerRange; + _p[_length]._length = 0; + if (_p[_length]._entries is null) + onOutOfMemoryErrorNoGC(); + _length++; + } + + size_t numEntries() + { + size_t sum = 0; + for (size_t r = 0; r < _length; r++) + sum += _p[r]._length; + return sum; + } + + size_t memUsage() + { + size_t sum = _cap * Range.sizeof; + for (size_t r = 0; r < _length; r++) + sum += _p[r]._capacity * TraceEntry.sizeof; + return sum; + } + +private: + void grow() + { + enum initSize = 64 * 1024; // Windows VirtualAlloc granularity + immutable ncap = _cap ? 2 * _cap : initSize / Range.sizeof; + auto p = cast(Range*)os_mem_map(ncap * Range.sizeof); + if (p is null) + onOutOfMemoryErrorNoGC(); + + p[0 .. _length] = _p[0 .. _length]; + os_mem_unmap(_p, _cap * Range.sizeof); + + _p = p; + _cap = ncap; + } + + size_t _length; + Range* _p; + size_t _cap; +} + +import core.demangle; +extern pragma(mangle, mangle!GC("gc.proxy.instance")) __gshared GC gc_instance; + +__gshared GCTraceProxy tracer = new GCTraceProxy; + +extern(C) void gc_init() +{ + import gc.config; + + config.initialize(); + ConservativeGC.initialize(gc_instance); + insertGCTracer(); + thread_init(); +} + +extern(C) void gc_term() +{ + //gc_instance.collectNoStack(); // not really a 'collect all' -- still scans static data area, roots, and ranges. + + thread_term(); + removeGCTracer(); + ConservativeGC.finalize(gc_instance); +} + +void insertGCTracer() +{ + initRtlCaptureStackBackTrace(); + + tracer.gc = gc_instance; + gc_instance = tracer; +} + +void removeGCTracer() +{ + gc_instance = tracer.gc; +} + +void traceAlloc(void* addr) nothrow +{ + TraceEntry te; + + te.addr = addr; + auto backtraceLength = RtlCaptureStackBackTrace(2, cast(ULONG)te.buffer.length, cast(void**)te.buffer.ptr, null); + + tracer.traceBuffer.pushEntry(te); +} + +extern(C) void dumpGC() +{ + dumpGC(tracer.gc); +} + +void dumpAddr(AddrTracePair[] traceMap, void* addr, size_t size) +{ + char buf[256]; + + const(char)* filename; + int line; + if (auto te = tracer.traceBuffer.findTraceEntry(traceMap, addr)) + { + if (auto ai = te.resolve()) + { + filename = stringBuffer.ptr + ai.filenameOff; + line = ai.line; + addAddrInfoStat(ai, size); + } + else + filename = ": "; + } + else + filename = ": "; + + gc.impl.conservative.gc.printf("%s(%d): %p %llx\n", filename, line, addr, cast(long) size); + //sprintf(buf.ptr, "%s(%d): %p %llx\n", filename, line, addr, cast(long) size); + //OutputDebugStringA(buf.ptr); +} + +struct AddrInfoStat +{ + @property ai() const nothrow { return cast(StackAddrInfo*) _ai; } + size_t _ai; // pretend it is not a pointer + size_t count; + size_t size; +} + +__gshared AddrInfoStat[1 << 13] addrInfoStat; + +void addAddrInfoStat(StackAddrInfo* ai, size_t size) +{ + // search with quadratic probing + size_t k = addrHash(ai, addrInfoStat.length - 1); + size_t j = 1; + while (addrInfoStat[k].ai != ai) + { + if (addrInfoStat[k].ai is null) + { + addrInfoStat[k]._ai = cast(size_t)ai; + addrInfoStat[k].count = 1; + addrInfoStat[k].size = size; + return; + } + k = (k + j) & (addrInfoStat.length - 1); + j++; + } + addrInfoStat[k].count++; + addrInfoStat[k].size += size; +} + +void dumpAddrInfoStat() +{ + char buf[256]; + + OutputDebugStringA("Dump combined by stack location:\n"); + + foreach(ref info; addrInfoStat) + if (info.ai) + { + const(char)* filename = stringBuffer.ptr + info.ai.filenameOff; + sprintf(buf.ptr, "%s(%d): %lld allocs %llx bytes\n", filename, info.ai.line, cast(long)info.count, cast(long)info.size); + OutputDebugStringA(buf.ptr); + } + +} + +/////////////////////////////////////////////////////////////// +import rt.util.container.hashtab; + +void collectReferences(ConservativeGC cgc, ref HashTab!(void*, void*) references, ref HashTab!(void*, size_t) objects) +{ + auto gcx = cgc.gcx; + + cgc.gcLock.lock(); + auto pooltable = gcx.pooltable; + + alias ScanRange = gc.gcinterface.Range; + + Gcx.ToScanStack toscan; + + /** + * Search a range of memory values and mark any pointers into the GC pool. + */ + void mark(void *pbot, void *ptop) scope nothrow + { + void **p1 = cast(void **)pbot; + void **p2 = cast(void **)ptop; + + // limit the amount of ranges added to the toscan stack + enum FANOUT_LIMIT = 32; + size_t stackPos; + ScanRange[FANOUT_LIMIT] stack = void; + + Lagain: + size_t pcache = 0; + + // let dmd allocate a register for this.pools + const minAddr = pooltable.minAddr; + const maxAddr = pooltable.maxAddr; + + //printf("marking range: [%p..%p] (%#zx)\n", p1, p2, cast(size_t)p2 - cast(size_t)p1); + Lnext: + for (; p1 < p2; p1++) + { + auto p = *p1; + + //if (log) debug(PRINTF) printf("\tmark %p\n", p); + if (p >= minAddr && p < maxAddr) + { + if ((cast(size_t)p & ~cast(size_t)(PAGESIZE-1)) == pcache) + continue; + + Pool* pool = pooltable.findPool(p); + if (!pool) + continue; + + size_t offset = cast(size_t)(p - pool.baseAddr); + size_t biti = void; + size_t pn = offset / PAGESIZE; + Bins bin = cast(Bins)pool.pagetable[pn]; + void* base = void; + + //debug(PRINTF) printf("\t\tfound pool %p, base=%p, pn = %zd, bin = %d, biti = x%x\n", pool, pool.baseAddr, pn, bin, biti); + + // Adjust bit to be at start of allocated memory block + if (bin < B_PAGE) + { + // We don't care abou setting pointsToBase correctly + // because it's ignored for small object pools anyhow. + auto offsetBase = offset & notbinsize[bin]; + biti = offsetBase >> pool.shiftBy; + base = pool.baseAddr + offsetBase; + //debug(PRINTF) printf("\t\tbiti = x%x\n", biti); + + if (!pool.mark.set(biti) && !pool.noscan.test(biti)) { + references[base] = p1; + objects[base] = binsize[bin]; + debug(COLLECT_PRINTF) printf("\t\tmark %p -> %p, off=%p\n", p1, base, p - base); + stack[stackPos++] = ScanRange(base, base + binsize[bin]); + if (stackPos == stack.length) + break; + } + } + else if (bin == B_PAGE) + { + auto offsetBase = offset & notbinsize[bin]; + base = pool.baseAddr + offsetBase; + biti = offsetBase >> pool.shiftBy; + //debug(PRINTF) printf("\t\tbiti = x%x\n", biti); + + pcache = cast(size_t)p & ~cast(size_t)(PAGESIZE-1); + + // For the NO_INTERIOR attribute. This tracks whether + // the pointer is an interior pointer or points to the + // base address of a block. + bool pointsToBase = (base == sentinel_sub(p)); + if(!pointsToBase && pool.nointerior.nbits && pool.nointerior.test(biti)) + continue; + + if (!pool.mark.set(biti) && !pool.noscan.test(biti)) { + references[base] = p1; + objects[base] = pool.bPageOffsets[pn] * PAGESIZE; + debug(COLLECT_PRINTF) printf("\t\tmark %p -> %p, off=%p\n", p1, base, p - base); + stack[stackPos++] = ScanRange(base, base + pool.bPageOffsets[pn] * PAGESIZE); + if (stackPos == stack.length) + break; + } + } + else if (bin == B_PAGEPLUS) + { + pn -= pool.bPageOffsets[pn]; + base = pool.baseAddr + (pn * PAGESIZE); + biti = pn * (PAGESIZE >> pool.shiftBy); + + pcache = cast(size_t)p & ~cast(size_t)(PAGESIZE-1); + if(pool.nointerior.nbits && pool.nointerior.test(biti)) + continue; + + if (!pool.mark.set(biti) && !pool.noscan.test(biti)) { + references[base] = p1; + objects[base] = pool.bPageOffsets[pn] * PAGESIZE; + debug(COLLECT_PRINTF) printf("\t\tmark %p -> %p, off=%p\n", p1, base, p - base); + stack[stackPos++] = ScanRange(base, base + pool.bPageOffsets[pn] * PAGESIZE); + if (stackPos == stack.length) + break; + } + } + else + { + // Don't mark bits in B_FREE pages + assert(bin == B_FREE); + continue; + } + } + } + + ScanRange next=void; + if (p1 < p2) + { + // local stack is full, push it to the global stack + assert(stackPos == stack.length); + toscan.push(ScanRange(p1, p2)); + // reverse order for depth-first-order traversal + foreach_reverse (ref rng; stack[0 .. $ - 1]) + toscan.push(rng); + stackPos = 0; + next = stack[$-1]; + } + else if (stackPos) + { + // pop range from local stack and recurse + next = stack[--stackPos]; + } + else if (!toscan.empty) + { + // pop range from global stack and recurse + next = toscan.pop(); + } + else + { + // nothing more to do + return; + } + p1 = cast(void**)next.pbot; + p2 = cast(void**)next.ptop; + // printf(" pop [%p..%p] (%#zx)\n", p1, p2, cast(size_t)p2 - cast(size_t)p1); + goto Lagain; + } + + thread_suspendAll(); + gcx.prepare(); // set freebits + + foreach(root; cgc.rootIter) + mark(&root, &root + 1); + foreach(range; cgc.rangeIter) + mark(range.pbot, range.ptop); + + thread_scanAll(&mark); + thread_resumeAll(); + + cgc.gcLock.unlock(); +} + +/////////////////////////////////////////////////////////////// +void dumpGC(GC _gc) +{ + auto cgc = cast(ConservativeGC) _gc; + assert(cgc); + auto gcx = cgc.gcx; + + cgc.gcLock.lock(); + + char buf[256]; + sprintf(buf.ptr, "Dump of GC %p: %d pools\n", _gc, gcx.npools); + OutputDebugStringA(buf.ptr); + sprintf(buf.ptr, "Trace buffer memory: %lld bytes\n", cast(long)tracer.traceBuffer.memUsage()); + OutputDebugStringA(buf.ptr); + + AddrTracePair[] traceMap = tracer.traceBuffer.createTraceMap(); + memset(addrInfoStat.ptr, 0, addrInfoStat.sizeof); + + thread_suspendAll(); + gcx.prepare(); // set freebits + + void dumpObjectAddrs() scope + { + size_t usedSize = 0; + size_t freeSize = 0; + foreach (pool; gcx.pooltable[0 .. gcx.npools]) + { + foreach (pn, bin; pool.pagetable[0 .. pool.npages]) + { + if (bin == B_PAGE) + { + auto lpool = cast(LargeObjectPool*) pool; + size_t npages = lpool.bPageOffsets[pn]; + + void* addr = sentinel_add(pool.baseAddr + pn * PAGESIZE); + dumpAddr(traceMap, addr, npages * PAGESIZE); + usedSize += npages * PAGESIZE; + } + else if (bin == B_FREE) + { + freeSize += PAGESIZE; + } + else if (bin < B_PAGE) + { + immutable size = binsize[bin]; + void *p = pool.baseAddr + pn * PAGESIZE; + void *ptop = p + PAGESIZE; + immutable base = pn * (PAGESIZE/16); + immutable bitstride = size / 16; + + for (size_t i; p < ptop; p += size, i += bitstride) + { + immutable biti = base + i; + + if (!pool.freebits.test(biti)) + { + void* addr = sentinel_add(p); + dumpAddr(traceMap, addr, size); + usedSize += size; + } + else + freeSize += size; + } + } + } + } + + sprintf(buf.ptr, "Sum of used memory: %lld bytes\n", cast(long)usedSize); + OutputDebugStringA(buf.ptr); + sprintf(buf.ptr, "Sum of free memory: %lld bytes\n", cast(long)freeSize); + OutputDebugStringA(buf.ptr); + } + + dumpObjectAddrs(); + dumpAddrInfoStat(); + + foreach(root; _gc.rootIter) + { + if (auto te = tracer.traceBuffer.findTraceEntry(traceMap, root)) + { + if (StackAddrInfo* ai = te.resolve()) + { + const(char)* filename = stringBuffer.ptr + ai.filenameOff; + sprintf(buf.ptr, "%s(%d): root %p\n", filename, ai.line, root); + } + else + sprintf(buf.ptr, ": root %p\n", root); + } + else + sprintf(buf.ptr, ": root %p\n", root); + + OutputDebugStringA(buf.ptr); + } + + void dumpRange(void *pbot, void *ptop) scope nothrow + { + bool rangeShown = false; + for (void** p = cast(void**) pbot; p < ptop; p++) + { + void* root = *p; + if (root < gcx.pooltable.minAddr || root >= gcx.pooltable.maxAddr) + continue; + + Pool* pool = gcx.pooltable.findPool(root); + if (!pool) + continue; + + size_t offset = cast(size_t)(root - pool.baseAddr); + size_t biti = void; + size_t pn = offset / PAGESIZE; + Bins bin = cast(Bins)pool.pagetable[pn]; + void* base = void; + + if (bin < B_PAGE) + { + auto offsetBase = offset & notbinsize[bin]; + base = pool.baseAddr + offsetBase; + biti = offsetBase >> pool.shiftBy; + if (pool.freebits.test(biti)) + continue; + } + else if (bin == B_PAGE) + { + auto offsetBase = offset & notbinsize[bin]; + base = pool.baseAddr + offsetBase; + } + else if (bin == B_PAGEPLUS) + { + pn -= pool.bPageOffsets[pn]; + base = pool.baseAddr + (pn * PAGESIZE); + } + else + continue; // B_FREE + + if (!rangeShown) + { + sprintf(buf.ptr, "within range %p - %p:\n", pbot, ptop); + OutputDebugStringA(buf.ptr); + rangeShown = true; + } + int len; + if (auto te = tracer.traceBuffer.findTraceEntry(traceMap, base)) + { + if (StackAddrInfo* ai = te.resolve()) + { + const(char)* filename = stringBuffer.ptr + ai.filenameOff; + len = sprintf(buf.ptr, "%s(%d): @range+%llx %p", filename, ai.line, cast(long)(cast(void*)p - pbot), root); + } + else + len = sprintf(buf.ptr, ": @range+%llx %p", cast(long)(cast(void*)p - pbot), root); + } + else + { + len = sprintf(buf.ptr, ": @range+%llx %p", cast(long)(cast(void*)p - pbot), root); + } + + if (root != base) + len += sprintf(buf.ptr + len, " base %p", base); + buf.ptr[len++] = '\n'; + buf.ptr[len] = 0; + OutputDebugStringA(buf.ptr); + } + } + foreach(range; _gc.rangeIter) + { + dumpRange(range.pbot, range.ptop); + } + + wipeStack(); // remove anything that might be left by iterating through the GC + thread_scanAll(&dumpRange); + + tracer.traceBuffer.deleteTraceMap(traceMap); + thread_resumeAll(); + + cgc.gcLock.unlock(); + + findRoot(null); +} + +void findRoot(void* sobj) +{ + if (!sobj) + return; + + auto cgc = cast(ConservativeGC) tracer.gc; + assert(cgc); + + HashTab!(void*, void*) references; + HashTab!(void*, size_t) objects; + collectReferences(cgc, references, objects); + + const(void*) minAddr = cgc.gcx.pooltable.minAddr; + const(void*) maxAddr = cgc.gcx.pooltable.maxAddr; + + char buf[256]; +nextLoc: + for ( ; ; ) + { + TraceEntry* te = tracer.traceBuffer.findTraceEntry(sobj); + StackAddrInfo* ai; + if (te && (ai = te.resolve()) !is null) + { + const(char)* filename = stringBuffer.ptr + ai.filenameOff; + sprintf(buf.ptr, "%s(%d): %p\n", filename, ai.line, sobj); + } + else + sprintf(buf.ptr, "no location: %p\n", sobj); + OutputDebugStringA(buf.ptr); + + ulong src; + if (auto psrc = sobj in references) + { + for (void* base = *psrc; base >= minAddr && base <= maxAddr; ) + { + if (auto pobj = base in objects) + { + if (*psrc < base + *pobj) + { + sobj = base; + continue nextLoc; + } + } + auto ubase = cast(size_t)base; + if (ubase & 0xfff) + base = cast(void*)(ubase ^ (ubase & -ubase)); // clear lowest bit + else + base -= 0x1000; + } + sprintf(buf.ptr, "%p not a heap object\n", *psrc); + OutputDebugStringA(buf.ptr); + } + break; + } +} diff --git a/vdc/ast/mod.d b/vdc/ast/mod.d index 770029da..bdbf7eb5 100644 --- a/vdc/ast/mod.d +++ b/vdc/ast/mod.d @@ -10,6 +10,7 @@ module vdc.ast.mod; import vdc.util; import vdc.semantic; +import vdc.semanticopt; import vdc.lexer; import vdc.ast.node; @@ -59,10 +60,10 @@ class Module : Node return tn.filename == filename && tn.imported == imported; } - - + + Project getProject() { return static_cast!Project(parent); } - + override void toD(CodeWriter writer) { foreach(m; members) @@ -116,7 +117,7 @@ class Module : Node writer("::", baseName(filename)); writer("::"); } - + string getModuleName() { if(auto md = cast(ModuleDeclaration) getMember(0)) @@ -158,7 +159,7 @@ class Module : Node auto imp = Import.create(objmod); // only needs module name scop.addImport(imp); } - + super.addMemberSymbols(scop); } } @@ -173,12 +174,12 @@ class Module : Node initScope(); return scop.search(ident, false, false, true); } - + override void _semantic(Scope sc) { if(imported) // no full semantic on imports return; - + // the order in which lazy semantic analysis takes place: // - evaluate/expand version/debug // - evaluate mixins and static if conditionals in lexical order @@ -192,17 +193,17 @@ class Module : Node sc = sc.push(scop); scope(exit) sc.pop(); - + foreach(m; members) { m.semantic(scop); } } - + public /* debug & version handling */ { VersionDebug debugIds; VersionDebug versionIds; - + Options getOptions() { if(options) @@ -234,7 +235,7 @@ class Module : Node return true; return false; } - + bool versionEnabled(int level) { if(Options opt = getOptions()) @@ -266,7 +267,7 @@ class Module : Node return true; return false; } - + bool debugEnabled(int level) { if(Options opt = getOptions()) @@ -284,7 +285,7 @@ class Module : Node return opt.debugOn; return false; } - + } } @@ -316,7 +317,7 @@ class PackageIdentifier : Node class ModuleFullyQualifiedName : Node { PackageIdentifier[] pkgs; - + mixin ForwardCtor!(); override void toD(CodeWriter writer) @@ -362,7 +363,7 @@ class ModuleFullyQualifiedName : Node } } } - + string getName() { string name = getMember!Identifier(0).ident; @@ -394,7 +395,7 @@ class AttributeSpecifier : Node override void toD(CodeWriter writer) { writer.writeAttributesAndAnnotations(attr, annotation); - + switch(id) { case TOK_colon: @@ -424,7 +425,7 @@ class AttributeSpecifier : Node m.attr = combineAttributes(attr, m.attr); m.annotation = combineAnnotations(annotation, m.annotation); } - + override Node[] expandNonScopeBlock(Scope sc, Node[] athis) { switch(id) @@ -499,7 +500,7 @@ class DeclarationBlock : Node foreach(m; members) writer(m); } - + override Node[] expandNonScopeBlock(Scope sc, Node[] athis) { return removeAll(); @@ -534,7 +535,7 @@ class Pragma : Node string ident; TemplateArgumentList getTemplateArgumentList() { return getMember!TemplateArgumentList(0); } - + override Pragma clone() { Pragma n = static_cast!Pragma(super.clone()); @@ -549,7 +550,7 @@ class Pragma : Node auto tn = static_cast!(typeof(this))(n); return tn.ident == ident; } - + override void toD(CodeWriter writer) { writer("pragma(", ident, ", ", getMember(0), ")"); @@ -562,7 +563,7 @@ class Pragma : Node string msg; auto alst = getTemplateArgumentList(); alst.semantic(sc); - + foreach(m; alst.members) { Value val = m.interpretCatch(nullContext); @@ -588,7 +589,7 @@ class ImportDeclaration : Node override void toC(CodeWriter writer) { } - + override void _semantic(Scope sc) { getMember(0).annotation = annotation; // copy protection attributes @@ -637,7 +638,7 @@ class Import : Node string aliasIdent; ImportBindList getImportBindList() { return members.length > 1 ? getMember!ImportBindList(1) : null; } - + Annotation getProtection() { if(parent && parent.parent) @@ -649,7 +650,7 @@ class Import : Node Module mod; int countLookups; int countFound; - + override Import clone() { Import n = static_cast!Import(super.clone()); @@ -665,7 +666,7 @@ class Import : Node auto tn = static_cast!(typeof(this))(n); return tn.aliasIdent == aliasIdent; } - + override void toD(CodeWriter writer) { if(aliasIdent.length) @@ -680,7 +681,7 @@ class Import : Node sc.addImport(this); if(aliasIdent.length > 0) sc.addSymbol(aliasIdent, this); - + auto mfqn = getMember!ModuleFullyQualifiedName(0); mfqn.addSymbols(sc); } @@ -690,10 +691,10 @@ class Import : Node if(!mod) if(auto prj = sc.mod.getProject()) mod = prj.importModule(getModuleName(), this); - + if(!mod) return Scope.SearchSet(); - + return mod.search(ident); } @@ -702,7 +703,7 @@ class Import : Node auto mfqn = getMember!ModuleFullyQualifiedName(0); return mfqn.getName(); } - + static Import create(Module mod) { // TODO: no location info @@ -722,8 +723,8 @@ unittest verifyParseWrite(q{ import ntest = pkg.test; }); verifyParseWrite(q{ import io = std.stdio : writeln, write; }); } - - + + //ImportBindList: // ImportBind // ImportBind , ImportBindList @@ -764,7 +765,7 @@ class MixinDeclaration : Node writer("mixin(", getMember(0), ");"); writer.nl; } - + override Node[] expandNonScopeInterpret(Scope sc, Node[] athis) { Context ctx = new Context(nullContext); diff --git a/vdc/ddmderrors.d b/vdc/ddmderrors.d new file mode 100644 index 00000000..109d454b --- /dev/null +++ b/vdc/ddmderrors.d @@ -0,0 +1,197 @@ +/** + * Compiler implementation of the + * $(LINK2 http://www.dlang.org, D programming language). + * + * Copyright: Copyright (c) 1999-2017 by Digital Mars, All Rights Reserved + * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/ddmd/errors.d, _errors.d) + */ + +module ddmd.errors; + +// Online documentation: https://dlang.org/phobos/ddmd_errors.html + +import core.stdc.stdarg; +import core.stdc.stdio; +import core.stdc.stdlib; +import core.stdc.string; +import ddmd.globals; +import ddmd.root.outbuffer; +import ddmd.root.rmem; +import ddmd.console; + +/********************** + * Color highlighting to classify messages + */ +enum Classification +{ + error = Color.brightRed, /// for errors + gagged = Color.brightBlue, /// for gagged errors + warning = Color.brightYellow, /// for warnings + deprecation = Color.brightCyan, /// for deprecations +} + +/************************************** + * Print error message + */ +extern (C++) void error(const ref Loc loc, const(char)* format, ...) +{ + va_list ap; + va_start(ap, format); + verror(loc, format, ap); + va_end(ap); +} + +extern (C++) void error(Loc loc, const(char)* format, ...) +{ + va_list ap; + va_start(ap, format); + verror(loc, format, ap); + va_end(ap); +} + +extern (C++) void error(const(char)* filename, uint linnum, uint charnum, const(char)* format, ...) +{ + Loc loc; + loc.filename = filename; + loc.linnum = linnum; + loc.charnum = charnum; + va_list ap; + va_start(ap, format); + verror(loc, format, ap); + va_end(ap); +} + +extern (C++) void errorSupplemental(const ref Loc loc, const(char)* format, ...) +{ + va_list ap; + va_start(ap, format); + verrorSupplemental(loc, format, ap); + va_end(ap); +} + +extern (C++) void warning(const ref Loc loc, const(char)* format, ...) +{ + va_list ap; + va_start(ap, format); + vwarning(loc, format, ap); + va_end(ap); +} + +extern (C++) void warningSupplemental(const ref Loc loc, const(char)* format, ...) +{ + va_list ap; + va_start(ap, format); + vwarningSupplemental(loc, format, ap); + va_end(ap); +} + +extern (C++) void deprecation(const ref Loc loc, const(char)* format, ...) +{ + va_list ap; + va_start(ap, format); + vdeprecation(loc, format, ap); + va_end(ap); +} + +extern (C++) void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) +{ + va_list ap; + va_start(ap, format); + vdeprecation(loc, format, ap); + va_end(ap); +} + +extern(C++) +void verrorPrint(const ref Loc loc, Color headerColor, const(char)* header, + const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null); + +// header is "Error: " by default (see errors.h) +extern (C++) void verror(const ref Loc loc, const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null, const(char)* header = "Error: ") +{ + global.errors++; + if (!global.gag) + { + verrorPrint(loc, Classification.error, header, format, ap, p1, p2); + if (global.errorLimit && global.errors >= global.errorLimit) + fatal(); // moderate blizzard of cascading messages + } + else + { + if (global.params.showGaggedErrors) + { + fprintf(stderr, "(spec:%d) ", global.gag); + verrorPrint(loc, Classification.gagged, header, format, ap, p1, p2); + } + global.gaggedErrors++; + } +} + +// Doesn't increase error count, doesn't print "Error:". +extern (C++) void verrorSupplemental(const ref Loc loc, const(char)* format, va_list ap) +{ + Color color; + if (global.gag) + { + if (!global.params.showGaggedErrors) + return; + color = Classification.gagged; + } + else + color = Classification.error; + verrorPrint(loc, color, " ", format, ap); +} + +extern (C++) void vwarning(const ref Loc loc, const(char)* format, va_list ap) +{ + if (global.params.warnings && !global.gag) + { + verrorPrint(loc, Classification.warning, "Warning: ", format, ap); + //halt(); + if (global.params.warnings == 1) + global.warnings++; // warnings don't count if gagged + } +} + +extern (C++) void vwarningSupplemental(const ref Loc loc, const(char)* format, va_list ap) +{ + if (global.params.warnings && !global.gag) + verrorPrint(loc, Classification.warning, " ", format, ap); +} + +extern (C++) void vdeprecation(const ref Loc loc, const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) +{ + static __gshared const(char)* header = "Deprecation: "; + if (global.params.useDeprecated == 0) + verror(loc, format, ap, p1, p2, header); + else if (global.params.useDeprecated == 2 && !global.gag) + verrorPrint(loc, Classification.deprecation, header, format, ap, p1, p2); +} + +extern (C++) void vdeprecationSupplemental(const ref Loc loc, const(char)* format, va_list ap) +{ + if (global.params.useDeprecated == 0) + verrorSupplemental(loc, format, ap); + else if (global.params.useDeprecated == 2 && !global.gag) + verrorPrint(loc, Classification.deprecation, " ", format, ap); +} + +/*************************************** + * Call this after printing out fatal error messages to clean up and exit + * the compiler. + */ +extern (C++) void fatal() +{ + throw new Exception("fatal"); +} + +/************************************** + * Try to stop forgetting to remove the breakpoints from + * release builds. + */ +extern (C++) void halt() +{ + throw new Exception("halt"); +} + diff --git a/vdc/ddmdlib.d b/vdc/ddmdlib.d new file mode 100644 index 00000000..41025b0b --- /dev/null +++ b/vdc/ddmdlib.d @@ -0,0 +1,5 @@ +module ddmd.lib; + +class Library +{ +} diff --git a/vdc/ddmdmars.d b/vdc/ddmdmars.d new file mode 100644 index 00000000..2077b105 --- /dev/null +++ b/vdc/ddmdmars.d @@ -0,0 +1,23 @@ + +module ddmd.mars; +import ddmd.dscope; +import ddmd.root.rmem; + +extern (C++) void genCmain(Scope* sc) +{ +} + +extern (C++) void *mem_malloc(size_t u) +{ + return mem.xmalloc(u); +} + +extern (C++) void mem_free(void* p) +{ + mem.xfree(p); +} + +extern (C) void* allocmemory(size_t size) nothrow +{ + return GC.malloc(size); +} diff --git a/vdc/ddmdrmem.d b/vdc/ddmdrmem.d new file mode 100644 index 00000000..eed56279 --- /dev/null +++ b/vdc/ddmdrmem.d @@ -0,0 +1,46 @@ +module ddmd.root.rmem; + +import core.memory : GC; +import core.stdc.string : strlen; + +extern (C++) struct Mem +{ + static char* xstrdup(const(char)* p) nothrow + { + return p[0 .. strlen(p) + 1].dup.ptr; + } + + static void xfree(void* p) nothrow + { + return GC.free(p); + } + + static void* xmalloc(size_t n) nothrow + { + if (cancel) + throw cancelError; + return GC.malloc(n); + } + + static void* xcalloc(size_t size, size_t n) nothrow + { + return GC.calloc(size * n); + } + + static void* xrealloc(void* p, size_t size) nothrow + { + return GC.realloc(p, size); + } + static void error() nothrow + { + __gshared static oom = new Error("out of memory"); + throw oom; + } + + __gshared cancelError = new Error("cancel malloc"); + __gshared bool cancel; +} + +extern (C++) const __gshared Mem mem; + + diff --git a/vdc/dmdicon.ico b/vdc/dmdicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3ead32d9b409a394a0aa0b675227fd22a6625fbe GIT binary patch literal 34494 zcmeHw2Y8iLwssun>YY1t9lci_XGTZt2&A2pMnZZcA%u`dNobPLdk-aqrihB7C{+*; z!4M$y5=bREv{0mzP(=tGXA~Icn04QGf9E?nNlpTy|8r;ln>^3TSI+sqz1G@muf6u( z@7l+~;UR~Aa|j4e%`6~_%>A2UZk>&bv2ZvXCIXFD?jCMWs zHx3T_MmabuOIL@n+(HMTGJ~9}>?^ID3&a0EFYuFvo?dlY8$Hm3tduM02WgZ^RQJNl_1_lH) z`uCbTaCP+>>FV0z&fvjIWbxv1$;kLh#*8^2X=(dq)TsS3a^yZ4K75}H8&)bqhnC8a zA*C{S@Lm}>aIXv)ut)m$-y?nd?pD;h_b%zxYnSxwxl2-0cS=giPU+s=B;C4c)TK*_ zbnaXtojMguQqm6T*l~w+=&(cDw=a@*?TREJp-|%E3nebDP};UFkeHYPY11ZOqNDSr zb?ZE7)hbUSBXcDpB3Hu0w<`(_-7X;^+ax%6n*;{tNI*c2v}~D+=U0ofbGsj$ojp&x zxjDsYcF@$>R({lbgsZFX_lp)CQ15@_k)_h;h1K%PE34(@SF$yFd9}Rsa<;tm67J#r z)mPU@&4w;gLrsukmk)dinq^3@gcR?q^L!Ujncw* zv-tXM6kk6a{Whs1zvJz_QM|l1io5#;^&Y;@*?FCMf0L$Kd9S{>lq^PJ|adGMSgNuvj9?I|L)-1GX)25GDbnuX~bMsT9M`tQMKlM~5biG|V zbSwZBT8{aaBkvVR$D{)3)TKz?=)OaG^eRD}m&m|DCfLSK8I`tM#*W)9<0tHuNs~%t zB5AVas9&q&K76)MCV=>z2@^|Y-1t&S8?#4-kK8SThU}Dn15DDZPlls zt^D@j!Im^$Yx9`YsSt9nli&PinZ(BCLYMw%V@?C911Be^rzyXio13e_5cJ&_U!0Lg z9{B?Hk_)?peATE>T_@unsZ(cMcP@bZMbe{ZvGnan`FF~&;kx{LWPHY6E2WRe`FPv| z@mwc$&+@$t9MjYHNZRP#GJM1?89c;nZl$p}*9o8TbJ92qrQ?~=V|K&W?1F#U3BO{J z-WK`au$0+N=kE>Zgv4unrbzz`M_V2f5_09S$G(K$_yRW2{1W9i8k_!w@*50p<6~md zl@DrxHky)J4B7#`m&l?e$7JQIGFiF0OtLITp08Y8uI}-Cb#}R|SyLwK)|cb_q=k6@ zq-3r*A)hZjCZ8=jD$_rJKZWen58H@NtnX2vw9%-0*nS%1A2DjT3>mgd`VWNsXj?sc z?vT_T8j-*5igu`WL0(DSQ?#Rgo!SF-V|gYOHu~#dFNJU2g!bU^y{-K4eG_A2GnDTQ z2-pn2U99Nij}OW98#k)x=1sXq!aYSbuX!K$uIis#j=a8(`+V2stJh`!{%<5ZyG-7m zwqMyfZJjg%ZJsm|va9+Ziu$MgeTp?geb5$k{`6x{=!Vp*7fJt|^+)2fcnK6sDU`e#aRTmA5}8akpL^m}~v z@ZpQ{>B6J%8@pvF>U$_;rVkwsKQa`@fsnsH+CV?}0s6vz{Y}zW5qvIuP9H@k95w2T zqxu~8`FTGQp5;3ze^Qct`QzdyDEki$-6{j%$EbJmWn0gRcU@lAr-iOvzg|rTHFc!) zq<_~Uzx7$m^@;M!^5I8c$-u#o8ARVdcqn`T^f4IcgLsdhfj6DVBijdw=eESYNTaG} zDSvWu{ql#0=P18J-@`Vm^J!bp)!KlKK5E^kZ1`N)hgA=jd)8~}#&U04?ip3@tS_xU z*`@4(wm{p^iTqV3ljYiS#CNGXl6n@lMfp2*%CT$z@$nN>92OawqxxRlIbs2S==d~is=Ssi0cY`{x(D4%$%1=`MA&^`71Nejy=o9E4$eWdv z?_hsvL;RfnMER6m%9o57rODs9bN%wSirQxN%bzc`$WLC$w++v{-o597bty6iPDUFk50A z`|&4-&nOjJ8jtJo_})0^h<#q` z=tr>%*Xv!kg*o#Mt9CjPZHs*t`znqD zdLZUty)!oL*by;#2c7b8PC^V1Vt>64u>jv^)vcwC*xs9uewemT`8i&gq{a&zH(<<&RIulQ-Wil_^t75%+2Jul$={ zH#qA4ZZ7zuU9x>LRvUmmrw`;$MJz(w=NO?qWKT@YQi9u47#v zyw=)*MSirQDdbP_xKGvfV6?j~T?$m&jfmVPVd%qxL$*pl;1)Hm^!C}LY=H8orrMW3 zF>#_r{#=48TJ&0la-#-T0KuGtT;f9#C5)vkR$>P&lgG{&s- z-z_6@Bs6TR1O;yqf5fvbd^f3aHRbQwGuLkYQ-01#u>PkaE}i!70m(*8uY9v!_c~ve z>p61|E4yT@%6^$+l|E>5sj2XN@OjA?tF~{ShdGQ~RX5RSi=@`AN!!#puQ}da_?acv zz`K>cQI_(Fma^EtbWDOR!L~b~P3hxMp7UN@d@g*K_Wo9_po5lMB{X!4Y6t%Q&;iCZ zl)qQ6JiGF@Yc~<&%M#4HQ*Ck3_u1IFs>rAB?p)=Hz@qLSnvZj{$+3mH%%3p#)= z2!k&OhA*J}efs3vwg2|*C!)_XS?&Kl*gxg3>HDqz06O_##z8gyqOCK&h(?*zx1awO z%>8W?quU0QwO-8&a*nWZ<26eD7hlxo5jl_ddXu%%%n@^ZF6(9XoWu3je_eW50ej%Q z5ZeUX25p$Wwx&O%{QdgXCI2KPKl_UADaFc%&x3!rEz>HyrEX~Rb@>|3dwO6Flyjk+ zf8+dUlO}8AHOTxj=1^aFVU;@an)mtnqQ%Fmm1kS_z0Q|^c|!Tb>i*Ey7i?Aa-@ku> z-TLp)VUn7krae+`)ZhCb9ITh0;fVR@$L;wV&h>gh2b>3H?8W+JJ+r=9@0>@b9k4yn zE@&S)@bUMOv#!stT)U1rq&<=Zf2jKcXx5#^i46x%yz@}^Zxq> z>g9+1UUgqnJ?_wAFKsTH?VI!1)GymT+duuli!W(&*v_z#OP8-V=|97bP| zgnm-jfvrEJ{DTG+)>;3QpS;m;(to};y?*&QrfREv4g75lU&DDcUrXHKiFE+CYQ8|5 z$7kIuUjRKYe$eH3(Bmb

hKfciQ?x@<^Me{DTMEm%n4jNr+o^s`U)^o3!b75d+o7 z%V>;4;}Lh*^EFkm*Jf$%y~*kiUEmKLoz_Vc*!yd+d#Ebn)h&OI9y{TWR;##~@iXIKTiw!`6%L3#gyH`!3X5M$IzoyQU9hjLbMdtxusH*v3Yz|6#*+*scGhq)BS6 zl6@1$O&mYHg*dpr^3t)EqkIiweEYFib$_Uj!+6ZVIPTonSL=O$eP!GGti*I)#ed|5 z;|}s>^@q?2#;L4QY|uXKQznEj#7Bjq1Cve<6@CnrzF*l3rEOW1dFyfEdh`sL5dKcm)s zxbCxdUAbhhEt3r!%Vjg>05@&HTwu;=DK0rD`wn~~6`cROkC^sBzq18p(r0t*!!Z!Y zgEhyBls_%4Zuz-p->A_l<*&IuJsEQ#56aKadG5lcpB4w0c6|-GwQ)bk|0;fizh~d1 zj}_S;Q2x=QOX{qD%Kw+Yti*V1gPJdxgf;7*Bgcb0%Q-i${d4~M)IHis1>&Vo7aUPz zT#j!z&$j%_`KJzm@h=!o-uK6wfEV+`z}NDVt4-Zrz|yI*~ z;9M)7|LGA~u<(d{GV74coOw{DP1^?_x=-nm7=<=5xxd(0QNtRoS91)UYhaAc`PeI# zxhl#|`_=s+$7zo~`UTc2h==j`&fVQHBp@IF*&+)6krEl%_wVn&e@q^K{7W?k)Zg#s zw%+OwIiBIThQ5aVI_FmOu_DJ9w!TKi9rrmeRTUrJW2~sg%d3@tpr3HUc+%B?v6aPN zF|OiVBiFV1K@PRh!AHSvWKa2rw=cVY6 ziOJ%4mb~imA?JGZu_EF!VYL6Ay+xUXoV?}#&XBv+itUNM)3qcIaIGj8_ z^T#ZOkqZtU^P`K4+iJ-CZ<_Sle_$RDPMEL+{^6jq6OPODd8wMdhOrUnR5`}c$BHWM zfDUwD!#PetLy^&oj@gfGuSy zU->Nh3-+0e8;G%L)M%xU#}`p1?TF(kg(2j85AN|Z##sC=pLrI~@*VWMd?(*cURf5) zWZD1qUzv)J#~;rGU(4k`|8u!IvaOOoer}IP;`oSrBkpVB#QlgXIsyyo^;u2X^=pH{ zJrTIq+XDyAs62V{vY1R)W$oGvz&3p?t5=_wRjbZRR@OOLvErO$W}cHTzdS3;mYo&i z=05-Yj4WAlS{5xjrD);8Q?g(|xy+wmF7xJ<$(%W5GJEz(nKkRAeDcXj_{S6S(MQK+ z#*E|g!3W1=`gD!nefOxm^UhJMK^&2(Q;%RR?y#zl$&(LZ-S3c0nDCXtrP5BvjXS9D zsiQ|%VN^$q&@igRr}BK-w8QAvmZ7hRybT-Q2%lFA_o~a!qrqT!9XQb~uCDHPjYc2X zN&qmvif-e0+ui-a$jvR__WhARzE_)!M*rJCl?(>o+XjONaIapcU0vO}L%fGEy1+}+(@{8uH!HP72%T<;}r!{-eeXwX1|1{yTbpn?B08jxS;uTs<4qj$CA!?(2K zLuW0=eC??ABj9O9!?n^t9eQ}ka{r-x^(}{oEyqXCYS)ii^!s~@-p4;^HFBQ_7f@GF z!#)vELc?E!1{yTbpn?C#8sPk!yL*$SuC7kOS}u~7pZw2r-n50gdsFN(RQnHe3QTNb*Bqa6ywy}+9;F80aEDe#)3qt8~O(J_I# zbaj3Gd0Pn_9sS1o`gZ;9?YDOWr@m8R-iUjwD<7G;$cc$sJ~DHWV`B?|C8<9bIV@~D zFeF+oa!`<#i|p?YT%g}pV1l*+i@OEui(9a60bHc#W~^as!ra^@V1$q#>_fc7Cza6e zWrM*vne+57zx?u}lmYt@xOjOb-bznDfH}ey3R@B$zD3RPhJ|T!@|=?;&NRA>wg$|+ zSYm>h8_0adzWs`|Tr%d9DJoX$ZUY7~f3?I0!&#)T>BLVYCTjQ@V*NPhPizc{bITfO z7)$1k5%c)eQ(3^id=A{B-wD=%yL+?e$bYkD0c$5u&XGU=c_r`}$cX?xR>Lt9D@-h} zmcPpL?kPnoe?jFG17}D4e+KelRQ`j?dC+qp^kdcMF~UnT#}&Ov85KgoOoVm=iy&y=LDHQY0E zKd5i!Uyy&U@9Fs~W02=c%(PCtKV~d)WN}n^EWlI{hpyE3ew zsw2;N?^K19BUh*Vv_?mcUXp{zS1bjdp>W4}S&m$u_ul_X;SQMtK%(CD+@xW|L<1Ag zJdd6r=7}ppehl+bHDbO5@TTCIc{3`P6Zu1b`3rF6fh3VcO*Vj zVNxylWF42ywLks5CVtlz%d9_p7C4;jb*Gelk!R+zFrP=`U(37HaxQ^y#@do1%1#jEze!Kb^{ocab_Bos%JzjyFChREzJUQz@<@})y zsXD(OKEG`)fIT^rD=Ag3fxeDwRzX3v`R867#JJH%e2VpEUC%o2yk3ReYWf+qhXQhgR8A7|@8|U=fXJVjltI9fSdPev033N9{YVJ)=z8m z&;3y7W0@be7<&Wgb#JW)l(~9Mx$^JKNwxBi{(v~NMA%+pI}0H{B9VmaiLe!7#H{U_ z^+4MMEdXYYxlhF75H~?$-WB_A+5-D~_WN9yCT@$E5bpUA8alI<{<&txe&TIlTbF)O z#XohW`^weGdt(2@c0}L6{CW0g*O9qa%X}^3S-7?t7FL^ouKQ8{%+Fe$iTph9t>47yFtXQbn8~2Fond{>g)Q%*Ky6Ccr)UU zhzHYRCg z%q1emn79NI@n1UMw#SXYP|=QPL&VCkE-4FflEiOw{a)n@F>elQ`&?6Q*|IkO+!Kg< zzSQJjFH7-H{VV>poKWV&bwnJ>J!OJ}VV}TK5MRReaT4<%h_@i7=U$j=mU9-l(d>H| zClY^5+zBy0%yVFDL#(OB|HrlLpXoiuh@J?`7TAt%N_FU4#FK3)7|@QGT0PL5?Bpz4zzdt3WKeZ-4!HEgVA(LTt{s zN9UjM5dA3gHi!jl+txn+%pIg3J?2<$fdVe-#@nPqXl zM(>2nP=TF?-BQCu6-cg0!qu*ez z{7O2V6o1LgC?KM6Rg#@S^8)CS^8W0UHV`8VdANEy>Xr<1{h;v zasL4R9Pffo-AE)|x=0qZAg#9?>4+=v3 zjJ$371>&iRc_qG>d5VmUn5S7YR%Kl=mZc6AE*gDOIAS;MH{s@nyaeCg-(e1y+xe?M zKup8J!~1>57>MH=`cdY+GM-_3=D3IBAC80Q7dSSd-P-yE_A!iKX`{?()cR-cE1>Oj zaR0F?u+y+%#)BL$l4q99cKOURE3r>N4s0#p3>g2Fg?)8!boBqSLx=Hy&&)iHwo(MW zVGP1KZXCJiroQi{e)RXx!MKF>q0N8u+}9W5RLp^E^WccBF%M4i^3vwQ_4#lkbZ9i9 zE)2|#AhB(1K)q|^3lR|<#rvwLiP7V(AoDu{I z3;_9iObGz_`*}?9^L1C`+roW{uaEnb7Iw)E_uZ!Wcx&X1qjz(+N$!T{d$~HkV5q6@ z=;(w^o!*!)ZQCuCHi=6lI$?=K#gP_EtJuX7*>-{!BunK9i7E z3neIGp#-#CAbw$=N{f(B#XD%ecm>QC5C3`M?mJhEE#`>9dycqx&J$1HiHMzjmNk9# zDKDLe$cUEjbV|t75~H4hlE z$2=&l)I4N#sd;ePUh`la`w!n^PU*kPoZO?t9GhIEo@<3?TP0LcR6@Sl$*15)58pS% z)BUxyfS}%wk%u0=GY*Eg%{3>b=9&8p*-<$p%~UyPREZ24RV;&%e?BT>r)0dfTPDA= zMCvTIA-BOgG86$-87MXgKcm!G0y(`xZ#oKA_(D7UFq9WlBGc1-cjg z!^vxTrMFM`YX890-?IEZ{ic?;=};)C0}3nm9lTI^{pJnqt#cLYOV_Z^o`o=P_4UQ8 z*n{%2oH|<}yGzeY=IY}z{>?qoYfuq*Es-IkvGy<+>+%DEDFCGo0QI*J&U+3ls!Zu$ zY&QC?tZd;IyA7`CH(L2`l|g4RaAfh1C(19$t#7d>G}o}f$4#7*c<a0!4WtvmH}J@PaPZqG zzeL{su(a~j*~_Z_b@|hvL+Y(J^xvfyuuXU$Wevm6x1XDSGy`EM*(FVS}8HqTP}Qwhij?&G$+r20T#z zt)aJo$gO5WilLgnlW1*`}1;Hvizvr zRpnn(@>2(Fqinxyo4JK&BsOWgwC{$xi{EDUK>H63t13Tj49ahvDVm|h?pTMB@mL#cgE^lF?7s*e98m{PznCek8`=uX)XQbrJf|L57yI!Z+6~)F zbo*ShSKunlIVD)_Z_L>D$^#2Zd7%9?S|$j zxfhyV|2i-9-SksAXp?L+ol@C;^UTeIS7W}YO8&9w)64xLwu^Vj`bydyeJ%Yf@m#YP z9Fkd|Vt)eIIFEA{9+I`2%9L$=k9SkYEbs0Q-wLm}p8)TXlpR72_ z{AnNTla*^vD0`#KEStWZelxLauFP9>SozOZ3ER!SVcA$SO~`@oSN<?|UPm5xvsDs~Hr@k$9oxQF zFzm#04KQ%ups2f2P<*yBFlwvWFMLg9LBeH1OQTZJHgyk$?eZn@FgIaGgqdYU(q8V+`4F6|_KR5eDY&3fYtv5S+ zuQk8!o^5{Fd6oIOCM(U)zMf@%$!V3jv0JwJbz`>rj#uz{vy=C>yJ68w#mCz)ma^+K zeB`u$Bm(CX)*5q}ZFAsbu`ZlIpM^Ez_L#fui1p%R%wu-O{-{aVAGRI+Fy=AaU_LPl zbA>Iph)*c|d(bB6f<6LkbuBPI?vLNq31qv$oNw?Z35i-Ikx_3P)62Cz4j9lod&tmn z#r+42E$Q2Dw5fNW(WaigMw?Q5rkT2@jxu%YKFZXk+elOAt|LsHx@eT#d4wss^KesA zr{SiK$-_(?l7^YulR6GFCAJ@GiccJBij5y^iisUu5|=P^M?^%-JlirG&Z}&oK^Olk zx`5iN{?0n6+%c6;mVp5AXAS#y8>N=~u$S(l3XGre6*TNxvK%JnnK((74O~ z{$oL7D*XJ$RJ3R@y28gNt)hAJQ59ZZqb_-Rj=bdIG4hhT`^bw%KYl_De z&7FHltx@a0twc;L@uccEp0M7?HAk**@;8&XZ?&`Y9PE!{=<4p?ZAKDu6!?1zIzFr> zPL=pfes%?MI)4L%SW@DViP_^`X8rLyJsL6BLi>Fhqub|@!K*jl-??*={l@V*%hb!ch&6WpMvjgdrvB9Lpg?cxw^4BI?!H95-_x_(j5ja_eeZp3 z4`aT+6j-M;>{-jb^QmKE0EyvP1H3KQ&{@t^V94LaGyLrlVz7ygRrpxQ!}UfNmqph1 zcTY9ROzd@~>xEbW)+1%+Z8}kk*J8`efec-w%@qS_0Q=RM3`u=Z>Gc$m5;V%C`y}4Z zXw=^C;qk_Y@$s;A*r)zXKK6MfzE78x>&L`0ab1~f%%{$3a}oOY^&@}dg6r;F7uV~T z?~jYqet%B?ULkPmwz6_9o9ozI!zNBf|6a}G68t_H*OiH*^z_v1)61*dM|?l=)%y1f zcbrqW09{t%Ke$fKJd8`2Ptw0v^T^*4Q2Rjv*W%TDsj6STpSe`rvrzv&=VJJKC#Id} zm8~8;bg>$?iS>GcZNj2|9*eQ(X&dA^ah;#oA8+p}{`r1l5^cY4@0_;Jz4wXdAU1^9 zQ2G$C_Alpey%B>;Y&C73 zzj;Id#kGB|^K;)a;&+HuB)))HgDhaU*5S7XxYqCOy$F~Gj}EWB78aC}lJ$4uCWw_F zZjd%fY^5$MZJR!oxLsm)i3cGzqzQ1G#4GT(DT(#u`ab30d;I(+Ucnlz+V?IfsQ0`M z9cENSN6)zUVsf@WU#_n&#)&+nt_ zzP=w_BYAtzxbEXK<7z-a#%U*~_S|R4`j?Q9@UWw!;}buZ_*=Zzm;Qfnf_N!Vr+kNp z0y7*O0wLA|QwH9V@9?Pgos7e%utuPN_BagoJQH+{cKs7*CPZ_vJo{6gv;D5MTs?lZ zJ(iVy3ryP)Ef%rQo0VtV=W3ptOjnd|txvWef2>rG*?xx@tna@2LEZmk)-hYYYn|JB zp6?nvwp2Y|P*@=!e|${&Z`(5T^SYiNIA~WjaVU%ajO|hXlI=a7U%7He|41G0-Zj_z ze6=szx!Ae0R{5$9bpCB0Vf`&#dP?QLQh&4O9G8O!uS-F}C7lO8OB>Ly?|GyiZJxKa jL8~p?=lj&NwBi5FKani>jI6+nhqB;%?vMCg{ki`E?7yL* literal 0 HcmV?d00001 diff --git a/vdc/dmdserver.d b/vdc/dmdserver.d new file mode 100644 index 00000000..0c387041 --- /dev/null +++ b/vdc/dmdserver.d @@ -0,0 +1,1734 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2012 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +module vdc.dmdserver; + +version(MAIN) {} else version = noServer; + +version(noServer): +import vdc.ivdserver; +import vdc.semanticopt; + +import ddmd.apply; +import ddmd.arraytypes; +import ddmd.builtin; +import ddmd.cond; +import ddmd.console; +import ddmd.dclass; +import ddmd.declaration; +import ddmd.dimport; +import ddmd.dinterpret; +import ddmd.dmodule; +import ddmd.dscope; +import ddmd.dstruct; +import ddmd.dsymbol; +import ddmd.dtemplate; +import ddmd.expression; +import ddmd.func; +import ddmd.globals; +import ddmd.hdrgen; +import ddmd.id; +import ddmd.identifier; +import ddmd.init; +import ddmd.mtype; +import ddmd.objc; +import ddmd.semantic; +import ddmd.sapply; +import ddmd.statement; +import ddmd.target; +import ddmd.tokens; +import ddmd.visitor; + +import ddmd.root.outbuffer; +import ddmd.root.rmem; +import ddmd.root.rootobject; + +//import vdc.util; +struct TextPos +{ + int index; + int line; +} +struct TextSpan +{ + TextPos start; + TextPos end; +} + +import sdk.port.base; +import sdk.win32.oaidl; +import sdk.win32.objbase; +import sdk.win32.oleauto; + +import stdext.com; +import stdext.string; +import stdext.array; + +version = SingleThread; + +//import std.stdio; +import std.parallelism; +import std.path; +import std.string; +import std.conv; +import std.array; + +import std.concurrency; +import std.datetime; +import core.memory; +import core.thread; +import core.time; +import core.stdc.stdio; +import core.stdc.string; + +//version = traceGC; +version (traceGC) import tracegc; + +debug version = DebugServer; +//debug version = vdlog; // log through visual D logging (needs version = InProc in vdserverclient) + +shared(Object) gDMDSync = new Object; // no multi-instances/multi-threading with DMD +shared(Object) gOptSync = new Object; // no multi-instances/multi-threading with DMD + +extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise" ]; + +/////////////////////////////////////////////////////////////////////// +version(DebugServer) +{ + import std.windows.charset; + import std.datetime; + version(vdlog) debug import visuald.logutil; + import core.stdc.stdio : fprintf, fopen, fputc, fflush, FILE; + __gshared FILE* dbgfh; + + void dbglog(string s) + { + debug + { + version(vdlog) + logCall("DMDServer: ", s); + else + sdk.win32.winbase.OutputDebugStringA(toMBSz("DMDServer: " ~ s ~ "\n")); + } + else + { + if(!dbgfh) + dbgfh = fopen("c:/tmp/dmdserver.log", "w"); + + 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); + fputc('\n', dbgfh); + fflush(dbgfh); + } + } +} + +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] + +/////////////////////////////////////////////////////////////// + +struct delegate_fake +{ + ptrdiff_t ptr; + ptrdiff_t context; +} + +class DMDServer : ComObject, IVDServer +{ + this() + { + version(unittest) {} else + version(SingleThread) mTid = spawn(&taskLoop, thisTid); + mOptions = new Options; + + synchronized(gDMDSync) + { + global._init(); + global.params.isWindows = true; + global.errorLimit = 0; + } + } + + override ULONG Release() + { + if(count == 1 && mTid != mTid.init) + { + // avoid recursive calls if the object is temporarily ref-counted + // while executing Dispose() + count = 0x12345678; + + send(mTid, "stop"); + receive((string val) { assert(val == "done"); }); + + assert(count == 0x12345678); + count = 1; + } + return super.Release(); + } + + override HRESULT QueryInterface(in IID* riid, void** pvObject) + { +// MessageBoxW(null, "Object1.QueryInterface"w.ptr, "[LOCAL] message", MB_OK|MB_SETFOREGROUND); + if(queryInterface!(IVDServer) (this, riid, pvObject)) + return S_OK; + return super.QueryInterface(riid, pvObject); + } + + extern(D) static void taskLoop(Tid tid) + { + bool cont = true; + while(cont) + { + try + { + receiveTimeout(dur!"msecs"(50), + (delegate_fake dg_fake) + { + void delegate() dg = *(cast(void delegate()*)&dg_fake); + dg(); + }, + (string cmd) + { + if(cmd == "stop") + cont = false; + }, + (Variant var) + { + var = var; + } + ); + } + catch(Throwable e) + { + version(DebugCmd) dbglog ("taskLoop exception: " ~ e.msg); + } + } + prioritySend(tid, "done"); + } + + extern(D) void schedule(void delegate() dg) + { + version(unittest) + dg(); + else version(SingleThread) + send(mTid, *cast(delegate_fake*)&dg); + else + runTask(dg); + } + + override HRESULT ConfigureSemanticProject(in BSTR filename, in BSTR imp, in BSTR stringImp, in BSTR versionids, in BSTR debugids, DWORD flags) + { + string fname = to_string(filename); + + + synchronized(gOptSync) + { + auto opts = mOptions; + + string imports = to_string(imp); + string strImports = to_string(stringImp); + + uint oldflags = ConfigureFlags!()(opts.unittestOn, opts.debugOn, opts.x64, + opts.coverage, opts.doDoc, opts.noBoundsCheck, opts.gdcCompiler, + 0, 0, // no need to compare version levels, done in setVersionIds + opts.noDeprecated, opts.ldcCompiler, opts.msvcrt, + opts.mixinAnalysis, opts.UFCSExpansions); + + opts.unittestOn = (flags & 1) != 0; + opts.debugOn = (flags & 2) != 0; + opts.x64 = (flags & 4) != 0; + opts.coverage = (flags & 8) != 0; + opts.doDoc = (flags & 16) != 0; + opts.noBoundsCheck = (flags & 32) != 0; + opts.gdcCompiler = (flags & 64) != 0; + opts.noDeprecated = (flags & 128) != 0; + opts.mixinAnalysis = (flags & 0x1_00_00_00) != 0; + opts.UFCSExpansions = (flags & 0x2_00_00_00) != 0; + opts.ldcCompiler = (flags & 0x4_00_00_00) != 0; + opts.msvcrt = (flags & 0x8_00_00_00) != 0; + + int versionlevel = (flags >> 8) & 0xff; + int debuglevel = (flags >> 16) & 0xff; + + string verids = to_string(versionids); + string dbgids = to_string(debugids); + + int changed = (oldflags != (flags & 0xff0000ff)); + changed += opts.setImportDirs(splitLines(imports)); + changed += opts.setStringImportDirs(splitLines(strImports)); + changed += opts.setVersionIds(versionlevel, splitLines(verids)); + changed += opts.setDebugIds(debuglevel, splitLines(dbgids)); + } + return S_OK; + } + + override HRESULT ClearSemanticProject() + { + /+ + synchronized(mSemanticProject) + mSemanticProject.disconnectAll(); + + mSemanticProject = new vdc.semantic.Project; + mSemanticProject.saveErrors = true; + +/ + return S_OK; + } + + override HRESULT UpdateModule(in BSTR filename, in BSTR srcText, in BOOL verbose) + { + string fname = to_string(filename); + size_t len = wcslen(srcText); + string text = to_string(srcText, len + 1); // DMD parser needs trailing 0 + text = text[0..$-1]; + + Module mod; + bool doCancel = false; + synchronized(gErrorSync) + { + // cancel existing + mod = findModule(fname, false); + if (mod) + { + if (auto pErr = cast(void*)mod in mErrors) + if (*pErr == "__parsing__") + doCancel = true; + } + + // always create new module + mod = findModule(fname, true); + mod.srcfile.setbuffer(cast(char*)(text.ptr), text.length); + mod.srcfile._ref = 1; // do not own buffer + + mErrors[cast(void*)mod] = "__pending__"; + } + if (doCancel) + { + Mem.cancel = true; + synchronized(gDMDSync) + { + // wait for parsing done + Mem.cancel = false; + } + } + + void doParse() + { + version(DebugServer) dbglog(" doParse: " ~ firstLine(text)); + + synchronized(gErrorSync) + { + auto pErr = cast(void*)mod in mErrors; + if (!pErr) + return; // already relaced by a new request + + *pErr = "__parsing__"; + } + string errors; + synchronized(gDMDSync) + { + try + { + initErrorFile(fname); + parseModules([mod]); + errors = gErrorMessages; + } + catch(Throwable t) + { + version(DebugServer) dbglog("UpdateModule.doParse: exception " ~ t.msg); + } + } + synchronized(gErrorSync) + { + if (auto pErr = cast(void*)mod in mErrors) + *pErr = errors; + } + + if(verbose) + writeReadyMessage(); + } + version(DebugServer) dbglog(" scheduleParse: " ~ firstLine(text)); + schedule(&doParse); + return S_OK; + } + + override HRESULT GetParseErrors(in BSTR filename, BSTR* errors) + { + string fname = to_string(filename); + + if(auto mod = findModule(fname, false)) + { + synchronized(gErrorSync) + { + if (auto pError = cast(void*)mod in mErrors) + { + if (*pError != "__pending__" && *pError != "__parsing__") + { + version(DebugServer) + dbglog("GetParseErrors: " ~ *pError); + + *errors = allocBSTR(*pError); + return S_OK; + } + } + } + } + return S_FALSE; + } + + override HRESULT GetTip(in BSTR filename, int startLine, int startIndex, int endLine, int endIndex) + { + string fname = to_string(filename); + + mTipSpan.start.line = startLine; + mTipSpan.start.index = startIndex; + mTipSpan.end.line = endLine; + mTipSpan.end.index = endIndex; + + Module m; + synchronized(gErrorSync) + { + m = findModule(fname, false); + if (!m) + return S_FALSE; + } + + void _getTip() + { + string txt; + synchronized(gDMDSync) + { + try + { + txt = findTip(m, startLine, startIndex + 1, endLine, endIndex + 1); + } + catch(Throwable t) + { + version(DebugServer) dbglog("GetTip: exception " ~ t.msg); + } + } + mLastTip = txt; + mSemanticTipRunning = false; + } + version(DebugServer) dbglog(" schedule GetTip: " ~ fname); + mSemanticTipRunning = true; + schedule(&_getTip); + + return S_OK; + } + + override HRESULT GetTipResult(ref int startLine, ref int startIndex, ref int endLine, ref int endIndex, BSTR* answer) + { + if(mSemanticTipRunning) + { + *answer = allocBSTR("__pending__"); + return S_OK; + } + + version(DebugServer) dbglog("GetTipResult: " ~ mLastTip); + writeReadyMessage(); + startLine = mTipSpan.start.line; + startIndex = mTipSpan.start.index; + endLine = mTipSpan.end.line; + endIndex = mTipSpan.end.index; + *answer = allocBSTR(mLastTip); + return S_OK; + } + + override HRESULT GetDefinition(in BSTR filename, int startLine, int startIndex, int endLine, int endIndex) + { + string fname = to_string(filename); + + mDefSpan.start.line = startLine; + mDefSpan.start.index = startIndex; + mDefSpan.end.line = endLine; + mDefSpan.end.index = endIndex; + + Module m; + synchronized(gErrorSync) + { + m = findModule(fname, false); + if (!m) + return S_FALSE; + } + + void _getDefinition() + { + string deffilename; + synchronized(gDMDSync) + { + try + { + deffilename = findDefinition(m, mDefSpan.start.line, mDefSpan.start.index); + } + catch(Throwable t) + { + version(DebugServer) dbglog("GetDefinition: exception " ~ t.msg); + } + } + mLastDefFile = deffilename; + mSemanticDefinitionRunning = false; + } + version(DebugServer) dbglog(" schedule GetDefinition: " ~ fname); + mSemanticDefinitionRunning = true; + schedule(&_getDefinition); + + return S_OK; + } + + override HRESULT GetDefinitionResult(ref int startLine, ref int startIndex, ref int endLine, ref int endIndex, BSTR* answer) + { + if(mSemanticDefinitionRunning) + { + *answer = allocBSTR("__pending__"); + return S_OK; + } + + version(DebugServer) dbglog("GetDefinitionResult: " ~ mLastDefFile); + writeReadyMessage(); + startLine = mDefSpan.start.line; + startIndex = mDefSpan.start.index; + endLine = mDefSpan.start.line; + endIndex = mDefSpan.start.index + 1; + *answer = allocBSTR(mLastDefFile); + return S_OK; + } + + override HRESULT GetSemanticExpansions(in BSTR filename, in BSTR tok, uint line, uint idx, in BSTR expr) + { + string[] symbols; + string fname = to_string(filename); + /+ + auto src = mSemanticProject.getModuleByFilename(fname); + if(!src) + return S_FALSE; + + string stok = to_string(tok); + string sexpr = to_string(expr); + void calcExpansions() + { + fnSemanticWriteError = &semanticWriteError; + try + { + mLastSymbols = null; //_GetSemanticExpansions(src, stok, line, idx, sexpr); + } + catch(Throwable t) + { + version(DebugServer) dbglog("GetSemanticExpansions.calcExpansions: exception " ~ t.msg); + logInfo(t.msg); + } + mSemanticExpansionsRunning = false; + } + version(DebugServer) dbglog(" schedule GetSemanticExpansions: " ~ fname); + mLastSymbols = null; + mSemanticExpansionsRunning = true; + schedule(&calcExpansions); + +/ + return S_OK; + } + + override HRESULT GetSemanticExpansionsResult(BSTR* stringList) + { + if(mSemanticExpansionsRunning) + return S_FALSE; + + Appender!string slist; + foreach(sym; mLastSymbols) + { + slist.put(sym); + slist.put('\n'); + } + *stringList = allocBSTR(slist.data); + + version(DebugServer) dbglog("GetSemanticExpansionsResult: " ~ slist.data); + writeReadyMessage(); + return S_OK; + } + + // obsolete, implement GetBinaryIsInLocations + override HRESULT IsBinaryOperator(in BSTR filename, uint startLine, uint startIndex, uint endLine, uint endIndex, BOOL* pIsOp) + { + if(!pIsOp) + return E_POINTER; + + *pIsOp = false; + return S_OK; + } + + override HRESULT ConfigureCommentTasks(in BSTR tasks) + { + return E_NOTIMPL; + } + + override HRESULT GetCommentTasks(in BSTR filename, BSTR* tasks) + { + return E_NOTIMPL; + } + + override HRESULT GetBinaryIsInLocations(in BSTR filename, VARIANT* locs) + { + // array of pairs of DWORD + int[] locData; + string fname = to_string(filename); + /+ + synchronized(mSemanticProject) + if(auto src = mSemanticProject.getModuleByFilename(fname)) + if(auto mod = src.parsed) + { + mod.visit(delegate bool (ast.Node n) { + if(n.id == TOK_in || n.id == TOK_is) + if(cast(ast.BinaryExpression) n) + { + locData ~= n.span.start.line; + locData ~= n.span.start.index; + } + return true; + }); + } + +/ + SAFEARRAY *sa = SafeArrayCreateVector(VT_INT, 0, cast(ULONG) locData.length); + if(!sa) + return E_OUTOFMEMORY; + + for(LONG index = 0; index < locData.length; index++) + SafeArrayPutElement(sa, &index, &locData[index]); + + locs.vt = VT_ARRAY; + locs.parray = sa; + return S_OK; + } + + override HRESULT GetLastMessage(BSTR* message) + { + if(!mLastMessage.length) + { + if(mNextReadyMessage > Clock.currTime()) + return S_FALSE; + + mLastMessage = "Ready"; + mNextReadyMessage = Clock.currTime().add!"years"(1); + } + *message = allocBSTR(mLastMessage); + mLastMessage = null; + return S_OK; + } + + override HRESULT GetReferences(in BSTR filename, in BSTR tok, uint line, uint idx, in BSTR expr) + { + return E_NOTIMPL; + } + + override HRESULT GetReferencesResult(BSTR* stringList) + { + 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) + __gshared TaskPool parseTaskPool; + + void runTask(T)(T dg) + { + if(!parseTaskPool) + { + int threads = defaultPoolThreads; + if(threads < 1) + threads = 1; + parseTaskPool = new TaskPool(threads); + parseTaskPool.isDaemon = true; + parseTaskPool.priority(core.thread.Thread.PRIORITY_MIN); + } + auto task = task(dg); + parseTaskPool.put(task); + } + + void writeReadyMessage() + { + if(mHadMessage) + { + mNextReadyMessage = Clock.currTime() + dur!"seconds"(2); + mHadMessage = false; + } + } + + void parseModules(Module[] modules) + { + clearDmdStatics(); + + synchronized(gOptSync) + { + global.params.color = false; + global.params.link = true; + global.params.useAssert = mOptions.debugOn; + global.params.useInvariants = mOptions.debugOn; + global.params.useIn = mOptions.debugOn; + global.params.useOut = mOptions.debugOn; + global.params.useArrayBounds = mOptions.noBoundsCheck ? BOUNDSCHECKon : BOUNDSCHECKoff; // set correct value later + global.params.doDocComments = mOptions.doDoc; + global.params.useSwitchError = true; + global.params.useInline = false; + global.params.obj = false; + global.params.useDeprecated = mOptions.noDeprecated ? 0 : 2; + global.params.linkswitches = new Strings(); + global.params.libfiles = new Strings(); + global.params.dllfiles = new Strings(); + global.params.objfiles = new Strings(); + global.params.ddocfiles = new Strings(); + // Default to -m32 for 32 bit dmd, -m64 for 64 bit dmd + global.params.is64bit = mOptions.x64; + global.params.mscoff = mOptions.msvcrt; + global.params.cpu = CPU.baseline; + + global.params.versionlevel = mOptions.versionIds.level; + global.params.versionids = new Strings(); + foreach(id, v; mOptions.versionIds.identifiers) + global.params.versionids.push(toStringz(id)); + + VersionCondition.addPredefinedGlobalIdent("DigitalMars"); + VersionCondition.addPredefinedGlobalIdent("Windows"); + VersionCondition.addPredefinedGlobalIdent("LittleEndian"); + VersionCondition.addPredefinedGlobalIdent("D_Version2"); + VersionCondition.addPredefinedGlobalIdent("all"); + if (global.params.is64bit) + { + VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86_64"); + VersionCondition.addPredefinedGlobalIdent("X86_64"); + VersionCondition.addPredefinedGlobalIdent("Win64"); + } + else + { + VersionCondition.addPredefinedGlobalIdent("D_InlineAsm"); //legacy + VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86"); + VersionCondition.addPredefinedGlobalIdent("X86"); + VersionCondition.addPredefinedGlobalIdent("Win32"); + } + if (global.params.mscoff) + VersionCondition.addPredefinedGlobalIdent("CRuntime_Microsoft"); + else + VersionCondition.addPredefinedGlobalIdent("CRuntime_DigitalMars"); + if (global.params.isLP64) + VersionCondition.addPredefinedGlobalIdent("D_LP64"); + if (global.params.doDocComments) + VersionCondition.addPredefinedGlobalIdent("D_Ddoc"); + if (global.params.cov) + VersionCondition.addPredefinedGlobalIdent("D_Coverage"); + if (global.params.pic) + VersionCondition.addPredefinedGlobalIdent("D_PIC"); + if (global.params.useUnitTests) + VersionCondition.addPredefinedGlobalIdent("unittest"); + if (global.params.useAssert) + VersionCondition.addPredefinedGlobalIdent("assert"); + if (global.params.useArrayBounds == BOUNDSCHECKoff) + VersionCondition.addPredefinedGlobalIdent("D_NoBoundsChecks"); + if (global.params.betterC) + VersionCondition.addPredefinedGlobalIdent("D_betterC"); + + // always enable for tooltips + global.params.doDocComments = true; + + global.params.debugids = new Strings(); + global.params.debuglevel = mOptions.debugIds.level; + foreach(id, v; mOptions.debugIds.identifiers) + global.params.debugids.push(toStringz(id)); + + global.path = new Strings(); + foreach(i; mOptions.importDirs) + global.path.push(toStringz(i)); + + global.filePath = new Strings(); + foreach(i; mOptions.stringImportDirs) + global.filePath.push(toStringz(i)); + } + + // Initialization + Token._init(); + Type._init(); + Id.initialize(); + Module._init(); + Target._init(); + Expression._init(); + Objc._init(); + builtin_init(); + Module.rootModule = null; + global.gag = false; + global.gaggedErrors = 0; + global.errors = 0; + global.warnings = 0; + + version(traceGC) + { + wipeStack(); + GC.collect(); + dumpGC(); + } + else + GC.collect(); + + // redo module name with the new Identifier.stringtable + foreach (m; modules) + { + auto fname = to!string(m.srcfile.name.str); + string name = stripExtension(baseName(fname)); + m.ident = Identifier.idPool(name); + } + + for (size_t i = 0; i < modules.length; i++) + { + Module m = modules[i]; + m.read(Loc()); + } + size_t filecount = modules.length; + for (size_t filei = 0, modi = 0; filei < filecount; filei++, modi++) + { + Module m = modules[modi]; + if (!Module.rootModule) + Module.rootModule = m; + m.importedFrom = m; + m.parse(); + } + for (size_t i = 0; i < modules.length; i++) + { + Module m = modules[i]; + m.importAll(null); + } + + // Do semantic analysis + for (size_t i = 0; i < modules.length; i++) + { + Module m = modules[i]; + m.semantic(null); + } + + Module.dprogress = 1; + Module.runDeferredSemantic(); + + // Do pass 2 semantic analysis + for (size_t i = 0; i < modules.length; i++) + { + Module m = modules[i]; + m.semantic2(null); + } + Module.runDeferredSemantic2(); + + // Do pass 3 semantic analysis + for (size_t i = 0; i < modules.length; i++) + { + Module m = modules[i]; + m.semantic3(null); + } + Module.runDeferredSemantic3(); + } + +private: + static void clearModule(Module m) + { + m.insearch = 0; + m.searchCacheIdent = null; + m.searchCacheSymbol = null; // cached value of search + m.searchCacheFlags = 0; // cached flags + + m.importedFrom = null; + m.decldefs = null; // top level declarations for this Module + m.aimports = Modules(); // all imported modules + + m.debuglevel = 0; // debug level + m.debugids = null; // debug identifiers + m.debugidsNot = null; // forward referenced debug identifiers + + m.versionlevel = 0; // version level + m.versionids = null; // version identifiers + m.versionidsNot = null; // forward referenced version identifiers + + m.macrotable = null; // document comment macros + m.escapetable = null; // document comment escapes + + m._scope = null; // !=null means context to use for semantic() + m.prettystring = null; // cached value of toPrettyChars() + m.errors = 0; // this symbol failed to pass semantic() + } + + Module findModule(string fname, bool createNew) + { + size_t pos = mModules.length; + foreach (i, m; mModules) + if (_stricmp(m.srcfile.name.str, fname) == 0) + { + if (createNew) + { + pos = i; + break; + } + return m; + } + + if (!createNew) + return null; + + auto m = new Module(toStringz(fname), null, false, false); + if (pos < mModules.length) + { + mErrors.remove(cast(void*)mModules[pos]); + mModules[pos] = m; + } + else + mModules ~= m; + return m; + } + + version(SingleThread) Tid mTid; + + Options mOptions; + Module[] mModules; + string[void*] mErrors; // cannot index by C++ class Module + + bool mSemanticExpansionsRunning; + bool mSemanticTipRunning; + bool mSemanticDefinitionRunning; + + string mModuleToParse; + string mLastTip; + TextSpan mTipSpan; + string mLastDefFile; + TextSpan mDefSpan; + string[] mLastSymbols; + string mLastMessage; + string mLastError; + bool mHadMessage; + SysTime mNextReadyMessage; +} + +shared(Object) gErrorSync = new Object; +__gshared string gErrorFile; +__gshared string gErrorMessages; + +extern(C++) +void verrorPrint(const ref Loc loc, Color headerColor, const(char)* header, + const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) +{ + if (!loc.filename) + return; + + synchronized(gErrorSync) + { + version(x) + if (_stricmp(loc.filename, gErrorFile) != 0) + return; + + __gshared char buf[4096]; + int len = snprintf(buf.ptr, buf.length, "%d,%d,%d,%d:", loc.linnum, loc.charnum - 1, loc.linnum, loc.charnum); + if (p1 && len < buf.length) + len += snprintf(buf.ptr + len, buf.length - len, "%s ", p1); + if (p2 && len < buf.length) + len += snprintf(buf.ptr + len, buf.length - len, "%s ", p2); + if (len < buf.length) + len += vsnprintf(buf.ptr + len, buf.length - len, format, ap); + if (len < buf.length) + buf[len++] = '\n'; + else + buf[$-1] = '\n'; + + gErrorMessages ~= buf[0..len]; + } +} + +void initErrorFile(string fname) +{ + synchronized(gErrorSync) + { + gErrorFile = fname; + gErrorMessages = null; + } +} + +int _stricmp(const(char)*str1, string s2) +{ + const(char)[] s1 = str1[0..strlen(str1)]; + return icmp(s1, s2); +} + +int _stricmp(const(wchar)*str1, wstring s2) +{ + const(wchar)[] s1 = str1[0..wcslen(str1)]; + return icmp(s1, s2); +} + +//////////////////////////////////////////////////////////////// +enum string[2][] dmdStatics = +[ + ["D4ddmd5clone12buildXtoHashRC4ddmd7dstruct17StructDeclarationPS4ddmd6dscope5ScopeZ8tftohashC4ddmd5mtype12TypeFunction", "TypeFunction"], + ["D4ddmd7dstruct15search_toStringRC4ddmd7dstruct17StructDeclarationZ10tftostringC4ddmd5mtype12TypeFunction", "TypeFunction"], + ["D4ddmd10expression11loadStdMathRZ10impStdMathC4ddmd7dimport6Import", "Import"], + ["D4ddmd4func15FuncDeclaration8genCfuncRPS4ddmd4root5array33__T5ArrayTC4ddmd5mtype9ParameterZ5ArrayC4ddmd5mtype4TypeC4ddmd10identifier10IdentifiermZ2stC4ddmd7dsymbol12DsymbolTable", "DsymbolTable"], + ["D4ddmd5mtype10TypeAArray6dotExpMRPS4ddmd6dscope5ScopeC4ddmd10expression10ExpressionC4ddmd10identifier10IdentifieriZ8fd_aaLenC4ddmd4func15FuncDeclaration", "FuncDeclaration"], + ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ3feqC4ddmd4func15FuncDeclaration", "FuncDeclaration"], + ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ4fcmpC4ddmd4func15FuncDeclaration", "FuncDeclaration"], + ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ5fhashC4ddmd4func15FuncDeclaration", "FuncDeclaration"], + + ["D4ddmd7dmodule6Module19runDeferredSemanticRZ6nestedi", "int"], + ["D4ddmd10dsymbolsem22DsymbolSemanticVisitor5visitMRC4ddmd9dtemplate13TemplateMixinZ4nesti", "int"], + ["D4ddmd9dtemplate16TemplateInstance16tryExpandMembersMRPS4ddmd6dscope5ScopeZ4nesti", "int"], + ["D4ddmd9dtemplate16TemplateInstance12trySemantic3MRPS4ddmd6dscope5ScopeZ4nesti", "int"], + ["D4ddmd13expressionsem25ExpressionSemanticVisitor5visitMRC4ddmd10expression7CallExpZ4nesti", "int"], + ["D4ddmd5mtype4Type8noMemberMRPS4ddmd6dscope5ScopeC4ddmd10expression10ExpressionC4ddmd10identifier10IdentifieriZ4nesti", "int"], +]; + +string cmangled(string s) +{ + version(Win64) + return "_" ~ s; + else + return s; +} +string genDeclDmdStatics() +{ + string s; + foreach (decl; dmdStatics) + s ~= q{extern extern(C) __gshared } ~ decl[1] ~ " " ~ cmangled(decl[0]) ~ ";\n"; + return s; +} + +string genInitDmdStatics() +{ + string s; + foreach (decl; dmdStatics) + s ~= cmangled(decl[0]) ~ " = " ~ decl[1] ~ ".init;\n"; + return s; +} + +mixin(genDeclDmdStatics); + +void clearDmdStatics() +{ + mixin(genInitDmdStatics); + + Module.rootModule = null; + Module.modules = null; // symbol table of all modules + Module.amodules = Modules(); // array of all modules + Module.deferred = Dsymbols(); // deferred Dsymbol's needing semantic() run on them + Module.deferred2 = Dsymbols(); // deferred Dsymbol's needing semantic2() run on them + Module.deferred3 = Dsymbols(); // deferred Dsymbol's needing semantic3() run on them + Module.dprogress = 0; // progress resolving the deferred list + Module.moduleinfo = null; + + ClassDeclaration.object = null; + ClassDeclaration.throwable = null; + ClassDeclaration.exception = null; + ClassDeclaration.errorException = null; + ClassDeclaration.cpp_type_info_ptr = null; + + StructDeclaration.xerreq = null; + StructDeclaration.xerrcmp = null; + + Type.dtypeinfo = null; + Type.typeinfoclass = null; + Type.typeinfointerface = null; + Type.typeinfostruct = null; + Type.typeinfopointer = null; + Type.typeinfoarray = null; + Type.typeinfostaticarray = null; + Type.typeinfoassociativearray = null; + Type.typeinfovector = null; + Type.typeinfoenum = null; + Type.typeinfofunction = null; + Type.typeinfodelegate = null; + Type.typeinfotypelist = null; + Type.typeinfoconst = null; + Type.typeinfoinvariant = null; + Type.typeinfoshared = null; + Type.typeinfowild = null; + Type.rtinfo = null; + Type.stringtable.reset(); + + // statementsem + // static __gshared FuncDeclaration* fdapply = [null, null]; + // static __gshared TypeDelegate* fldeTy = [null, null]; + + ctfeStack = ctfeStack.init; + Scope.freelist = null; + //Token.freelist = null; + + Identifier.initTable(); +} + +//////////////////////////////////////////////////////////////// +Loc endLoc(Dsymbol sym) +{ + return Loc(); +} + +// walk the complete AST (declarations, statement and expressions) +// assumes being started on module/declaration level +extern(C++) class ASTVisitor : StoppableVisitor +{ + alias visit = super.visit; + + void visitExpression(Expression expr) + { + if (stop || !expr) + return; + + if (walkPostorder(expr, this)) + stop = true; + } + + void visitStatement(Statement stmt) + { + if (stop || !stmt) + return; + + if (walkPostorder(stmt, this)) + stop = true; + } + + void visitDeclaration(Dsymbol sym) + { + if (stop || !sym) + return; + + sym.accept(this); + } + + override void visit(ScopeDsymbol scopesym) + { + // optimize to only visit members in approriate source range + size_t mcnt = scopesym.members ? scopesym.members.dim : 0; + for (size_t m = 0; !stop && m < mcnt; m++) + { + Dsymbol s = (*scopesym.members)[m]; + s.accept(this); + } + } + + override void visit(VarDeclaration decl) + { + visit(cast(Declaration)decl); + + if (!stop && decl._init) + decl._init.accept(this); + } + + override void visit(ExpInitializer einit) + { + visitExpression(einit.exp); + } + + override void visit(FuncDeclaration decl) + { + visit(cast(Declaration)decl); + + if (decl.parameters) + foreach(p; *decl.parameters) + if (!stop) + p.accept(this); + + visitStatement(decl.frequire); + visitStatement(decl.fensure); + visitStatement(decl.fbody); + } + + override void visit(ErrorStatement stmt) + { + visitStatement(stmt.errStmt); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(ExpStatement stmt) + { + visitExpression(stmt.exp); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(CompileStatement stmt) + { + visitExpression(stmt.exp); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(WhileStatement stmt) + { + visitExpression(stmt.condition); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(DoStatement stmt) + { + visitExpression(stmt.condition); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(ForStatement stmt) + { + visitExpression(stmt.condition); + visitExpression(stmt.increment); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(ForeachStatement stmt) + { + if (stmt.parameters) + foreach(p; *stmt.parameters) + if (!stop) + p.accept(this); + visitExpression(stmt.aggr); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(ForeachRangeStatement stmt) + { + if (!stop && stmt.prm) + stmt.prm.accept(this); + visitExpression(stmt.lwr); + visitExpression(stmt.upr); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(IfStatement stmt) + { + if (!stop && stmt.prm) + stmt.prm.accept(this); + visitExpression(stmt.condition); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(PragmaStatement stmt) + { + if (!stop && stmt.args) + foreach(a; *stmt.args) + if (!stop) + a.accept(this); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(StaticAssertStatement stmt) + { + visitExpression(stmt.sa.exp); + visitExpression(stmt.sa.msg); + visit(cast(Statement)stmt); + } + + override void visit(SwitchStatement stmt) + { + visitExpression(stmt.condition); + visit(cast(Statement)stmt); + } + + override void visit(CaseStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(CaseRangeStatement stmt) + { + visitExpression(stmt.first); + visitExpression(stmt.last); + visit(cast(Statement)stmt); + } + + override void visit(GotoCaseStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(ReturnStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(SynchronizedStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(WithStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(TryCatchStatement stmt) + { + if (!stop && stmt.catches) + foreach(c; *stmt.catches) + visitDeclaration(c.var); + visit(cast(Statement)stmt); + } + + override void visit(ThrowStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(ImportStatement stmt) + { + if (!stop && stmt.imports) + foreach(i; *stmt.imports) + visitDeclaration(i); + visit(cast(Statement)stmt); + } + + override void visit(DeclarationExp expr) + { + visitDeclaration(expr.declaration); + } + + override void visit(ErrorExp expr) + { + visitExpression(expr.errExp); + if (!stop) + visit(cast(Expression)expr); + } + +} + +extern(C++) class FindASTVisitor : ASTVisitor +{ + const(char*) filename; + int startLine; + int startIndex; + int endLine; + int endIndex; + + alias visit = super.visit; + RootObject found; + + this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) + { + this.filename = filename; + this.startLine = startLine; + this.startIndex = startIndex; + this.endLine = endLine; + this.endIndex = endIndex; + } + + bool foundNode(RootObject obj) + { + if (!obj) + { + found = obj; + stop = true; + } + return stop; + } + + bool matchIdentifier(ref Loc loc, Identifier ident) + { + if (ident) + if (loc.filename is filename) + if (loc.linnum == startLine && loc.linnum == endLine) + if (loc.charnum <= startIndex && loc.charnum + ident.toString().length >= endIndex) + return true; + return false; + } + + override void visit(Dsymbol sym) + { + if (!found && matchIdentifier(sym.loc, sym.ident)) + foundNode(sym); + } + + override void visit(ScopeDsymbol scopesym) + { + // optimize to only visit members in approriate source range + size_t mcnt = scopesym.members ? scopesym.members.dim : 0; + for (size_t m = 0; m < mcnt; m++) + { + Dsymbol s = (*scopesym.members)[m]; + if (s.isTemplateInstance) + continue; + if (s.loc.filename !is filename) + continue; + + if (s.loc.linnum > endLine || (s.loc.linnum == endLine && s.loc.charnum > endIndex)) + continue; + + Loc nextloc; + for (m++; m < mcnt; m++) + { + auto ns = (*scopesym.members)[m]; + if (ns.isTemplateInstance) + continue; + if (ns.loc.filename is filename) + { + nextloc = ns.loc; + break; + } + } + m--; + + if (nextloc.filename) + if (nextloc.linnum < startLine || (nextloc.linnum == startLine && nextloc.charnum < startIndex)) + continue; + + s.accept(this); + + if (!found) + foundNode(s); + break; + } + } + override void visit(TemplateInstance) + { + // skip members added by semantic + } + + override void visit(Statement stmt) + { + // default to nothing + } + + override void visit(CallExp expr) + { + super.visit(expr); + } + + override void visit(Expression expr) + { + // default to nothing + } + override void visit(SymbolExp expr) + { + if (!found && expr.var) + if (matchIdentifier(expr.loc, expr.var.ident)) + foundNode(expr); + } +} + +extern(C++) class FindTipVisitor : FindASTVisitor +{ + string tip; + + alias visit = super.visit; + + this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) + { + super(filename, startLine, startIndex, endLine, endIndex); + } + + void visitCallExpression(CallExp expr) + { + if (!found) + { + // replace function type with actual + visitExpression(expr); + if (found is expr.e1) + { + foundNode(expr); + } + } + } + + override bool foundNode(RootObject obj) + { + found = obj; + if (obj) + { + string tipForDeclaration(Declaration decl) + { + if (auto func = decl.isFuncDeclaration()) + { + OutBuffer buf; + functionToBufferWithIdent(decl.type.toTypeFunction(), &buf, decl.toPrettyChars()); + auto res = buf.peekSlice(); + buf.extractString(); // take ownership + return cast(string)res; + } + + string txt; + if (decl.isParameter()) + txt = "(parameter) "; + else if (!decl.isDataseg() && !decl.isCodeseg() && !decl.isField()) + txt = "(local variable) "; + bool fqn = txt.empty; + + if (decl.type) + txt ~= to!string(decl.type.toPrettyChars()) ~ " "; + txt ~= to!string(fqn ? decl.toPrettyChars(fqn) : decl.toChars()); + return txt; + } + + const(char)* toc = null; + if (auto t = obj.isType()) + toc = t.toChars(); + else if (auto e = obj.isExpression()) + { + switch(e.op) + { + case TOKvar: + case TOKsymoff: + tip = tipForDeclaration((cast(SymbolExp)e).var); + break; + default: + if (e.type) + toc = e.type.toPrettyChars(); + break; + } + } + else if (auto s = obj.isDsymbol()) + { + if (auto decl = s.isDeclaration) + tip = tipForDeclaration(decl); + else + toc = s.toPrettyChars(true); + } + if (!tip.length) + { + if (!toc) + toc = obj.toChars(); + tip = to!string(toc); + } + // append doc + stop = true; + } + return stop; + } +} + +RootObject _findAST(Dsymbol sym, const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) +{ + scope FindASTVisitor fav = new FindASTVisitor(filename, startLine, startIndex, endLine, endIndex); + sym.accept(fav); + + return fav.found; +} + +RootObject findAST(Module mod, int startLine, int startIndex, int endLine, int endIndex) +{ + auto filename = mod.srcfile.name.str; + return _findAST(mod, filename, startLine, startIndex, endLine, endIndex); +} + +string findTip(Module mod, int startLine, int startIndex, int endLine, int endIndex) +{ + auto filename = mod.srcfile.name.str; + scope FindTipVisitor ftv = new FindTipVisitor(filename, startLine, startIndex, endLine, endIndex); + mod.accept(ftv); + + return ftv.tip; +} +//////////////////////////////////////////////////////////////// + +extern(C++) class FindDefinitionVisitor : FindASTVisitor +{ + Loc loc; + + alias visit = super.visit; + + this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) + { + super(filename, startLine, startIndex, endLine, endIndex); + } + + override bool foundNode(RootObject obj) + { + found = obj; + if (obj) + { + if (auto t = obj.isType()) + { + if (t.ty == Tstruct) + loc = (cast(TypeStruct)t).sym.loc; + } + else if (auto e = obj.isExpression()) + { + switch(e.op) + { + case TOKvar: + case TOKsymoff: + loc = (cast(SymbolExp)e).var.loc; + break; + default: + loc = e.loc; + break; + } + } + else if (auto s = obj.isDsymbol()) + { + loc = s.loc; + } + stop = true; + } + return stop; + } +} + +string findDefinition(Module mod, ref int line, ref int index) +{ + auto filename = mod.srcfile.name.str; + scope FindDefinitionVisitor fdv = new FindDefinitionVisitor(filename, line, index, line, index + 1); + mod.accept(fdv); + + if (!fdv.loc.filename) + return null; + line = fdv.loc.linnum; + index = fdv.loc.charnum; + return to!string(fdv.loc.filename); +} + +extern(C) int _CrtDumpMemoryLeaks(); +extern(C) void dumpGC(); + +//////////////////////////////////////////////////////////////// +unittest +{ + //_CrtDumpMemoryLeaks(); + dumpGC(); + + DMDServer srv = newCom!DMDServer; + addref(srv); + scope(exit) release(srv); + + auto filename = allocBSTR("source.d"); + auto imp = allocBSTR(r"c:\l\D\dmd2.076\dmd2\src\druntime\import" ~ "\n" ~ + r"c:\l\D\dmd2.076\dmd2\src\phobos"); + auto empty = allocBSTR(""); + uint flags = ConfigureFlags!()(false, //bool unittestOn + false, //bool debugOn, + true, //bool x64 + false, //bool cov + false, //bool doc, + false, //bool nobounds, + false, //bool gdc, + 0, //int versionLevel, + 0, //int debugLevel, + false, //bool noDeprecated, + false, //bool ldc, + true, //bool msvcrt, + true, //bool mixinAnalysis, + true); //bool ufcsExpansionsfalse, + + HRESULT hr; + hr = srv.ConfigureSemanticProject(filename, imp, empty, empty, empty, flags); + assert(hr == S_OK); + + void checkErrors(string src, string expected_err) + { + auto source = allocBSTR(src); + HRESULT hr = srv.UpdateModule(filename, source, false); + assert(hr == S_OK); + BSTR errors; + while (srv.GetParseErrors(filename, &errors) == S_FALSE) + Thread.sleep(10.msecs); + + string err = detachBSTR(errors); + assert(err == expected_err); + freeBSTR(source); + } + + void checkTip(int line, int col, string expected_tip) + { + HRESULT hr = srv.GetTip(filename, line, col, line, col + 1); + assert(hr == S_OK); + BSTR bstrTip; + int startLine, startIndex, endLine, endIndex; + while (srv.GetTipResult(startLine, startIndex, endLine, endIndex, &bstrTip) == S_FALSE || _stricmp(bstrTip, "__pending__"w) == 0) + { + detachBSTR(bstrTip); + Thread.sleep(10.msecs); + } + + string tip = detachBSTR(bstrTip); + assert(tip == expected_tip); + } + + void checkDefinition(int line, int col, string expected_fname, int expected_line, int expected_col) + { + HRESULT hr = srv.GetDefinition(filename, line, col, line, col + 1); + assert(hr == S_OK); + BSTR bstrFile; + int startLine, startIndex, endLine, endIndex; + while (srv.GetDefinitionResult(startLine, startIndex, endLine, endIndex, &bstrFile) == S_FALSE || _stricmp(bstrFile, "__pending__"w) == 0) + { + detachBSTR(bstrFile); + Thread.sleep(10.msecs); + } + + string file = detachBSTR(bstrFile); + assert(file == expected_fname); + assert(startLine == expected_line); + assert(startIndex == expected_col); + } + + string source; +/+ + source = q{ + int main() + { + return abc; + } + }; + checkErrors(source, "4,10,4,11:undefined identifier `abc`\n"); + + GC.collect(); + + source = q{ + int main() + { + return abcd; + } + }; + checkErrors(source, "4,10,4,11:undefined identifier `abcd`\n"); ++/ + wipeStack(); + GC.collect(); + + //_CrtDumpMemoryLeaks(); + dumpGC(); + + for (int i = 0; i < 2; i++) + { + source = q{ + import std.stdio; + int main(string[] args) + { + int xyz = 7; + writeln(1, 2, 3); + return xyz; + } + }; + checkErrors(source, ""); + + srv.mModules = null; + srv.mErrors = null; + clearDmdStatics (); + + wipeStack(); + GC.collect(); + + //_CrtDumpMemoryLeaks(); + dumpGC(); + } + + + checkTip(5, 9, "(local variable) int xyz"); + checkTip(6, 9, "void std.stdio.writeln!(int, int, int).writeln(int _param_0, int _param_1, int _param_2) @safe"); + checkTip(7, 12, "(local variable) int xyz"); + + wipeStack(); + GC.collect(); + + checkDefinition(7, 12, "source.d", 5, 8); // xyz +} diff --git a/vdc/dmdserver.idl b/vdc/dmdserver.idl new file mode 100644 index 00000000..a59d2120 --- /dev/null +++ b/vdc/dmdserver.idl @@ -0,0 +1,25 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2012 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +// bring in core IDL files +import "oaidl.idl"; +import "ivdserver.idl"; + +// library statement +[uuid(002a2de9-8bb6-484d-9907-7e4ad4084715), version(1.0), + helpstring("DMD Semantic Server")] +library VDServerLib +{ + importlib("stdole32.tlb"); + [uuid(002a2de9-8bb6-484d-9906-7e4ad4084715)] + coclass VDServerClassFactory + { + [default] interface IVDServer; + }; +}; + diff --git a/vdc/dmdserver.rc b/vdc/dmdserver.rc new file mode 100644 index 00000000..ab756cf7 --- /dev/null +++ b/vdc/dmdserver.rc @@ -0,0 +1,85 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2010 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +///////////////////////////////////////////////////////////////////////////// +// Resources for the Visual D semantic server +// +1 TYPELIB dmdserver.tlb + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// +#define __str(x) #x +#define _str(x) __str(x) + +#include "../version" + +#if VERSION_BUILD > 0 +#define VERSION_POSTFIX _str(VERSION_BETA) _str(VERSION_BUILD) +#else +#define VERSION_POSTFIX +#endif + +#define VER_COMPANYNAME_STR "Rainer Schuetze" +#define VER_FILEVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_REVISION +#define VER_FILEVERSION_STR _str(VERSION_MAJOR.VERSION_MINOR.VERSION_REVISION) VERSION_POSTFIX +#define VER_PRODUCTVERSION VER_FILEVERSION +#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR +#define VER_LEGALCOPYRIGHT_STR "(c) 2017 Rainer Schuetze" + +#define VER_FILEDESCRIPTION_STR "DMD Semantic Server\0" +#define VER_PRODUCTNAME_STR "DMDServer\0" +#define VER_INTERNALNAME_STR "dmdserver.exe\0" +#define VER_ORIGINALFILENAME_STR "dmdserver.exe\0" +#define VER_LANGUAGENEUTRAL + +#define VER_FILEFLAGSMASK 0x3fL +#define VER_FILEFLAGS 0x8L +#define VER_FILEOS 0x40004L +#define VER_FILETYPE 0x1L // VS_APP +#define VER_FILESUBTYPE 0x0L // unknown + +#define VER_BLOCKHEADER "040904b0" +#define VER_TRANSLATION 0x409 + +///////////////////////////////////////////////////////////////////////////// +#define VS_VERSION_INFO 1 + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEFLAGSMASK VER_FILEFLAGSMASK +FILEFLAGS VER_FILEFLAGS +FILEOS VER_FILEOS +FILETYPE VER_FILETYPE +FILESUBTYPE VER_FILESUBTYPE +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK VER_BLOCKHEADER + BEGIN + VALUE "CompanyName", VER_COMPANYNAME_STR + VALUE "FileDescription", VER_FILEDESCRIPTION_STR + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", VER_INTERNALNAME_STR + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR + VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR + VALUE "ProductName", VER_PRODUCTNAME_STR + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", VER_TRANSLATION, 0x04B0 + END +END + +IDI_VISUALD ICON "dmdicon.ico" + +///////////////////////////////////////////////////////////////////////////// diff --git a/vdc/dmdserver.visualdproj b/vdc/dmdserver.visualdproj new file mode 100644 index 00000000..1293bcc8 --- /dev/null +++ b/vdc/dmdserver.visualdproj @@ -0,0 +1,1223 @@ + + {34289BD7-AB7E-4264-B146-8139DDE9F0BF} + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -c -cpp -Isrc;src\backend;src\tk;src\root -DMARS -e -wx -DTARGET_WINDOS=1 -DDM_TARGET_CPU_X86=1 + 1 + 0 + c:\l\d\dmd2\windows\bin\dmd.exe + dmd\src + dmd dmd\res + ..\bin\$(ConfigurationName) + $(OutDir)\$(PlatfromName)\$(ProjectName) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS NoBackend + 0 + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 2 + 0 + -L/STACK:8388608 + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -c -cpp -Isrc;src\backend;src\tk;src\root -DMARS -e -wx -DTARGET_WINDOS=1 -DDM_TARGET_CPU_X86=1 + 1 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + + $(OutDir) ..\..\res + ..\bin\$(ConfigurationName) + $(OutDir)\$(PlatfromName)\$(ProjectName) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS + 0 + 0 + 0 + 0 + + + + 0 + + 0 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 1 + 0 + -L/STACK:8388608 + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -nologo -c -TP -Isrc -Isrc\backend -Isrc\tk -Isrc\root -Isrc\vcbuild -DTARGET_WINDOS=1 -FIvcbuild\warnings.h + 1 + 0 + c:\l\d\dmd2\windows\bin\dmd.exe + + $(OutDir) ..\..\res + ..\bin\$(ConfigurationName) + $(OutDir)\$(PlatfromName)\$(ProjectName) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS + 0 + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 2 + 0 + -L/STACK:8388608 + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -nologo -c -TP -Isrc -Isrc\backend -Isrc\tk -Isrc\root -Isrc\vcbuild -DTARGET_WINDOS=1 -FIvcbuild\warnings.h + 1 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + + $(OutDir) ..\..\res + ..\bin\$(ConfigurationName) + $(OutDir)\$(PlatfromName)\$(ProjectName) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS + 0 + 0 + 0 + 0 + + + + 0 + + 0 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 1 + 0 + -L/STACK:8388608 + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -c -nologo -c -TP -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + 1 + 0 + c:\l\d\dmd2\windows\bin\dmd.exe + dmd\src .. + dmd dmd\res + ..\bin\$(ConfigurationName) + $(OutDir)\$(PlatfromName)\$(ProjectName) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS NoBackend GC + 0 + 2 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib oleaut32.lib + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 2 + 0 + -L/STACK:8388608 + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -c -nologo -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + 1 + 0 + c:\l\d\dmd2\windows\bin\dmd.exe + dmd\src .. $(DMDInstallDir)\src\druntime\src + dmd dmd\res + ..\bin\$(ConfigurationName)\$(PlatfromName)\$(ProjectName) + $(OutDir) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS NoBackend GC + 0 + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib oleaut32.lib + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 2 + 1 + -L/STACK:8388608 -gf + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -c -nologo -c -TP -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + 1 + 0 + c:\l\d\dmd2\windows\bin\dmd.exe + dmd\src .. + dmd dmd\res + ..\bin\$(ConfigurationName) + $(OutDir)\$(PlatfromName)\$(ProjectName) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS NoBackend GC + 0 + 2 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib oleaut32.lib + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 2 + 0 + -L/STACK:8388608 + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 2 + 0 + $(CC) -c -nologo -c -TP -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + 1 + 0 + c:\l\d\dmd2\windows\bin\dmd.exe + dmd\src .. + dmd dmd\res + ..\bin\$(ConfigurationName) + $(OutDir)\$(PlatfromName)\$(ProjectName) + + + 0 + + + + + 0 + + + 0 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS NoBackend GC + 0 + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib oleaut32.lib + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 2 + 0 + -L/STACK:8388608 + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -c -nologo -c -TP -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + 1 + 0 + c:\l\d\dmd2\windows\bin\dmd.exe + dmd\src .. + dmd dmd\res + ..\bin\$(ConfigurationName) + $(OutDir)\$(PlatfromName)\$(ProjectName) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS NoBackend GC + 0 + 2 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib oleaut32.lib + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 2 + 0 + -L/STACK:8388608 + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -c -nologo -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + 1 + 0 + c:\l\d\dmd2\windows\bin\dmd.exe + dmd\src .. $(DMDInstallDir)\src\druntime\src + dmd dmd\res + ..\bin\$(ConfigurationName)\$(PlatfromName)\$(ProjectName) + $(OutDir) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS NoBackend GC + 0 + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib oleaut32.lib + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 2 + 1 + -L/STACK:8388608 -gf + + + *.obj;*.cmd;*.build;*.json;*.dep + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vdc/ivdserver.idl b/vdc/ivdserver.idl new file mode 100644 index 00000000..b63d0759 --- /dev/null +++ b/vdc/ivdserver.idl @@ -0,0 +1,42 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2012 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +// bring in core IDL files +import "oaidl.idl"; + +[ + object, + uuid(002a2de9-8bb6-484d-9901-7e4ad4084715), + dual, + nonextensible, + helpstring("IVDServer Interface"), + pointer_default(unique) +] +interface IVDServer : IUnknown +{ + HRESULT ConfigureSemanticProject([in] BSTR filename, [in] BSTR imp, [in] BSTR stringImp, [in] BSTR versionids, [in] BSTR debugids, [in] DWORD flags); + HRESULT ClearSemanticProject(); + HRESULT UpdateModule([in] BSTR filename, [in] BSTR srcText, [in] DWORD flags); + HRESULT GetTip([in] BSTR filename, [in] DWORD startLine, [in] DWORD startIndex, [in] DWORD endLine, [in] DWORD endIndex, [in] DWORD flags); + HRESULT GetTipResult([out] DWORD *startLine, [out] DWORD *startIndex, [out] DWORD *endLine, [out] DWORD *endIndex, [out,retval] BSTR* answer); + HRESULT GetSemanticExpansions([in] BSTR filename, [in] BSTR tok, [in] DWORD line, [in] DWORD idx, [in] BSTR expr); + HRESULT GetSemanticExpansionsResult([out,retval] BSTR* stringList); + HRESULT IsBinaryOperator([in] BSTR filename, [in] DWORD startLine, [in] DWORD startIndex, [in] DWORD endLine, [in] DWORD endIndex, [out,retval] BOOL* pIsOp); + HRESULT GetParseErrors([in] BSTR filename, [out, retval] BSTR* errors); + HRESULT GetBinaryIsInLocations([in] BSTR filename, [out,retval] VARIANT* locs); // array of pairs of DWORD + HRESULT GetLastMessage([out,retval] BSTR* message); + HRESULT GetIdentifierTypes([in] BSTR filename, [in] DWORD startLine, [in] DWORD endLine, [in] DWORD flags); + HRESULT GetIdentifierTypesResult([out, retval] BSTR* types); + HRESULT GetDefinition([in] BSTR filename, [in] DWORD startLine, [in] DWORD startIndex, [in] DWORD endLine, [in] DWORD endIndex); + HRESULT GetDefinitionResult([out] DWORD *startLine, [out] DWORD *startIndex, [out] DWORD *endLine, [out] DWORD *endIndex, [out,retval] BSTR* filename); + HRESULT GetReferences([in] BSTR filename, [in] BSTR tok, [in] DWORD line, [in] DWORD idx, [in] BSTR expr); + HRESULT GetReferencesResult([out,retval] BSTR* stringList); + HRESULT ConfigureCommentTasks([in] BSTR tasks); + HRESULT GetCommentTasks([in] BSTR filename, [out,retval] BSTR* tasks); +}; + diff --git a/vdc/parser.visualdproj b/vdc/parser.visualdproj index fce31c07..ed5f47cb 100644 --- a/vdc/parser.visualdproj +++ b/vdc/parser.visualdproj @@ -1406,7 +1406,7 @@ 0 0 0 - 1 + 0 $(CC) -c 1 0 @@ -1985,8 +1985,8 @@ + - diff --git a/vdc/semantic.d b/vdc/semantic.d index cc5dbd5c..06f00065 100644 --- a/vdc/semantic.d +++ b/vdc/semantic.d @@ -21,6 +21,7 @@ import vdc.parser.engine; import vdc.logger; import vdc.interpret; import vdc.versions; +import vdc.semanticopt; import stdext.util; import stdext.array; @@ -833,207 +834,3 @@ class Project : Node } } } - -struct VersionInfo -{ - TextPos defined; // line -1 if not defined yet - TextPos firstUsage; // line int.max if not used yet -} - -struct VersionDebug -{ - int level; - VersionInfo[string] identifiers; - - bool reset(int lev, string[] ids) - { - if(lev == level && ids.length == identifiers.length) - { - bool different = false; - foreach(id; ids) - if(id !in identifiers) - different = true; - if(!different) - return false; - } - - level = lev; - identifiers = identifiers.init; - foreach(id; ids) - identifiers[id] = VersionInfo(); - - return true; - } - - bool preDefined(string ident) const - { - if(auto vi = ident in identifiers) - return vi.defined.line >= 0; - return false; - } - - bool defined(string ident, TextPos pos) - { - if(auto vi = ident in identifiers) - { - if(pos < vi.defined) - semanticErrorPos(pos, "identifier " ~ ident ~ " used before defined"); - - if(pos < vi.firstUsage) - vi.firstUsage = pos; - - return vi.defined.line >= 0; - } - VersionInfo vi; - vi.defined.line = -1; - vi.firstUsage = pos; - identifiers[ident] = vi; - return false; - } - - void define(string ident, TextPos pos) - { - if(auto vi = ident in identifiers) - { - if(pos > vi.firstUsage) - semanticErrorPos(pos, "identifier " ~ ident ~ " defined after usage"); - if(pos < vi.defined) - vi.defined = pos; - } - - VersionInfo vi; - vi.firstUsage.line = int.max; - vi.defined = pos; - identifiers[ident] = vi; - } -} - -class Options -{ - string[] importDirs; - string[] stringImportDirs; - - public /* debug & version handling */ { - bool unittestOn; - bool x64; - bool msvcrt; - bool debugOn; - bool coverage; - bool doDoc; - bool noBoundsCheck; - bool gdcCompiler; - bool ldcCompiler; - bool noDeprecated; - bool mixinAnalysis; - bool UFCSExpansions; - VersionDebug debugIds; - VersionDebug versionIds; - - int changeCount; - - bool setImportDirs(string[] dirs) - { - if(dirs == importDirs) - return false; - - importDirs = dirs.dup; - changeCount++; - return true; - } - bool setStringImportDirs(string[] dirs) - { - if(dirs == stringImportDirs) - return false; - - stringImportDirs = dirs.dup; - changeCount++; - return true; - } - bool setVersionIds(int level, string[] versionids) - { - if(!versionIds.reset(level, versionids)) - return false; - changeCount++; - return true; - } - bool setDebugIds(int level, string[] debugids) - { - if(!debugIds.reset(level, debugids)) - return false; - changeCount++; - return true; - } - - bool versionEnabled(string ident) - { - int pre = versionPredefined(ident); - if(pre == 0) - return versionIds.defined(ident, TextPos()); - - return pre > 0; - } - - bool versionEnabled(int level) - { - return level <= versionIds.level; - } - - bool debugEnabled(string ident) - { - return debugIds.defined(ident, TextPos()); - } - - bool debugEnabled(int level) - { - return level <= debugIds.level; - } - - int versionPredefined(string ident) - { - int* p = ident in sPredefinedVersions; - if(!p) - return 0; - if(*p) - return *p; - - switch(ident) - { - case "unittest": - return unittestOn ? 1 : -1; - case "assert": - return unittestOn || debugOn ? 1 : -1; - case "D_Coverage": - return coverage ? 1 : -1; - case "D_Ddoc": - return doDoc ? 1 : -1; - case "D_NoBoundsChecks": - return noBoundsCheck ? 1 : -1; - case "Win32": - case "X86": - case "D_InlineAsm_X86": - return x64 ? -1 : 1; - case "CRuntime_DigitalMars": - return msvcrt ? -1 : 1; - case "CRuntime_Microsoft": - return msvcrt ? 1 : -1; - case "MinGW": - return gdcCompiler || (ldcCompiler && !msvcrt) ? 1 : -1; - case "Win64": - case "X86_64": - case "D_InlineAsm_X86_64": - case "D_LP64": - return x64 ? 1 : -1; - case "GNU": - return gdcCompiler ? 1 : -1; - case "LDC": - return ldcCompiler ? 1 : -1; - case "DigitalMars": - return gdcCompiler || ldcCompiler ? -1 : 1; - default: - assert(false, "inconsistent predefined versions"); - } - } - - } -} - diff --git a/vdc/semanticopt.d b/vdc/semanticopt.d new file mode 100644 index 00000000..2e2b7937 --- /dev/null +++ b/vdc/semanticopt.d @@ -0,0 +1,238 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2010-2011 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +module vdc.semanticopt; + +version(MARS) +{ + struct TextPos + { + enum line = 0; // always defined + } +} +else +{ + import vdc.semantic; + import vdc.util; + import vdc.versions; +} + +struct VersionInfo +{ + TextPos defined; // line -1 if not defined yet + TextPos firstUsage; // line int.max if not used yet +} + +struct VersionDebug +{ + int level; + VersionInfo[string] identifiers; + + bool reset(int lev, string[] ids) + { + if(lev == level && ids.length == identifiers.length) + { + bool different = false; + foreach(id; ids) + if(id !in identifiers) + different = true; + if(!different) + return false; + } + + level = lev; + identifiers = identifiers.init; + foreach(id; ids) + identifiers[id] = VersionInfo(); + + return true; + } + + bool preDefined(string ident) const + { + if(auto vi = ident in identifiers) + return vi.defined.line >= 0; + return false; + } + + bool defined(string ident, TextPos pos) + { + version(MARS) + { + return (ident in identifiers) != null; + } + else + { + if(auto vi = ident in identifiers) + { + if(pos < vi.defined) + semanticErrorPos(pos, "identifier " ~ ident ~ " used before defined"); + + if(pos < vi.firstUsage) + vi.firstUsage = pos; + + return vi.defined.line >= 0; + } + VersionInfo vi; + vi.defined.line = -1; + vi.firstUsage = pos; + identifiers[ident] = vi; + return false; + } + } + + version(MARS) {} else + void define(string ident, TextPos pos) + { + if(auto vi = ident in identifiers) + { + if(pos > vi.firstUsage) + semanticErrorPos(pos, "identifier " ~ ident ~ " defined after usage"); + if(pos < vi.defined) + vi.defined = pos; + } + + VersionInfo vi; + vi.firstUsage.line = int.max; + vi.defined = pos; + identifiers[ident] = vi; + } +} + +class Options +{ + string[] importDirs; + string[] stringImportDirs; + + public /* debug & version handling */ { + bool unittestOn; + bool x64; + bool msvcrt; + bool debugOn; + bool coverage; + bool doDoc; + bool noBoundsCheck; + bool gdcCompiler; + bool ldcCompiler; + bool noDeprecated; + bool mixinAnalysis; + bool UFCSExpansions; + VersionDebug debugIds; + VersionDebug versionIds; + + int changeCount; + + bool setImportDirs(string[] dirs) + { + if(dirs == importDirs) + return false; + + importDirs = dirs.dup; + changeCount++; + return true; + } + bool setStringImportDirs(string[] dirs) + { + if(dirs == stringImportDirs) + return false; + + stringImportDirs = dirs.dup; + changeCount++; + return true; + } + bool setVersionIds(int level, string[] versionids) + { + if(!versionIds.reset(level, versionids)) + return false; + changeCount++; + return true; + } + bool setDebugIds(int level, string[] debugids) + { + if(!debugIds.reset(level, debugids)) + return false; + changeCount++; + return true; + } + + bool versionEnabled(string ident) + { + int pre = versionPredefined(ident); + if(pre == 0) + return versionIds.defined(ident, TextPos()); + + return pre > 0; + } + + bool versionEnabled(int level) + { + return level <= versionIds.level; + } + + bool debugEnabled(string ident) + { + return debugIds.defined(ident, TextPos()); + } + + bool debugEnabled(int level) + { + return level <= debugIds.level; + } + + int versionPredefined(string ident) + { + version(MARS) {} else + { + int* p = ident in sPredefinedVersions; + if(!p) + return 0; + if(*p) + return *p; + } + + switch(ident) + { + case "unittest": + return unittestOn ? 1 : -1; + case "assert": + return unittestOn || debugOn ? 1 : -1; + case "D_Coverage": + return coverage ? 1 : -1; + case "D_Ddoc": + return doDoc ? 1 : -1; + case "D_NoBoundsChecks": + return noBoundsCheck ? 1 : -1; + case "Win32": + case "X86": + case "D_InlineAsm_X86": + return x64 ? -1 : 1; + case "CRuntime_DigitalMars": + return msvcrt ? -1 : 1; + case "CRuntime_Microsoft": + return msvcrt ? 1 : -1; + case "MinGW": + return gdcCompiler || (ldcCompiler && !msvcrt) ? 1 : -1; + case "Win64": + case "X86_64": + case "D_InlineAsm_X86_64": + case "D_LP64": + return x64 ? 1 : -1; + case "GNU": + return gdcCompiler ? 1 : -1; + case "LDC": + return ldcCompiler ? 1 : -1; + case "DigitalMars": + return gdcCompiler || ldcCompiler ? -1 : 1; + default: + assert(false, "inconsistent predefined versions"); + } + } + + } +} + diff --git a/vdc/vdserver.d b/vdc/vdserver.d index b5c9ab54..cbacdf5f 100644 --- a/vdc/vdserver.d +++ b/vdc/vdserver.d @@ -208,7 +208,7 @@ class VDServer : ComObject, IVDServer int changed = (oldflags != (flags & 0xff0000ff)); changed += opts.setImportDirs(splitLines(imports)); - changed += opts.setImportDirs(splitLines(imports)); + changed += opts.setStringImportDirs(splitLines(strImports)); changed += opts.setVersionIds(versionlevel, splitLines(verids)); changed += opts.setDebugIds(debuglevel, splitLines(dbgids)); } diff --git a/vdc/vdserver.idl b/vdc/vdserver.idl index ce29f3a9..95c7b313 100644 --- a/vdc/vdserver.idl +++ b/vdc/vdserver.idl @@ -8,38 +8,9 @@ // bring in core IDL files import "oaidl.idl"; +import "ivdserver.idl"; -[ - object, - uuid(002a2de9-8bb6-484d-9901-7e4ad4084715), - dual, - nonextensible, - helpstring("IVDServer Interface"), - pointer_default(unique) -] -interface IVDServer : IUnknown -{ - HRESULT ConfigureSemanticProject([in] BSTR filename, [in] BSTR imp, [in] BSTR stringImp, [in] BSTR versionids, [in] BSTR debugids, [in] DWORD flags); - HRESULT ClearSemanticProject(); - HRESULT UpdateModule([in] BSTR filename, [in] BSTR srcText, [in] DWORD flags); - HRESULT GetTip([in] BSTR filename, [in] DWORD startLine, [in] DWORD startIndex, [in] DWORD endLine, [in] DWORD endIndex, [in] DWORD flags); - HRESULT GetTipResult([out] DWORD *startLine, [out] DWORD *startIndex, [out] DWORD *endLine, [out] DWORD *endIndex, [out,retval] BSTR* answer); - HRESULT GetSemanticExpansions([in] BSTR filename, [in] BSTR tok, [in] DWORD line, [in] DWORD idx, [in] BSTR expr); - HRESULT GetSemanticExpansionsResult([out,retval] BSTR* stringList); - HRESULT IsBinaryOperator([in] BSTR filename, [in] DWORD startLine, [in] DWORD startIndex, [in] DWORD endLine, [in] DWORD endIndex, [out,retval] BOOL* pIsOp); - HRESULT GetParseErrors([in] BSTR filename, [out, retval] BSTR* errors); - HRESULT GetBinaryIsInLocations([in] BSTR filename, [out,retval] VARIANT* locs); // array of pairs of DWORD - HRESULT GetLastMessage([out,retval] BSTR* message); - HRESULT GetIdentifierTypes([in] BSTR filename, [in] DWORD startLine, [in] DWORD endLine, [in] DWORD flags); - HRESULT GetIdentifierTypesResult([out, retval] BSTR* types); - HRESULT GetDefinition([in] BSTR filename, [in] DWORD startLine, [in] DWORD startIndex, [in] DWORD endLine, [in] DWORD endIndex); - HRESULT GetDefinitionResult([out] DWORD *startLine, [out] DWORD *startIndex, [out] DWORD *endLine, [out] DWORD *endIndex, [out,retval] BSTR* filename); HRESULT GetReferences([in] BSTR filename, [in] BSTR tok, [in] DWORD line, [in] DWORD idx, [in] BSTR expr, [in] BOOL moduleOnly); - HRESULT GetReferencesResult([out,retval] BSTR* stringList); - HRESULT ConfigureCommentTasks([in] BSTR tasks); - HRESULT GetCommentTasks([in] BSTR filename, [out,retval] BSTR* tasks); -}; - // library statement [uuid(002a2de9-8bb6-484d-9903-7e4ad4084715), version(1.0), helpstring("Visual D Semantic Server")] diff --git a/vdc/vdserver.visualdproj b/vdc/vdserver.visualdproj index 1a06dbeb..ccee8e7f 100644 --- a/vdc/vdserver.visualdproj +++ b/vdc/vdserver.visualdproj @@ -1012,11 +1012,11 @@ 0 0 0 - 1 + 0 $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. ..\bin\$(ConfigurationName) @@ -1499,6 +1499,7 @@ *.obj;*.cmd;*.build;*.json;*.dep + Date: Mon, 30 Apr 2018 13:12:53 +0200 Subject: [PATCH 04/73] improve building with new Win10 SDK, better find UCRTVersion --- build/dte_idl.bat | 2 +- visuald/dpackage.d | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build/dte_idl.bat b/build/dte_idl.bat index 528ebc35..e131ce46 100644 --- a/build/dte_idl.bat +++ b/build/dte_idl.bat @@ -24,7 +24,7 @@ if "%IVIEWER%" == "" if exist "%WindowsSdkVerBinPath%\x86\iviewers.dll" set IVIE if "%IVIEWER%" == "" if exist "%WindowsSdkDir%\bin\x86\iviewers.dll" set IVIEWER=%WindowsSdkDir%\bin\x86\iviewers.dll if "%IVIEWER%" == "" if exist "%WindowsSdkDir%\bin\iviewers.dll" set IVIEWER=%WindowsSdkDir%\bin\iviewers.dll if "%IVIEWER%" == "" if exist "%WindowsSdkDir%\bin\%WindowsSdkVersion%\x86\iviewers.dll" set IVIEWER=%WindowsSdkDir%\bin\%WindowsSdkVersion%\x86\iviewers.dll -if "%IVIEWER%" == "" (echo "iviewer.dll" not found && exit /B 1) +if "%IVIEWER%" == "" (echo "iviewer.dll" not found with WindowsSdkDir="%WindowsSdkDir%", WindowsSdkVersion=%WindowsSdkVersion% && exit /B 1) echo "%TLB2IDL%" "%MSENV%\dte80.olb" "%DTE_IDL_PATH%\dte80.idl" "%IVIEWER%" diff --git a/visuald/dpackage.d b/visuald/dpackage.d index 9e18d152..0a3af556 100644 --- a/visuald/dpackage.d +++ b/visuald/dpackage.d @@ -378,7 +378,7 @@ class Package : DisposingComObject, scope(exit) release(taskList); taskList.UnregisterTaskProvider(mTaskProviderCookie); mTaskProvider = null; - mTaskProviderCookie = 0; + mTaskProviderCookie = 0; } } @@ -533,7 +533,7 @@ version(none) mTaskProvider = newCom!TaskProvider; if (taskList.RegisterTaskProvider (mTaskProvider, &mTaskProviderCookie) != S_OK) mTaskProvider = null; - else + else taskList.RefreshTasks(mTaskProviderCookie); } @@ -1327,7 +1327,7 @@ version(none) if (auto taskList = queryService!(IVsTaskList)) { taskList.RefreshTasks(s_instance.mTaskProviderCookie); - release(taskList); + release(taskList); } } @@ -1811,8 +1811,8 @@ class GlobalOptions scope RegKey keyDMD = new RegKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\DMD", false); string dir = toUTF8(keyDMD.GetString("InstallationFolder")); if(!dir.empty) - DMD.InstallDir = dir ~ "\\dmd2"; - } + DMD.InstallDir = dir ~ "\\dmd2"; + } } void detectLDCInstallDir() @@ -2469,16 +2469,16 @@ class GlobalOptions auto arr = cast(ArraySetting)sw; foreach(a; arr.vals()) { - string opts = replace(a, "%%ldcbinarypath%%", bindir); + string opts = replace(a, "%%ldcbinarypath%%", bindir); imports ~= getOptionImportPaths(opts, bindir); } - } - } + } + } } - } + } } catch(Exception) - { + { } } return imports; @@ -2500,7 +2500,7 @@ class GlobalOptions } string[] args = tokenizeArgs(searchpaths); foreach(arg; args) - imports ~= removeDotDotPath(normalizeDir(unquoteArgument(arg))); + imports ~= removeDotDotPath(normalizeDir(unquoteArgument(arg))); return imports; } From 5faf402f41c2ef3b7eb8de771b467db251d2b367 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 30 Apr 2018 13:13:46 +0200 Subject: [PATCH 05/73] update to dmd master --- vdc/ddmderrors.d | 67 +++++++++- vdc/ddmdlib.d | 6 +- vdc/ddmdmars.d | 6 +- vdc/ddmdrmem.d | 76 +++++------ vdc/dmdserver.d | 98 ++++++++------- vdc/dmdserver.visualdproj | 259 ++++++++++++++++++++------------------ 6 files changed, 292 insertions(+), 220 deletions(-) diff --git a/vdc/ddmderrors.d b/vdc/ddmderrors.d index 109d454b..9a4eb0f8 100644 --- a/vdc/ddmderrors.d +++ b/vdc/ddmderrors.d @@ -8,7 +8,7 @@ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/ddmd/errors.d, _errors.d) */ -module ddmd.errors; +module dmd.errors; // Online documentation: https://dlang.org/phobos/ddmd_errors.html @@ -16,10 +16,10 @@ import core.stdc.stdarg; import core.stdc.stdio; import core.stdc.stdlib; import core.stdc.string; -import ddmd.globals; -import ddmd.root.outbuffer; -import ddmd.root.rmem; -import ddmd.console; +import dmd.globals; +import dmd.root.outbuffer; +import dmd.root.rmem; +import dmd.console; /********************** * Color highlighting to classify messages @@ -114,7 +114,7 @@ extern (C++) void verror(const ref Loc loc, const(char)* format, va_list ap, con if (!global.gag) { verrorPrint(loc, Classification.error, header, format, ap, p1, p2); - if (global.errorLimit && global.errors >= global.errorLimit) + if (global.params.errorLimit && global.errors >= global.params.errorLimit) fatal(); // moderate blizzard of cascading messages } else @@ -195,3 +195,58 @@ extern (C++) void halt() throw new Exception("halt"); } +/** +* Print a verbose message. +* Doesn't prefix or highlight messages. +* Params: +* loc = location of message +* format = printf-style format specification +* ... = printf-style variadic arguments +*/ +extern (C++) void message(const ref Loc loc, const(char)* format, ...) +{ + va_list ap; + va_start(ap, format); + vmessage(loc, format, ap); + va_end(ap); +} + +/** +* Same as above, but doesn't take a location argument. +* Params: +* format = printf-style format specification +* ... = printf-style variadic arguments +*/ +extern (C++) void message(const(char)* format, ...) +{ + va_list ap; + va_start(ap, format); + vmessage(Loc.initial, format, ap); + va_end(ap); +} + +/** +* Same as $(D message), but takes a va_list parameter. +* Params: +* loc = location of message +* format = printf-style format specification +* ap = printf-style variadic arguments +*/ +extern (C++) void vmessage(const ref Loc loc, const(char)* format, va_list ap) +{ + version(none) + { + const p = loc.toChars(); + if (*p) + { + fprintf(stdout, "%s: ", p); + mem.xfree(cast(void*)p); + } + OutBuffer tmp; + tmp.vprintf(format, ap); + fputs(tmp.peekString(), stdout); + fputc('\n', stdout); + fflush(stdout); // ensure it gets written out in case of compiler aborts + } +} + diff --git a/vdc/ddmdlib.d b/vdc/ddmdlib.d index 41025b0b..98ced22b 100644 --- a/vdc/ddmdlib.d +++ b/vdc/ddmdlib.d @@ -1,5 +1,5 @@ -module ddmd.lib; +module dmd.lib; -class Library -{ +class Library +{ } diff --git a/vdc/ddmdmars.d b/vdc/ddmdmars.d index 2077b105..1728ceeb 100644 --- a/vdc/ddmdmars.d +++ b/vdc/ddmdmars.d @@ -1,7 +1,7 @@ -module ddmd.mars; -import ddmd.dscope; -import ddmd.root.rmem; +module dmd.mars; +import dmd.dscope; +import dmd.root.rmem; extern (C++) void genCmain(Scope* sc) { diff --git a/vdc/ddmdrmem.d b/vdc/ddmdrmem.d index eed56279..e34f96e6 100644 --- a/vdc/ddmdrmem.d +++ b/vdc/ddmdrmem.d @@ -1,46 +1,46 @@ -module ddmd.root.rmem; - -import core.memory : GC; -import core.stdc.string : strlen; - -extern (C++) struct Mem -{ - static char* xstrdup(const(char)* p) nothrow - { - return p[0 .. strlen(p) + 1].dup.ptr; - } - - static void xfree(void* p) nothrow - { - return GC.free(p); - } - - static void* xmalloc(size_t n) nothrow - { +module dmd.root.rmem; + +import core.memory : GC; +import core.stdc.string : strlen; + +extern (C++) struct Mem +{ + static char* xstrdup(const(char)* p) nothrow + { + return p[0 .. strlen(p) + 1].dup.ptr; + } + + static void xfree(void* p) nothrow + { + return GC.free(p); + } + + static void* xmalloc(size_t n) nothrow + { if (cancel) throw cancelError; - return GC.malloc(n); - } - - static void* xcalloc(size_t size, size_t n) nothrow - { - return GC.calloc(size * n); - } - - static void* xrealloc(void* p, size_t size) nothrow - { - return GC.realloc(p, size); - } - static void error() nothrow + return GC.malloc(n); + } + + static void* xcalloc(size_t size, size_t n) nothrow + { + return GC.calloc(size * n); + } + + static void* xrealloc(void* p, size_t size) nothrow + { + return GC.realloc(p, size); + } + static void error() nothrow { __gshared static oom = new Error("out of memory"); - throw oom; + throw oom; } __gshared cancelError = new Error("cancel malloc"); - __gshared bool cancel; -} - -extern (C++) const __gshared Mem mem; + __gshared bool cancel; +} + +extern (C++) const __gshared Mem mem; + - diff --git a/vdc/dmdserver.d b/vdc/dmdserver.d index 0c387041..7dd08124 100644 --- a/vdc/dmdserver.d +++ b/vdc/dmdserver.d @@ -14,39 +14,41 @@ version(noServer): import vdc.ivdserver; import vdc.semanticopt; -import ddmd.apply; -import ddmd.arraytypes; -import ddmd.builtin; -import ddmd.cond; -import ddmd.console; -import ddmd.dclass; -import ddmd.declaration; -import ddmd.dimport; -import ddmd.dinterpret; -import ddmd.dmodule; -import ddmd.dscope; -import ddmd.dstruct; -import ddmd.dsymbol; -import ddmd.dtemplate; -import ddmd.expression; -import ddmd.func; -import ddmd.globals; -import ddmd.hdrgen; -import ddmd.id; -import ddmd.identifier; -import ddmd.init; -import ddmd.mtype; -import ddmd.objc; -import ddmd.semantic; -import ddmd.sapply; -import ddmd.statement; -import ddmd.target; -import ddmd.tokens; -import ddmd.visitor; - -import ddmd.root.outbuffer; -import ddmd.root.rmem; -import ddmd.root.rootobject; +import dmd.apply; +import dmd.arraytypes; +import dmd.builtin; +import dmd.cond; +import dmd.console; +import dmd.dclass; +import dmd.declaration; +import dmd.dimport; +import dmd.dinterpret; +import dmd.dmodule; +import dmd.dscope; +import dmd.dstruct; +import dmd.dsymbol; +import dmd.dsymbolsem; +import dmd.dtemplate; +import dmd.expression; +import dmd.func; +import dmd.globals; +import dmd.hdrgen; +import dmd.id; +import dmd.identifier; +import dmd.init; +import dmd.mtype; +import dmd.objc; +import dmd.sapply; +import dmd.semantic2; +import dmd.semantic3; +import dmd.statement; +import dmd.target; +import dmd.tokens; +import dmd.visitor; + +import dmd.root.outbuffer; +import dmd.root.rmem; +import dmd.root.rootobject; //import vdc.util; struct TextPos @@ -154,7 +156,7 @@ class DMDServer : ComObject, IVDServer { global._init(); global.params.isWindows = true; - global.errorLimit = 0; + global.params.errorLimit = 0; } } @@ -668,21 +670,21 @@ class DMDServer : ComObject, IVDServer { global.params.color = false; global.params.link = true; - global.params.useAssert = mOptions.debugOn; + global.params.useAssert = mOptions.debugOn ? CHECKENABLE.on : CHECKENABLE.off; global.params.useInvariants = mOptions.debugOn; global.params.useIn = mOptions.debugOn; global.params.useOut = mOptions.debugOn; - global.params.useArrayBounds = mOptions.noBoundsCheck ? BOUNDSCHECKon : BOUNDSCHECKoff; // set correct value later + global.params.useArrayBounds = mOptions.noBoundsCheck ? CHECKENABLE.on : CHECKENABLE.off; // set correct value later global.params.doDocComments = mOptions.doDoc; - global.params.useSwitchError = true; + global.params.useSwitchError = CHECKENABLE.on; global.params.useInline = false; global.params.obj = false; global.params.useDeprecated = mOptions.noDeprecated ? 0 : 2; - global.params.linkswitches = new Strings(); - global.params.libfiles = new Strings(); - global.params.dllfiles = new Strings(); - global.params.objfiles = new Strings(); - global.params.ddocfiles = new Strings(); + global.params.linkswitches = Strings(); + global.params.libfiles = Strings(); + global.params.dllfiles = Strings(); + global.params.objfiles = Strings(); + global.params.ddocfiles = Strings(); // Default to -m32 for 32 bit dmd, -m64 for 64 bit dmd global.params.is64bit = mOptions.x64; global.params.mscoff = mOptions.msvcrt; @@ -727,7 +729,7 @@ class DMDServer : ComObject, IVDServer VersionCondition.addPredefinedGlobalIdent("unittest"); if (global.params.useAssert) VersionCondition.addPredefinedGlobalIdent("assert"); - if (global.params.useArrayBounds == BOUNDSCHECKoff) + if (global.params.useArrayBounds == CHECKENABLE.off) VersionCondition.addPredefinedGlobalIdent("D_NoBoundsChecks"); if (global.params.betterC) VersionCondition.addPredefinedGlobalIdent("D_betterC"); @@ -805,7 +807,7 @@ class DMDServer : ComObject, IVDServer for (size_t i = 0; i < modules.length; i++) { Module m = modules[i]; - m.semantic(null); + m.dsymbolSemantic(null); } Module.dprogress = 1; @@ -1477,8 +1479,8 @@ extern(C++) class FindTipVisitor : FindASTVisitor { switch(e.op) { - case TOKvar: - case TOKsymoff: + case TOK.variable: + case TOK.symbolOffset: tip = tipForDeclaration((cast(SymbolExp)e).var); break; default: @@ -1556,8 +1558,8 @@ extern(C++) class FindDefinitionVisitor : FindASTVisitor { switch(e.op) { - case TOKvar: - case TOKsymoff: + case TOK.variable: + case TOK.symbolOffset: loc = (cast(SymbolExp)e).var.loc; break; default: diff --git a/vdc/dmdserver.visualdproj b/vdc/dmdserver.visualdproj index 1293bcc8..20fcccb5 100644 --- a/vdc/dmdserver.visualdproj +++ b/vdc/dmdserver.visualdproj @@ -264,12 +264,12 @@ 0 0 0 - $(CC) -nologo -c -TP -Isrc -Isrc\backend -Isrc\tk -Isrc\root -Isrc\vcbuild -DTARGET_WINDOS=1 -FIvcbuild\warnings.h + $(CC) -nologo -c -TP -Idmd\src -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\vcbuild -DTARGET_WINDOS=1 -FIwarnings.h 1 - 0 + 1 c:\l\d\dmd2\windows\bin\dmd.exe - $(OutDir) ..\..\res + dmd dmd\res ..\bin\$(ConfigurationName) $(OutDir)\$(PlatfromName)\$(ProjectName) @@ -287,7 +287,7 @@ 0 0 - MARS + MARS NoBackend 0 0 0 @@ -478,7 +478,7 @@ 0 0 0 - $(CC) -c -nologo -c -TP -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + $(CC) -c -nologo -c -TP -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 1 0 c:\l\d\dmd2\windows\bin\dmd.exe @@ -585,7 +585,7 @@ 0 0 0 - $(CC) -c -nologo -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + $(CC) -c -nologo -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 1 0 c:\l\d\dmd2\windows\bin\dmd.exe @@ -692,7 +692,7 @@ 0 0 0 - $(CC) -c -nologo -c -TP -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + $(CC) -c -nologo -c -TP -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 1 0 c:\l\d\dmd2\windows\bin\dmd.exe @@ -799,7 +799,7 @@ 0 2 0 - $(CC) -c -nologo -c -TP -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + $(CC) -c -nologo -c -TP -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 1 0 c:\l\d\dmd2\windows\bin\dmd.exe @@ -906,7 +906,7 @@ 0 0 0 - $(CC) -c -nologo -c -TP -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + $(CC) -c -nologo -c -TP -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 1 0 c:\l\d\dmd2\windows\bin\dmd.exe @@ -1013,7 +1013,7 @@ 0 0 0 - $(CC) -c -nologo -Idmd\src\ddmd -Idmd\src\ddmd\backend -Idmd\src\ddmd\tk -Idmd\src\ddmd\root -Idmd\src\ddmd\vcbuild -DTARGET_WINDOS=1 + $(CC) -c -nologo -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 1 0 c:\l\d\dmd2\windows\bin\dmd.exe @@ -1073,12 +1073,12 @@ - - - - - - + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1210,11 +1221,15 @@ ml64 -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(Input +set midl=midl +if exist "%WindowsSdkDir%\bin\%WindowsSDKVersion%x86\midl.exe" set midl="%WindowsSdkDir%\bin\%WindowsSDKVersion%x86\midl.exe" +%midl% /D _DEBUG /nologo /char signed /env win32 /Oicf /tlb ".\$(InputName).tlb" /out "$(IntDir)" /error stub_data $(InputPath)" tool="Custom" outfile="$(IntDir)/dmdserver.tlb" /> +set rc=rc +if exist "%WindowsSdkDir%\bin\%WindowsSDKVersion%x86\rc.exe" set rc="%WindowsSdkDir%\bin\%WindowsSDKVersion%x86\rc.exe" +%rc% /fo"$(OutDir)\$(InputName).res" /I"$(IntDir)" $(InputPath)" tool="Custom" dependencies=""$(IntDir)\dmdserver.tlb" ..\version" linkoutput="true" outfile="$(OutDir)\dmdserver.res" /> From a99b94cd4ae0e212b91c041ca1dc23514b565ab9 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 30 Apr 2018 16:56:47 +0200 Subject: [PATCH 06/73] basic fix dmdserver --- vdc/dmdserver.d | 133 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 90 insertions(+), 43 deletions(-) diff --git a/vdc/dmdserver.d b/vdc/dmdserver.d index 7dd08124..28224be4 100644 --- a/vdc/dmdserver.d +++ b/vdc/dmdserver.d @@ -415,6 +415,7 @@ class DMDServer : ComObject, IVDServer catch(Throwable t) { version(DebugServer) dbglog("GetTip: exception " ~ t.msg); + txt = "exception: " ~ t.msg; } } mLastTip = txt; @@ -666,6 +667,30 @@ class DMDServer : ComObject, IVDServer { clearDmdStatics(); + // Initialization + Token._init(); + Type._init(); + Id.initialize(); + Module._init(); + Target._init(); + Expression._init(); + Objc._init(); + builtin_init(); + Module.rootModule = null; + global.gag = false; + global.gaggedErrors = 0; + global.errors = 0; + global.warnings = 0; + + version(traceGC) + { + wipeStack(); + GC.collect(); + dumpGC(); + } + else + GC.collect(); + synchronized(gOptSync) { global.params.color = false; @@ -695,6 +720,13 @@ class DMDServer : ComObject, IVDServer foreach(id, v; mOptions.versionIds.identifiers) global.params.versionids.push(toStringz(id)); + global.versionids = new Identifiers(); + + // Add in command line versions + if (global.params.versionids) + foreach (charz; *global.params.versionids) + VersionCondition.addGlobalIdent(charz[0 .. strlen(charz)]); + VersionCondition.addPredefinedGlobalIdent("DigitalMars"); VersionCondition.addPredefinedGlobalIdent("Windows"); VersionCondition.addPredefinedGlobalIdent("LittleEndian"); @@ -713,7 +745,7 @@ class DMDServer : ComObject, IVDServer VersionCondition.addPredefinedGlobalIdent("X86"); VersionCondition.addPredefinedGlobalIdent("Win32"); } - if (global.params.mscoff) + if (global.params.mscoff || global.params.is64bit) VersionCondition.addPredefinedGlobalIdent("CRuntime_Microsoft"); else VersionCondition.addPredefinedGlobalIdent("CRuntime_DigitalMars"); @@ -742,6 +774,11 @@ class DMDServer : ComObject, IVDServer foreach(id, v; mOptions.debugIds.identifiers) global.params.debugids.push(toStringz(id)); + global.debugids = new Identifiers(); + if (global.params.debugids) + foreach (charz; *global.params.debugids) + DebugCondition.addGlobalIdent(charz[0 .. strlen(charz)]); + global.path = new Strings(); foreach(i; mOptions.importDirs) global.path.push(toStringz(i)); @@ -751,30 +788,6 @@ class DMDServer : ComObject, IVDServer global.filePath.push(toStringz(i)); } - // Initialization - Token._init(); - Type._init(); - Id.initialize(); - Module._init(); - Target._init(); - Expression._init(); - Objc._init(); - builtin_init(); - Module.rootModule = null; - global.gag = false; - global.gaggedErrors = 0; - global.errors = 0; - global.warnings = 0; - - version(traceGC) - { - wipeStack(); - GC.collect(); - dumpGC(); - } - else - GC.collect(); - // redo module name with the new Identifier.stringtable foreach (m; modules) { @@ -964,24 +977,47 @@ int _stricmp(const(wchar)*str1, wstring s2) } //////////////////////////////////////////////////////////////// -enum string[2][] dmdStatics = -[ - ["D4ddmd5clone12buildXtoHashRC4ddmd7dstruct17StructDeclarationPS4ddmd6dscope5ScopeZ8tftohashC4ddmd5mtype12TypeFunction", "TypeFunction"], - ["D4ddmd7dstruct15search_toStringRC4ddmd7dstruct17StructDeclarationZ10tftostringC4ddmd5mtype12TypeFunction", "TypeFunction"], - ["D4ddmd10expression11loadStdMathRZ10impStdMathC4ddmd7dimport6Import", "Import"], - ["D4ddmd4func15FuncDeclaration8genCfuncRPS4ddmd4root5array33__T5ArrayTC4ddmd5mtype9ParameterZ5ArrayC4ddmd5mtype4TypeC4ddmd10identifier10IdentifiermZ2stC4ddmd7dsymbol12DsymbolTable", "DsymbolTable"], - ["D4ddmd5mtype10TypeAArray6dotExpMRPS4ddmd6dscope5ScopeC4ddmd10expression10ExpressionC4ddmd10identifier10IdentifieriZ8fd_aaLenC4ddmd4func15FuncDeclaration", "FuncDeclaration"], - ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ3feqC4ddmd4func15FuncDeclaration", "FuncDeclaration"], - ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ4fcmpC4ddmd4func15FuncDeclaration", "FuncDeclaration"], - ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ5fhashC4ddmd4func15FuncDeclaration", "FuncDeclaration"], - - ["D4ddmd7dmodule6Module19runDeferredSemanticRZ6nestedi", "int"], - ["D4ddmd10dsymbolsem22DsymbolSemanticVisitor5visitMRC4ddmd9dtemplate13TemplateMixinZ4nesti", "int"], - ["D4ddmd9dtemplate16TemplateInstance16tryExpandMembersMRPS4ddmd6dscope5ScopeZ4nesti", "int"], - ["D4ddmd9dtemplate16TemplateInstance12trySemantic3MRPS4ddmd6dscope5ScopeZ4nesti", "int"], - ["D4ddmd13expressionsem25ExpressionSemanticVisitor5visitMRC4ddmd10expression7CallExpZ4nesti", "int"], - ["D4ddmd5mtype4Type8noMemberMRPS4ddmd6dscope5ScopeC4ddmd10expression10ExpressionC4ddmd10identifier10IdentifieriZ4nesti", "int"], -]; +version(all) // new mangling with dmd version >= 2.077 +{ + enum string[2][] dmdStatics = + [ + ["_D3dmd5clone12buildXtoHashRCQBa7dstruct17StructDeclarationPSQCg6dscope5ScopeZ8tftohashCQDh5mtype12TypeFunction", "TypeFunction"], + ["_D3dmd7dstruct15search_toStringRCQBfQBe17StructDeclarationZ10tftostringCQCs5mtype12TypeFunction", "TypeFunction"], + ["_D3dmd13expressionsem11loadStdMathFZ10impStdMathCQBv7dimport6Import", "Import"], + ["_D3dmd4func15FuncDeclaration8genCfuncRPSQBm4root5array__T5ArrayTCQCl5mtype9ParameterZQBcCQDjQy4TypeCQDu10identifier10IdentifiermZ2stCQFb7dsymbol12DsymbolTable", "DsymbolTable"], + ["_D3dmd7typesem13DotExpVisitor5visitMRCQBk5mtype10TypeAArrayZ8fd_aaLenCQCq4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem19TypeSemanticVisitor5visitMRCQBq5mtype10TypeAArrayZ3feqCQCr4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem19TypeSemanticVisitor5visitMRCQBq5mtype10TypeAArrayZ4fcmpCQCs4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem19TypeSemanticVisitor5visitMRCQBq5mtype10TypeAArrayZ5fhashCQCt4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7dmodule6Module19runDeferredSemanticRZ6nestedi", "int"], + ["_D3dmd10dsymbolsem22DsymbolSemanticVisitor5visitMRCQBx9dtemplate13TemplateMixinZ4nesti", "int"], + ["_D3dmd9dtemplate16TemplateInstance16tryExpandMembersMRPSQCc6dscope5ScopeZ4nesti", "int"], + ["_D3dmd9dtemplate16TemplateInstance12trySemantic3MRPSQBy6dscope5ScopeZ4nesti", "int"], + ["_D3dmd13expressionsem25ExpressionSemanticVisitor5visitMRCQCd10expression7CallExpZ4nesti", "int"], + ["_D3dmd7typesem13DotExpVisitor8noMemberMRCQBn5mtype4TypePSQCd6dscope5ScopeCQCu10expression10ExpressionCQDw10identifier10IdentifieriZ4nesti", "int"], + ]; +} +else +{ + enum string[2][] dmdStatics = + [ + ["D4ddmd5clone12buildXtoHashRC4ddmd7dstruct17StructDeclarationPS4ddmd6dscope5ScopeZ8tftohashC4ddmd5mtype12TypeFunction", "TypeFunction"], + ["D4ddmd7dstruct15search_toStringRC4ddmd7dstruct17StructDeclarationZ10tftostringC4ddmd5mtype12TypeFunction", "TypeFunction"], + ["D4ddmd10expression11loadStdMathRZ10impStdMathC4ddmd7dimport6Import", "Import"], + ["D4ddmd4func15FuncDeclaration8genCfuncRPS4ddmd4root5array33__T5ArrayTC4ddmd5mtype9ParameterZ5ArrayC4ddmd5mtype4TypeC4ddmd10identifier10IdentifiermZ2stC4ddmd7dsymbol12DsymbolTable", "DsymbolTable"], + ["D4ddmd5mtype10TypeAArray6dotExpMRPS4ddmd6dscope5ScopeC4ddmd10expression10ExpressionC4ddmd10identifier10IdentifieriZ8fd_aaLenC4ddmd4func15FuncDeclaration", "FuncDeclaration"], + ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ3feqC4ddmd4func15FuncDeclaration", "FuncDeclaration"], + ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ4fcmpC4ddmd4func15FuncDeclaration", "FuncDeclaration"], + ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ5fhashC4ddmd4func15FuncDeclaration", "FuncDeclaration"], + + ["D4ddmd7dmodule6Module19runDeferredSemanticRZ6nestedi", "int"], + ["D4ddmd10dsymbolsem22DsymbolSemanticVisitor5visitMRC4ddmd9dtemplate13TemplateMixinZ4nesti", "int"], + ["D4ddmd9dtemplate16TemplateInstance16tryExpandMembersMRPS4ddmd6dscope5ScopeZ4nesti", "int"], + ["D4ddmd9dtemplate16TemplateInstance12trySemantic3MRPS4ddmd6dscope5ScopeZ4nesti", "int"], + ["D4ddmd13expressionsem25ExpressionSemanticVisitor5visitMRC4ddmd10expression7CallExpZ4nesti", "int"], + ["D4ddmd5mtype4Type8noMemberMRPS4ddmd6dscope5ScopeC4ddmd10expression10ExpressionC4ddmd10identifier10IdentifieriZ4nesti", "int"], + ]; +} string cmangled(string s) { @@ -1010,6 +1046,11 @@ mixin(genDeclDmdStatics); void clearDmdStatics() { + /* + import core.demangle; + static foreach(s; dmdStatics) + pragma(msg, demangle(s[0])); + */ mixin(genInitDmdStatics); Module.rootModule = null; @@ -1352,6 +1393,12 @@ extern(C++) class FindASTVisitor : ASTVisitor foundNode(sym); } + override void visit(Parameter sym) + { + //if (!found && matchIdentifier(sym.loc, sym.ident)) + // foundNode(sym); + } + override void visit(ScopeDsymbol scopesym) { // optimize to only visit members in approriate source range From ba0255e61364f53cf41807c58d683bfc05156126 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 30 Apr 2018 22:07:55 +0200 Subject: [PATCH 07/73] handle newexp allow switching to dmdserver in registry --- vdc/dmdserver.d | 24 ++++++++++++++++++++++++ visuald/dpackage.d | 25 +++++++++++++------------ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/vdc/dmdserver.d b/vdc/dmdserver.d index 28224be4..126151ef 100644 --- a/vdc/dmdserver.d +++ b/vdc/dmdserver.d @@ -1387,6 +1387,15 @@ extern(C++) class FindASTVisitor : ASTVisitor return false; } + bool matchLoc(ref Loc loc) + { + if (loc.filename is filename) + if (loc.linnum == startLine && loc.linnum == endLine) + if (loc.charnum <= startIndex /*&& loc.charnum + ident.toString().length >= endIndex*/) + return true; + return false; + } + override void visit(Dsymbol sym) { if (!found && matchIdentifier(sym.loc, sym.ident)) @@ -1464,6 +1473,21 @@ extern(C++) class FindASTVisitor : ASTVisitor if (matchIdentifier(expr.loc, expr.var.ident)) foundNode(expr); } + override void visit(NewExp ne) + { + if (!found && matchLoc(ne.loc)) + if (ne.member) + foundNode(ne.member); + else + foundNode(ne.type); + } + + override void visit(DotIdExp de) + { + if (!found && de.ident) + if (matchIdentifier(de.identloc, de.ident)) + foundNode(de); + } } extern(C++) class FindTipVisitor : FindASTVisitor diff --git a/visuald/dpackage.d b/visuald/dpackage.d index 0a3af556..302cfcb9 100644 --- a/visuald/dpackage.d +++ b/visuald/dpackage.d @@ -378,7 +378,7 @@ class Package : DisposingComObject, scope(exit) release(taskList); taskList.UnregisterTaskProvider(mTaskProviderCookie); mTaskProvider = null; - mTaskProviderCookie = 0; + mTaskProviderCookie = 0; } } @@ -533,7 +533,7 @@ version(none) mTaskProvider = newCom!TaskProvider; if (taskList.RegisterTaskProvider (mTaskProvider, &mTaskProviderCookie) != S_OK) mTaskProvider = null; - else + else taskList.RefreshTasks(mTaskProviderCookie); } @@ -1327,7 +1327,7 @@ version(none) if (auto taskList = queryService!(IVsTaskList)) { taskList.RefreshTasks(s_instance.mTaskProviderCookie); - release(taskList); + release(taskList); } } @@ -1811,8 +1811,8 @@ class GlobalOptions scope RegKey keyDMD = new RegKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\DMD", false); string dir = toUTF8(keyDMD.GetString("InstallationFolder")); if(!dir.empty) - DMD.InstallDir = dir ~ "\\dmd2"; - } + DMD.InstallDir = dir ~ "\\dmd2"; + } } void detectLDCInstallDir() @@ -1926,7 +1926,8 @@ class GlobalOptions fmtIndentCase = getBoolOpt("fmtIndentCase", true); scope RegKey keyDParser = new RegKey(HKEY_CLASSES_ROOT, "CLSID\\{002a2de9-8bb6-484d-AA05-7e4ad4084715}", false); - useDParser = true; // getBoolOpt("useDParser2", keyDParser.key !is null); + version(all) useDParser = getBoolOpt("useDParser2", keyDParser.key !is null); + else useDParser = true; mixinAnalysis = getBoolOpt("mixinAnalysis", false); UFCSExpansions = getBoolOpt("UFCSExpansions", true); sortExpMode = getBoolOpt("sortExpMode", 0); @@ -2469,16 +2470,16 @@ class GlobalOptions auto arr = cast(ArraySetting)sw; foreach(a; arr.vals()) { - string opts = replace(a, "%%ldcbinarypath%%", bindir); + string opts = replace(a, "%%ldcbinarypath%%", bindir); imports ~= getOptionImportPaths(opts, bindir); } - } - } + } + } } - } + } } catch(Exception) - { + { } } return imports; @@ -2500,7 +2501,7 @@ class GlobalOptions } string[] args = tokenizeArgs(searchpaths); foreach(arg; args) - imports ~= removeDotDotPath(normalizeDir(unquoteArgument(arg))); + imports ~= removeDotDotPath(normalizeDir(unquoteArgument(arg))); return imports; } From 7cfe73de2f9d6ad89e0a0230c37ee8c80924a1b7 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 8 Dec 2018 17:52:05 +0100 Subject: [PATCH 08/73] fix rebase --- tools/tracegc.d | 10 ++--- vdc/ddmdrmem.d | 39 ++++++++++++++++ vdc/dmdserver.d | 84 ++++++++++++++++++++-------------- vdc/dmdserver.visualdproj | 95 +++++++++++++++++++++++---------------- 4 files changed, 150 insertions(+), 78 deletions(-) diff --git a/tools/tracegc.d b/tools/tracegc.d index 0f22db9b..80e83edb 100644 --- a/tools/tracegc.d +++ b/tools/tracegc.d @@ -143,7 +143,7 @@ struct StackAddrInfo uint line; } -__gshared StackAddrInfo addrInfo[1 << 16]; +__gshared StackAddrInfo[1 << 16] addrInfo; __gshared size_t addrInfoPos; StackAddrInfo* findOrAddAddr(size_t pc) nothrow @@ -608,7 +608,7 @@ extern(C) void dumpGC() void dumpAddr(AddrTracePair[] traceMap, void* addr, size_t size) { - char buf[256]; + char[256] buf; const(char)* filename; int line; @@ -664,7 +664,7 @@ void addAddrInfoStat(StackAddrInfo* ai, size_t size) void dumpAddrInfoStat() { - char buf[256]; + char[256] buf; OutputDebugStringA("Dump combined by stack location:\n"); @@ -864,7 +864,7 @@ void dumpGC(GC _gc) cgc.gcLock.lock(); - char buf[256]; + char[256] buf; sprintf(buf.ptr, "Dump of GC %p: %d pools\n", _gc, gcx.npools); OutputDebugStringA(buf.ptr); sprintf(buf.ptr, "Trace buffer memory: %lld bytes\n", cast(long)tracer.traceBuffer.memUsage()); @@ -1049,7 +1049,7 @@ void findRoot(void* sobj) const(void*) minAddr = cgc.gcx.pooltable.minAddr; const(void*) maxAddr = cgc.gcx.pooltable.maxAddr; - char buf[256]; + char[256] buf; nextLoc: for ( ; ; ) { diff --git a/vdc/ddmdrmem.d b/vdc/ddmdrmem.d index e34f96e6..711301e1 100644 --- a/vdc/ddmdrmem.d +++ b/vdc/ddmdrmem.d @@ -43,4 +43,43 @@ extern (C++) struct Mem extern (C++) const __gshared Mem mem; +/** +Makes a null-terminated copy of the given string on newly allocated memory. +The null-terminator won't be part of the returned string slice. It will be +at position `n` where `n` is the length of the input string. +Params: + s = string to copy + +Returns: A null-terminated copy of the input array. +*/ +extern (D) char[] xarraydup(const(char)[] s) nothrow +{ + if (!s) + return null; + + auto p = cast(char*)mem.xmalloc(s.length + 1); + char[] a = p[0 .. s.length]; + a[] = s[0 .. s.length]; + p[s.length] = 0; // preserve 0 terminator semantics + return a; +} + +/** +Makes a copy of the given array on newly allocated memory. + +Params: + s = array to copy + +Returns: A copy of the input array. +*/ +extern (D) T[] arraydup(T)(const scope T[] s) nothrow +{ + if (!s) + return null; + + const dim = s.length; + auto p = (cast(T*)mem.xmalloc(T.sizeof * dim))[0 .. dim]; + p[] = s; + return p; +} diff --git a/vdc/dmdserver.d b/vdc/dmdserver.d index 126151ef..bcc584c4 100644 --- a/vdc/dmdserver.d +++ b/vdc/dmdserver.d @@ -285,7 +285,7 @@ class DMDServer : ComObject, IVDServer return S_OK; } - override HRESULT UpdateModule(in BSTR filename, in BSTR srcText, in BOOL verbose) + override HRESULT UpdateModule(in BSTR filename, in BSTR srcText, in DWORD flags) { string fname = to_string(filename); size_t len = wcslen(srcText); @@ -354,7 +354,7 @@ class DMDServer : ComObject, IVDServer *pErr = errors; } - if(verbose) + if(flags & 1) writeReadyMessage(); } version(DebugServer) dbglog(" scheduleParse: " ~ firstLine(text)); @@ -386,7 +386,7 @@ class DMDServer : ComObject, IVDServer return S_FALSE; } - override HRESULT GetTip(in BSTR filename, int startLine, int startIndex, int endLine, int endIndex) + override HRESULT GetTip(in BSTR filename, int startLine, int startIndex, int endLine, int endIndex, int flags) { string fname = to_string(filename); @@ -634,6 +634,16 @@ class DMDServer : ComObject, IVDServer return E_NOTIMPL; } + HRESULT GetIdentifierTypes(in BSTR filename, int startLine, int endLine, int flags) + { + return E_NOTIMPL; + } + + HRESULT GetIdentifierTypesResult(BSTR* types) + { + 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) @@ -696,15 +706,15 @@ class DMDServer : ComObject, IVDServer global.params.color = false; global.params.link = true; global.params.useAssert = mOptions.debugOn ? CHECKENABLE.on : CHECKENABLE.off; - global.params.useInvariants = mOptions.debugOn; - global.params.useIn = mOptions.debugOn; - global.params.useOut = mOptions.debugOn; + global.params.useInvariants = mOptions.debugOn ? CHECKENABLE.on : CHECKENABLE.off; + global.params.useIn = mOptions.debugOn ? CHECKENABLE.on : CHECKENABLE.off; + global.params.useOut = mOptions.debugOn ? CHECKENABLE.on : CHECKENABLE.off; global.params.useArrayBounds = mOptions.noBoundsCheck ? CHECKENABLE.on : CHECKENABLE.off; // set correct value later global.params.doDocComments = mOptions.doDoc; global.params.useSwitchError = CHECKENABLE.on; global.params.useInline = false; global.params.obj = false; - global.params.useDeprecated = mOptions.noDeprecated ? 0 : 2; + global.params.useDeprecated = mOptions.noDeprecated ? Diagnostic.error : Diagnostic.off; global.params.linkswitches = Strings(); global.params.libfiles = Strings(); global.params.dllfiles = Strings(); @@ -791,8 +801,8 @@ class DMDServer : ComObject, IVDServer // redo module name with the new Identifier.stringtable foreach (m; modules) { - auto fname = to!string(m.srcfile.name.str); - string name = stripExtension(baseName(fname)); + auto fname = m.srcfile.name.toString(); + auto name = stripExtension(baseName(fname)); m.ident = Identifier.idPool(name); } @@ -875,7 +885,7 @@ private: { size_t pos = mModules.length; foreach (i, m; mModules) - if (_stricmp(m.srcfile.name.str, fname) == 0) + if (_stricmp(m.srcfile.name.toChars(), fname) == 0) { if (createNew) { @@ -938,7 +948,7 @@ void verrorPrint(const ref Loc loc, Color headerColor, const(char)* header, if (_stricmp(loc.filename, gErrorFile) != 0) return; - __gshared char buf[4096]; + __gshared char[4096] buf; int len = snprintf(buf.ptr, buf.length, "%d,%d,%d,%d:", loc.linnum, loc.charnum - 1, loc.linnum, loc.charnum); if (p1 && len < buf.length) len += snprintf(buf.ptr + len, buf.length - len, "%s ", p1); @@ -981,20 +991,21 @@ version(all) // new mangling with dmd version >= 2.077 { enum string[2][] dmdStatics = [ - ["_D3dmd5clone12buildXtoHashRCQBa7dstruct17StructDeclarationPSQCg6dscope5ScopeZ8tftohashCQDh5mtype12TypeFunction", "TypeFunction"], - ["_D3dmd7dstruct15search_toStringRCQBfQBe17StructDeclarationZ10tftostringCQCs5mtype12TypeFunction", "TypeFunction"], - ["_D3dmd13expressionsem11loadStdMathFZ10impStdMathCQBv7dimport6Import", "Import"], - ["_D3dmd4func15FuncDeclaration8genCfuncRPSQBm4root5array__T5ArrayTCQCl5mtype9ParameterZQBcCQDjQy4TypeCQDu10identifier10IdentifiermZ2stCQFb7dsymbol12DsymbolTable", "DsymbolTable"], - ["_D3dmd7typesem13DotExpVisitor5visitMRCQBk5mtype10TypeAArrayZ8fd_aaLenCQCq4func15FuncDeclaration", "FuncDeclaration"], - ["_D3dmd7typesem19TypeSemanticVisitor5visitMRCQBq5mtype10TypeAArrayZ3feqCQCr4func15FuncDeclaration", "FuncDeclaration"], - ["_D3dmd7typesem19TypeSemanticVisitor5visitMRCQBq5mtype10TypeAArrayZ4fcmpCQCs4func15FuncDeclaration", "FuncDeclaration"], - ["_D3dmd7typesem19TypeSemanticVisitor5visitMRCQBq5mtype10TypeAArrayZ5fhashCQCt4func15FuncDeclaration", "FuncDeclaration"], - ["_D3dmd7dmodule6Module19runDeferredSemanticRZ6nestedi", "int"], - ["_D3dmd10dsymbolsem22DsymbolSemanticVisitor5visitMRCQBx9dtemplate13TemplateMixinZ4nesti", "int"], - ["_D3dmd9dtemplate16TemplateInstance16tryExpandMembersMRPSQCc6dscope5ScopeZ4nesti", "int"], - ["_D3dmd9dtemplate16TemplateInstance12trySemantic3MRPSQBy6dscope5ScopeZ4nesti", "int"], - ["_D3dmd13expressionsem25ExpressionSemanticVisitor5visitMRCQCd10expression7CallExpZ4nesti", "int"], - ["_D3dmd7typesem13DotExpVisitor8noMemberMRCQBn5mtype4TypePSQCd6dscope5ScopeCQCu10expression10ExpressionCQDw10identifier10IdentifieriZ4nesti", "int"], + ["_D3dmd5clone12buildXtoHashFCQBa7dstruct17StructDeclarationPSQCg6dscope5ScopeZ8tftohashCQDh5mtype12TypeFunction", "TypeFunction"], + ["_D3dmd7dstruct15search_toStringRCQBfQBe17StructDeclarationZ10tftostringCQCs5mtype12TypeFunction", "TypeFunction"], + ["_D3dmd13expressionsem11loadStdMathFZ10impStdMathCQBv7dimport6Import", "Import"], + ["_D3dmd4func15FuncDeclaration8genCfuncRPSQBm4root5array__T5ArrayTCQCl5mtype9ParameterZQBcCQDjQy4TypeCQDu10identifier10IdentifiermZ2stCQFb7dsymbol12DsymbolTable", "DsymbolTable"], + ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ11visitAArrayMFCQEwQEc10TypeAArrayZ8fd_aaLenCQFz4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ3feqCQEn4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ4fcmpCQEo4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ5fhashCQEp4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBufferkPkAxaZ4nesti", "int"], // x86 + ["_D3dmd7dmodule6Module19runDeferredSemanticRZ6nestedi", "int"], + ["_D3dmd10dsymbolsem22DsymbolSemanticVisitor5visitMRCQBx9dtemplate13TemplateMixinZ4nesti", "int"], + ["_D3dmd9dtemplate16TemplateInstance16tryExpandMembersMFPSQCc6dscope5ScopeZ4nesti", "int"], + ["_D3dmd9dtemplate16TemplateInstance12trySemantic3MFPSQBy6dscope5ScopeZ4nesti", "int"], + ["_D3dmd13expressionsem25ExpressionSemanticVisitor5visitMRCQCd10expression7CallExpZ4nesti", "int"], + ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ8noMemberMFQDxQDmQCxQByiZ4nesti", "int"], ]; } else @@ -1021,10 +1032,10 @@ else string cmangled(string s) { - version(Win64) - return "_" ~ s; - else - return s; + version (Win64) + if (s == "_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBufferkPkAxaZ4nesti") + return "_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBuffermPmAxaZ4nesti"; + return s; } string genDeclDmdStatics() { @@ -1095,7 +1106,9 @@ void clearDmdStatics() // static __gshared FuncDeclaration* fdapply = [null, null]; // static __gshared TypeDelegate* fldeTy = [null, null]; - ctfeStack = ctfeStack.init; + // dmd.dinterpret + // ctfeStack = ctfeStack.init; + Scope.freelist = null; //Token.freelist = null; @@ -1194,7 +1207,10 @@ extern(C++) class ASTVisitor : StoppableVisitor override void visit(CompileStatement stmt) { - visitExpression(stmt.exp); + if (stmt.exps) + foreach(e; *stmt.exps) + if (!stop) + e.accept(this); if (!stop) visit(cast(Statement)stmt); } @@ -1590,13 +1606,13 @@ RootObject _findAST(Dsymbol sym, const(char*) filename, int startLine, int start RootObject findAST(Module mod, int startLine, int startIndex, int endLine, int endIndex) { - auto filename = mod.srcfile.name.str; + auto filename = mod.srcfile.name.toChars(); return _findAST(mod, filename, startLine, startIndex, endLine, endIndex); } string findTip(Module mod, int startLine, int startIndex, int endLine, int endIndex) { - auto filename = mod.srcfile.name.str; + auto filename = mod.srcfile.name.toChars(); scope FindTipVisitor ftv = new FindTipVisitor(filename, startLine, startIndex, endLine, endIndex); mod.accept(ftv); @@ -1650,7 +1666,7 @@ extern(C++) class FindDefinitionVisitor : FindASTVisitor string findDefinition(Module mod, ref int line, ref int index) { - auto filename = mod.srcfile.name.str; + auto filename = mod.srcfile.name.toChars(); scope FindDefinitionVisitor fdv = new FindDefinitionVisitor(filename, line, index, line, index + 1); mod.accept(fdv); diff --git a/vdc/dmdserver.visualdproj b/vdc/dmdserver.visualdproj index 20fcccb5..4f8e49cb 100644 --- a/vdc/dmdserver.visualdproj +++ b/vdc/dmdserver.visualdproj @@ -1,6 +1,6 @@ {34289BD7-AB7E-4264-B146-8139DDE9F0BF} - + 0 0 0 @@ -15,6 +15,7 @@ 0 0 1 + 1 0 0 0 @@ -107,7 +108,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -122,6 +123,7 @@ 0 0 0 + 1 1 0 0 @@ -214,7 +216,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -229,6 +231,7 @@ 0 0 1 + 1 0 0 1 @@ -321,7 +324,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -336,6 +339,7 @@ 0 0 2 + 1 1 0 1 @@ -428,7 +432,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -443,6 +447,7 @@ 0 0 1 + 1 0 0 0 @@ -535,7 +540,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -550,6 +555,7 @@ 0 0 1 + 1 0 0 1 @@ -591,7 +597,7 @@ c:\l\d\dmd2\windows\bin\dmd.exe dmd\src .. $(DMDInstallDir)\src\druntime\src dmd dmd\res - ..\bin\$(ConfigurationName)\$(PlatfromName)\$(ProjectName) + ..\bin\$(ConfigurationName)\$(PlatformName)\$(ProjectName) $(OutDir) @@ -610,7 +616,7 @@ 0 MARS NoBackend GC 0 - 0 + 1 0 0 @@ -642,7 +648,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -657,6 +663,7 @@ 0 0 1 + 1 0 0 0 @@ -749,7 +756,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -764,6 +771,7 @@ 0 0 1 + 1 0 0 1 @@ -856,7 +864,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -871,6 +879,7 @@ 0 0 1 + 1 0 0 0 @@ -963,7 +972,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -978,6 +987,7 @@ 0 0 1 + 1 1 0 1 @@ -1079,27 +1089,11 @@ - - - - - - - - + - + @@ -1107,10 +1101,7 @@ ml64 -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(Input - - - - + @@ -1119,12 +1110,15 @@ ml64 -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(Input + + + @@ -1146,6 +1140,7 @@ ml64 -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(Input + @@ -1153,15 +1148,22 @@ ml64 -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(Input + + + + + + + @@ -1171,17 +1173,22 @@ ml64 -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(Input + + + + + @@ -1190,21 +1197,31 @@ ml64 -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(Input + + + - + + + + + + + + @@ -1218,18 +1235,18 @@ ml64 -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(Input - - + +%rc% /fo"$(OutDir)\$(InputName).res" /I"$(IntDir)" $(InputPath)" dependencies=""$(IntDir)\dmdserver.tlb" ..\version" outfile="$(OutDir)\dmdserver.res" path="dmdserver.rc" linkoutput="true" tool="Custom" /> From fa8558920c22211e31525bb6dd69d5f89d2adb19 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 9 Dec 2018 11:53:50 +0100 Subject: [PATCH 09/73] move dmdserver into subfolder --- vdc/{ => dmdserver}/ddmderrors.d | 0 vdc/{ => dmdserver}/ddmdlib.d | 0 vdc/{ => dmdserver}/ddmdmars.d | 0 vdc/{ => dmdserver}/ddmdrmem.d | 0 vdc/{ => dmdserver}/dmdicon.ico | Bin vdc/{ => dmdserver}/dmdserver.d | 18 +++--- vdc/{ => dmdserver}/dmdserver.idl | 2 +- vdc/{ => dmdserver}/dmdserver.rc | 2 +- vdc/{ => dmdserver}/dmdserver.visualdproj | 70 +++++++++++----------- 9 files changed, 46 insertions(+), 46 deletions(-) rename vdc/{ => dmdserver}/ddmderrors.d (100%) rename vdc/{ => dmdserver}/ddmdlib.d (100%) rename vdc/{ => dmdserver}/ddmdmars.d (100%) rename vdc/{ => dmdserver}/ddmdrmem.d (100%) rename vdc/{ => dmdserver}/dmdicon.ico (100%) rename vdc/{ => dmdserver}/dmdserver.d (96%) rename vdc/{ => dmdserver}/dmdserver.idl (92%) rename vdc/{ => dmdserver}/dmdserver.rc (96%) rename vdc/{ => dmdserver}/dmdserver.visualdproj (95%) diff --git a/vdc/ddmderrors.d b/vdc/dmdserver/ddmderrors.d similarity index 100% rename from vdc/ddmderrors.d rename to vdc/dmdserver/ddmderrors.d diff --git a/vdc/ddmdlib.d b/vdc/dmdserver/ddmdlib.d similarity index 100% rename from vdc/ddmdlib.d rename to vdc/dmdserver/ddmdlib.d diff --git a/vdc/ddmdmars.d b/vdc/dmdserver/ddmdmars.d similarity index 100% rename from vdc/ddmdmars.d rename to vdc/dmdserver/ddmdmars.d diff --git a/vdc/ddmdrmem.d b/vdc/dmdserver/ddmdrmem.d similarity index 100% rename from vdc/ddmdrmem.d rename to vdc/dmdserver/ddmdrmem.d diff --git a/vdc/dmdicon.ico b/vdc/dmdserver/dmdicon.ico similarity index 100% rename from vdc/dmdicon.ico rename to vdc/dmdserver/dmdicon.ico diff --git a/vdc/dmdserver.d b/vdc/dmdserver/dmdserver.d similarity index 96% rename from vdc/dmdserver.d rename to vdc/dmdserver/dmdserver.d index bcc584c4..d26d6b3a 100644 --- a/vdc/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -732,10 +732,10 @@ class DMDServer : ComObject, IVDServer global.versionids = new Identifiers(); - // Add in command line versions - if (global.params.versionids) - foreach (charz; *global.params.versionids) - VersionCondition.addGlobalIdent(charz[0 .. strlen(charz)]); + // Add in command line versions + if (global.params.versionids) + foreach (charz; *global.params.versionids) + VersionCondition.addGlobalIdent(charz[0 .. strlen(charz)]); VersionCondition.addPredefinedGlobalIdent("DigitalMars"); VersionCondition.addPredefinedGlobalIdent("Windows"); @@ -785,9 +785,9 @@ class DMDServer : ComObject, IVDServer global.params.debugids.push(toStringz(id)); global.debugids = new Identifiers(); - if (global.params.debugids) - foreach (charz; *global.params.debugids) - DebugCondition.addGlobalIdent(charz[0 .. strlen(charz)]); + if (global.params.debugids) + foreach (charz; *global.params.debugids) + DebugCondition.addGlobalIdent(charz[0 .. strlen(charz)]); global.path = new Strings(); foreach(i; mOptions.importDirs) @@ -1497,13 +1497,13 @@ extern(C++) class FindASTVisitor : ASTVisitor else foundNode(ne.type); } - + override void visit(DotIdExp de) { if (!found && de.ident) if (matchIdentifier(de.identloc, de.ident)) foundNode(de); - } + } } extern(C++) class FindTipVisitor : FindASTVisitor diff --git a/vdc/dmdserver.idl b/vdc/dmdserver/dmdserver.idl similarity index 92% rename from vdc/dmdserver.idl rename to vdc/dmdserver/dmdserver.idl index a59d2120..da5b50f3 100644 --- a/vdc/dmdserver.idl +++ b/vdc/dmdserver/dmdserver.idl @@ -8,7 +8,7 @@ // bring in core IDL files import "oaidl.idl"; -import "ivdserver.idl"; +import "../ivdserver.idl"; // library statement [uuid(002a2de9-8bb6-484d-9907-7e4ad4084715), version(1.0), diff --git a/vdc/dmdserver.rc b/vdc/dmdserver/dmdserver.rc similarity index 96% rename from vdc/dmdserver.rc rename to vdc/dmdserver/dmdserver.rc index ab756cf7..8f978b4f 100644 --- a/vdc/dmdserver.rc +++ b/vdc/dmdserver/dmdserver.rc @@ -18,7 +18,7 @@ #define __str(x) #x #define _str(x) __str(x) -#include "../version" +#include "../../version" #if VERSION_BUILD > 0 #define VERSION_POSTFIX _str(VERSION_BETA) _str(VERSION_BUILD) diff --git a/vdc/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj similarity index 95% rename from vdc/dmdserver.visualdproj rename to vdc/dmdserver/dmdserver.visualdproj index 4f8e49cb..29139c63 100644 --- a/vdc/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -55,10 +55,10 @@ 1 0 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src + dmd\src ..\.. dmd dmd\res - ..\bin\$(ConfigurationName) - $(OutDir)\$(PlatfromName)\$(ProjectName) + ..\..\bin\$(ConfigurationName) + $(OutDir)\$(PlatformName)\$(ProjectName) 0 @@ -163,10 +163,10 @@ 1 0 $(DMDInstallDir)windows\bin\dmd.exe - + dmd\src ..\.. $(OutDir) ..\..\res - ..\bin\$(ConfigurationName) - $(OutDir)\$(PlatfromName)\$(ProjectName) + ..\..\bin\$(ConfigurationName) + $(OutDir)\$(PlatformName)\$(ProjectName) 0 @@ -271,10 +271,10 @@ 1 1 c:\l\d\dmd2\windows\bin\dmd.exe - + dmd\src ..\.. dmd dmd\res - ..\bin\$(ConfigurationName) - $(OutDir)\$(PlatfromName)\$(ProjectName) + ..\..\bin\$(ConfigurationName)\$(PlatformName) + $(OutDir)\$(ProjectName) 0 @@ -379,10 +379,10 @@ 1 0 $(DMDInstallDir)windows\bin\dmd.exe - + dmd\src ..\.. $(OutDir) ..\..\res - ..\bin\$(ConfigurationName) - $(OutDir)\$(PlatfromName)\$(ProjectName) + ..\..\bin\$(ConfigurationName)\$(PlatformName) + $(OutDir)\$(ProjectName) 0 @@ -487,10 +487,10 @@ 1 0 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src .. + dmd\src ..\.. dmd dmd\res - ..\bin\$(ConfigurationName) - $(OutDir)\$(PlatfromName)\$(ProjectName) + ..\..\bin\$(ConfigurationName) + $(OutDir)\$(PlatformName)\$(ProjectName) 0 @@ -595,10 +595,10 @@ 1 0 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src .. $(DMDInstallDir)\src\druntime\src + dmd\src ..\.. dmd dmd\res - ..\bin\$(ConfigurationName)\$(PlatformName)\$(ProjectName) - $(OutDir) + ..\..\bin\$(ConfigurationName)\$(PlatformName) + $(OutDir)\$(ProjectName) 0 @@ -703,10 +703,10 @@ 1 0 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src .. + dmd\src ..\.. dmd dmd\res - ..\bin\$(ConfigurationName) - $(OutDir)\$(PlatfromName)\$(ProjectName) + ..\..\bin\$(ConfigurationName) + $(OutDir)\$(PlatformName)\$(ProjectName) 0 @@ -811,10 +811,10 @@ 1 0 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src .. + dmd\src ..\.. dmd dmd\res - ..\bin\$(ConfigurationName) - $(OutDir)\$(PlatfromName)\$(ProjectName) + ..\..\bin\$(ConfigurationName)\$(PlatformName) + $(OutDir)\$(ProjectName) 0 @@ -919,10 +919,10 @@ 1 0 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src .. + dmd\src ..\.. dmd dmd\res - ..\bin\$(ConfigurationName) - $(OutDir)\$(PlatfromName)\$(ProjectName) + ..\..\bin\$(ConfigurationName) + $(OutDir)\$(PlatformName)\$(ProjectName) 0 @@ -1027,10 +1027,10 @@ 1 0 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src .. $(DMDInstallDir)\src\druntime\src + dmd\src ..\.. dmd dmd\res - ..\bin\$(ConfigurationName)\$(PlatfromName)\$(ProjectName) - $(OutDir) + ..\..\bin\$(ConfigurationName)\$(PlatformName) + $(OutDir)\$(ProjectName) 0 @@ -1246,10 +1246,10 @@ if exist "$(VCINSTALLDIR)\Auxiliary\Build\vcvars32.bat" ( pushd . & if errorlevel 1 goto reportError set rc=rc if exist "%WindowsSdkDir%\bin\%WindowsSDKVersion%x86\rc.exe" set rc="%WindowsSdkDir%\bin\%WindowsSDKVersion%x86\rc.exe" -%rc% /fo"$(OutDir)\$(InputName).res" /I"$(IntDir)" $(InputPath)" dependencies=""$(IntDir)\dmdserver.tlb" ..\version" outfile="$(OutDir)\dmdserver.res" path="dmdserver.rc" linkoutput="true" tool="Custom" /> - - - - +%rc% /fo"$(OutDir)\$(InputName).res" /I"$(IntDir)" $(InputPath)" dependencies=""$(IntDir)\dmdserver.tlb" ..\..\version" outfile="$(OutDir)\dmdserver.res" path="dmdserver.rc" linkoutput="true" tool="Custom" /> + + + + From 439b3a557297657d7c823aaf0013fd65286ec099 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Wed, 26 Dec 2018 11:22:24 +0100 Subject: [PATCH 10/73] handle out-of-memory more graciously, fix test build --- vdc/dmdserver/dmdserver.d | 65 +++++--- vdc/dmdserver/dmdserver.visualdproj | 224 +++++++++++++++++++++++++++- 2 files changed, 267 insertions(+), 22 deletions(-) diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index d26d6b3a..4ea8c411 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -82,10 +82,12 @@ import std.array; import std.concurrency; import std.datetime; +import core.exception; import core.memory; import core.thread; import core.time; import core.stdc.stdio; +import core.stdc.stdlib; import core.stdc.string; //version = traceGC; @@ -209,6 +211,10 @@ class DMDServer : ComObject, IVDServer } ); } + catch(OutOfMemoryError e) + { + exit(7); // terminate + } catch(Throwable e) { version(DebugCmd) dbglog ("taskLoop exception: " ~ e.msg); @@ -341,12 +347,16 @@ class DMDServer : ComObject, IVDServer { initErrorFile(fname); parseModules([mod]); - errors = gErrorMessages; + } + catch(OutOfMemoryError e) + { + throw e; // terminate } catch(Throwable t) { version(DebugServer) dbglog("UpdateModule.doParse: exception " ~ t.msg); } + errors = gErrorMessages; } synchronized(gErrorSync) { @@ -412,6 +422,10 @@ class DMDServer : ComObject, IVDServer { txt = findTip(m, startLine, startIndex + 1, endLine, endIndex + 1); } + catch(OutOfMemoryError e) + { + throw e; // terminate + } catch(Throwable t) { version(DebugServer) dbglog("GetTip: exception " ~ t.msg); @@ -472,6 +486,10 @@ class DMDServer : ComObject, IVDServer { deffilename = findDefinition(m, mDefSpan.start.line, mDefSpan.start.index); } + catch(OutOfMemoryError e) + { + throw e; // terminate + } catch(Throwable t) { version(DebugServer) dbglog("GetDefinition: exception " ~ t.msg); @@ -523,6 +541,10 @@ class DMDServer : ComObject, IVDServer { mLastSymbols = null; //_GetSemanticExpansions(src, stok, line, idx, sexpr); } + catch(OutOfMemoryError e) + { + throw e; // terminate + } catch(Throwable t) { version(DebugServer) dbglog("GetSemanticExpansions.calcExpansions: exception " ~ t.msg); @@ -944,7 +966,6 @@ void verrorPrint(const ref Loc loc, Color headerColor, const(char)* header, synchronized(gErrorSync) { - version(x) if (_stricmp(loc.filename, gErrorFile) != 0) return; @@ -1540,7 +1561,10 @@ extern(C++) class FindTipVisitor : FindASTVisitor if (auto func = decl.isFuncDeclaration()) { OutBuffer buf; - functionToBufferWithIdent(decl.type.toTypeFunction(), &buf, decl.toPrettyChars()); + if (decl.type) + functionToBufferWithIdent(decl.type.toTypeFunction(), &buf, decl.toPrettyChars()); + else + buf.writestring(decl.toPrettyChars()); auto res = buf.peekSlice(); buf.extractString(); // take ownership return cast(string)res; @@ -1684,15 +1708,16 @@ extern(C) void dumpGC(); unittest { //_CrtDumpMemoryLeaks(); - dumpGC(); + version(traceGC) + dumpGC(); DMDServer srv = newCom!DMDServer; addref(srv); scope(exit) release(srv); auto filename = allocBSTR("source.d"); - auto imp = allocBSTR(r"c:\l\D\dmd2.076\dmd2\src\druntime\import" ~ "\n" ~ - r"c:\l\D\dmd2.076\dmd2\src\phobos"); + auto imp = allocBSTR(r"c:\s\d\rainers\druntime\import" ~ "\n" ~ + r"c:\s\d\rainers\phobos"); auto empty = allocBSTR(""); uint flags = ConfigureFlags!()(false, //bool unittestOn false, //bool debugOn, @@ -1729,7 +1754,7 @@ unittest void checkTip(int line, int col, string expected_tip) { - HRESULT hr = srv.GetTip(filename, line, col, line, col + 1); + HRESULT hr = srv.GetTip(filename, line, col, line, col + 1, 0); assert(hr == S_OK); BSTR bstrTip; int startLine, startIndex, endLine, endIndex; @@ -1781,14 +1806,20 @@ unittest }; checkErrors(source, "4,10,4,11:undefined identifier `abcd`\n"); +/ - wipeStack(); + version(traceGC) + wipeStack(); GC.collect(); //_CrtDumpMemoryLeaks(); - dumpGC(); + version(traceGC) + dumpGC(); for (int i = 0; i < 2; i++) { + srv.mModules = null; + srv.mErrors = null; + clearDmdStatics (); + source = q{ import std.stdio; int main(string[] args) @@ -1800,24 +1831,22 @@ unittest }; checkErrors(source, ""); - srv.mModules = null; - srv.mErrors = null; - clearDmdStatics (); - - wipeStack(); + version(traceGC) + wipeStack(); GC.collect(); //_CrtDumpMemoryLeaks(); - dumpGC(); + version(traceGC) + dumpGC(); } - checkTip(5, 9, "(local variable) int xyz"); checkTip(6, 9, "void std.stdio.writeln!(int, int, int).writeln(int _param_0, int _param_1, int _param_2) @safe"); checkTip(7, 12, "(local variable) int xyz"); - wipeStack(); + version(traceGC) + wipeStack(); GC.collect(); - checkDefinition(7, 12, "source.d", 5, 8); // xyz + checkDefinition(7, 12, "source.d", 5, 9); // xyz } diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index 29139c63..fdbefdb6 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -880,7 +880,7 @@ 0 1 1 - 0 + 1 0 0 0 @@ -899,7 +899,7 @@ 0 0 0 - 0 + 1 0 0 0 @@ -1080,6 +1080,222 @@ *.obj;*.cmd;*.build;*.json;*.dep + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + c:\l\dmc\bin\dmc -c -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DMARS -e -wx -DTARGET_WINDOS=1 -DDM_TARGET_CPU_X86=1 + 1 + 0 + c:\l\d\dmd2\windows\bin\dmd.exe + dmd\src ..\.. + dmd dmd\res + ..\..\bin\$(ConfigurationName) + $(OutDir)\$(PlatformName)\$(ProjectName) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS NoBackend + 0 + 0 + 0 + 0 + + + + 0 + + 2 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + -s. + + + ole32.lib oleaut32.lib + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 2 + 1 + -L/STACK:8388608 + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -nologo -c -TP -Idmd\src -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\vcbuild -DTARGET_WINDOS=1 -FIwarnings.h + 1 + 1 + c:\l\d\dmd2\windows\bin\dmd.exe + dmd\src ..\.. + dmd dmd\res + ..\..\bin\$(ConfigurationName)\$(PlatformName) + $(OutDir)\$(ProjectName) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + MARS NoBackend + 0 + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + + + + + $(OutDir)\$(ProjectName).exe + $(IntDir)\$(SafeProjectName).pdb + $(IntDir)\$(SafeProjectName).lib + $(IntDir)\$(SafeProjectName).map + 1 + 2 + 0 + -L/STACK:8388608 + + + *.obj;*.cmd;*.build;*.json;*.dep + @@ -1093,7 +1309,7 @@ - + @@ -1101,7 +1317,7 @@ - + From 78ce1a85da34f7ffcd895a815134bbc90e493b83 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Wed, 26 Dec 2018 11:31:26 +0100 Subject: [PATCH 11/73] moved dmdserver, fixed unittest init, better restart of vdserverclient --- tools/pipedmd.d | 3 ++- vdc/vdserverfactory.d | 6 ++---- visuald/propertypage.d | 2 +- visuald/vdserverclient.d | 8 +++++--- visuald_vs10.sln | 14 +++++++------- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/tools/pipedmd.d b/tools/pipedmd.d index 43d4cea1..adb57cd3 100644 --- a/tools/pipedmd.d +++ b/tools/pipedmd.d @@ -155,11 +155,12 @@ int main(string[] argv) string fullexe = findExeInPath(exe); bool isX64 = isExe64bit(fullexe); if (verbose) + { if (fullexe.empty) printf ("%.*s not found in PATH, assuming %d-bit application\n", exe.length, exe.ptr, isX64 ? 64 : 32); else printf ("%.*s is a %d-bit application\n", fullexe.length, fullexe.ptr, isX64 ? 64 : 32); - + } string trackerArgs; string tracker = findTracker(isX64, trackerArgs); if (tracker.length > 0) diff --git a/vdc/vdserverfactory.d b/vdc/vdserverfactory.d index cb4ef1e3..a74f969a 100644 --- a/vdc/vdserverfactory.d +++ b/vdc/vdserverfactory.d @@ -156,9 +156,7 @@ static if(version_minor < 64) } else { - extern (C) int rt_init(); - extern (C) int rt_term(); - extern (C) bool runModuleUnitTests(); + import core.runtime; enum EXIT_SUCCESS = 0; enum EXIT_FAILURE = -1; @@ -171,7 +169,7 @@ else if (rt_init()) { version(unittest) - result = runModuleUnitTests() ? 0 : EXIT_FAILURE; + result = runModuleUnitTests().passed ? EXIT_SUCCESS : EXIT_FAILURE; else result = vdserver_main(); } diff --git a/visuald/propertypage.d b/visuald/propertypage.d index 34cd87da..6237b2c7 100644 --- a/visuald/propertypage.d +++ b/visuald/propertypage.d @@ -37,7 +37,7 @@ import std.path; import std.process : environment; import std.string; -// version = DParserOption; +debug version = DParserOption; enum hasDubSupport = false; class PropertyWindow : Window diff --git a/visuald/vdserverclient.d b/visuald/vdserverclient.d index 00d050bf..a54534ca 100644 --- a/visuald/vdserverclient.d +++ b/visuald/vdserverclient.d @@ -885,7 +885,8 @@ class VDServerClient static void clientLoop() { - startVDServer(); + if (!startVDServer()) + restartServer = true; try { @@ -893,7 +894,7 @@ class VDServerClient bool pendingMessageSent = false; Queue!(_shared!(Command)) toAnswer; - while(gVDServer) + while(gVDServer || restartServer) { bool changed = false; receiveTimeout(dur!"msecs"(50), @@ -973,7 +974,8 @@ class VDServerClient restartServer = false; version(DebugCmd) dbglog("*** clientLoop: restarting server ***"); stopVDServer(); - startVDServer(); + if (!startVDServer()) + restartServer = true; } } } diff --git a/visuald_vs10.sln b/visuald_vs10.sln index 69d75f9f..11aa2a96 100644 --- a/visuald_vs10.sln +++ b/visuald_vs10.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29102.190 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2BD51E62-6604-48AE-9E01-C940C0CA1C68}" ProjectSection(SolutionItems) = preProject @@ -137,7 +137,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", nsis\Extensions\visuald.pkgdef = nsis\Extensions\visuald.pkgdef EndProjectSection EndProject -Project("{002A2DE9-8BB6-484D-9802-7E4AD4084715}") = "dmdserver", "vdc\dmdserver.visualdproj", "{34289BD7-AB7E-4264-B146-8139DDE9F0BF}" +Project("{002A2DE9-8BB6-484D-9802-7E4AD4084715}") = "dmdserver", "vdc\dmdserver\dmdserver.visualdproj", "{34289BD7-AB7E-4264-B146-8139DDE9F0BF}" ProjectSection(ProjectDependencies) = postProject {32872753-4812-40DA-9B24-1C2114621E78} = {32872753-4812-40DA-9B24-1C2114621E78} {2070DF9A-6D80-4E3C-950A-C1BBA1B20F4D} = {2070DF9A-6D80-4E3C-950A-C1BBA1B20F4D} @@ -648,8 +648,8 @@ Global {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug|Win32.Build.0 = Debug|Win32 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug|x64.ActiveCfg = Debug|x64 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug|x64.Build.0 = Debug|x64 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release COFF32|Win32.ActiveCfg = Release|Win32 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release COFF32|Win32.Build.0 = Release|Win32 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release COFF32|Win32.ActiveCfg = Release COFF32|Win32 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release COFF32|Win32.Build.0 = Release COFF32|Win32 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release COFF32|x64.ActiveCfg = Release COFF32|x64 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release COFF32|x64.Build.0 = Release COFF32|x64 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release LDC|Win32.ActiveCfg = Release|Win32 @@ -664,8 +664,8 @@ Global {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Test|Win32.Build.0 = Release|Win32 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Test|x64.ActiveCfg = Release|x64 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Test|x64.Build.0 = Release|x64 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|Win32.ActiveCfg = Debug|Win32 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|Win32.Build.0 = Debug|Win32 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|Win32.ActiveCfg = TestDebug|Win32 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|Win32.Build.0 = TestDebug|Win32 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|x64.ActiveCfg = Debug|x64 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|x64.Build.0 = Debug|x64 EndGlobalSection From 94219807232655814df14b955efc85af6fbf3486 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 19 Jan 2019 21:14:41 +0100 Subject: [PATCH 12/73] fix build, tweak errors and tooltips --- vdc/dmdserver/ddmderrors.d | 3 +- vdc/dmdserver/dmdserver.d | 126 +++++++++++++++++++++++++--- vdc/dmdserver/dmdserver.visualdproj | 4 +- 3 files changed, 118 insertions(+), 15 deletions(-) diff --git a/vdc/dmdserver/ddmderrors.d b/vdc/dmdserver/ddmderrors.d index 9a4eb0f8..accc9db8 100644 --- a/vdc/dmdserver/ddmderrors.d +++ b/vdc/dmdserver/ddmderrors.d @@ -30,6 +30,7 @@ enum Classification gagged = Color.brightBlue, /// for gagged errors warning = Color.brightYellow, /// for warnings deprecation = Color.brightCyan, /// for deprecations + supplemental = Color.brightMagenta, /// for supplemental info (e.g. instantiation trace) } /************************************** @@ -139,7 +140,7 @@ extern (C++) void verrorSupplemental(const ref Loc loc, const(char)* format, va_ color = Classification.gagged; } else - color = Classification.error; + color = Classification.supplemental; verrorPrint(loc, color, " ", format, ap); } diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index 4ea8c411..585509f1 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -110,7 +110,7 @@ version(DebugServer) import core.stdc.stdio : fprintf, fopen, fputc, fflush, FILE; __gshared FILE* dbgfh; - void dbglog(string s) + void dbglog(const(char)[] s) { debug { @@ -356,7 +356,7 @@ class DMDServer : ComObject, IVDServer { version(DebugServer) dbglog("UpdateModule.doParse: exception " ~ t.msg); } - errors = gErrorMessages; + errors = cast(string) gErrorMessages; } synchronized(gErrorSync) { @@ -746,6 +746,7 @@ class DMDServer : ComObject, IVDServer global.params.is64bit = mOptions.x64; global.params.mscoff = mOptions.msvcrt; global.params.cpu = CPU.baseline; + global.params.isLP64 = global.params.is64bit; global.params.versionlevel = mOptions.versionIds.level; global.params.versionids = new Strings(); @@ -759,6 +760,7 @@ class DMDServer : ComObject, IVDServer foreach (charz; *global.params.versionids) VersionCondition.addGlobalIdent(charz[0 .. strlen(charz)]); +/* VersionCondition.addPredefinedGlobalIdent("DigitalMars"); VersionCondition.addPredefinedGlobalIdent("Windows"); VersionCondition.addPredefinedGlobalIdent("LittleEndian"); @@ -797,7 +799,7 @@ class DMDServer : ComObject, IVDServer VersionCondition.addPredefinedGlobalIdent("D_NoBoundsChecks"); if (global.params.betterC) VersionCondition.addPredefinedGlobalIdent("D_betterC"); - +*/ // always enable for tooltips global.params.doDocComments = true; @@ -955,7 +957,9 @@ private: shared(Object) gErrorSync = new Object; __gshared string gErrorFile; -__gshared string gErrorMessages; +__gshared char[] gErrorMessages; +__gshared char[] gOtherErrorMessages; +__gshared bool gErrorWasSupplemental; extern(C++) void verrorPrint(const ref Loc loc, Color headerColor, const(char)* header, @@ -964,25 +968,63 @@ void verrorPrint(const ref Loc loc, Color headerColor, const(char)* header, if (!loc.filename) return; + import dmd.errors; + synchronized(gErrorSync) { - if (_stricmp(loc.filename, gErrorFile) != 0) - return; + bool other = _stricmp(loc.filename, gErrorFile) != 0; + bool supplemental = (cast(Classification)headerColor == Classification.supplemental); __gshared char[4096] buf; - int len = snprintf(buf.ptr, buf.length, "%d,%d,%d,%d:", loc.linnum, loc.charnum - 1, loc.linnum, loc.charnum); + int len = 0; + if (other) + { + len = snprintf(buf.ptr, buf.length, "%s(%d):", loc.filename, loc.linnum); + } + else + { + int llen = snprintf(buf.ptr, buf.length, "%d,%d,%d,%d:", loc.linnum, loc.charnum - 1, loc.linnum, loc.charnum); + gErrorMessages ~= buf[0..llen]; + if (supplemental) + gErrorMessages ~= gOtherErrorMessages; + gOtherErrorMessages = null; + } if (p1 && len < buf.length) len += snprintf(buf.ptr + len, buf.length - len, "%s ", p1); if (p2 && len < buf.length) len += snprintf(buf.ptr + len, buf.length - len, "%s ", p2); if (len < buf.length) len += vsnprintf(buf.ptr + len, buf.length - len, format, ap); + char nl = other ? '\a' : '\n'; if (len < buf.length) - buf[len++] = '\n'; + buf[len++] = nl; else - buf[$-1] = '\n'; + buf[$-1] = nl; + + dbglog(buf[0..len]); - gErrorMessages ~= buf[0..len]; + if (other) + { + if (gErrorWasSupplemental) + { + if (gErrorMessages.length && gErrorMessages[$-1] == '\n') + gErrorMessages[$-1] = '\a'; + gErrorMessages ~= buf[0..len]; + gErrorMessages ~= '\n'; + } + else if (supplemental) + gOtherErrorMessages ~= buf[0..len]; + else + { + gErrorWasSupplemental = false; + gOtherErrorMessages = buf[0..len].dup; + } + } + else + { + gErrorMessages ~= buf[0..len]; + gErrorWasSupplemental = supplemental; + } } } @@ -992,6 +1034,8 @@ void initErrorFile(string fname) { gErrorFile = fname; gErrorMessages = null; + gOtherErrorMessages = null; + gErrorWasSupplemental = false; } } @@ -1016,7 +1060,6 @@ version(all) // new mangling with dmd version >= 2.077 ["_D3dmd7dstruct15search_toStringRCQBfQBe17StructDeclarationZ10tftostringCQCs5mtype12TypeFunction", "TypeFunction"], ["_D3dmd13expressionsem11loadStdMathFZ10impStdMathCQBv7dimport6Import", "Import"], ["_D3dmd4func15FuncDeclaration8genCfuncRPSQBm4root5array__T5ArrayTCQCl5mtype9ParameterZQBcCQDjQy4TypeCQDu10identifier10IdentifiermZ2stCQFb7dsymbol12DsymbolTable", "DsymbolTable"], - ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ11visitAArrayMFCQEwQEc10TypeAArrayZ8fd_aaLenCQFz4func15FuncDeclaration", "FuncDeclaration"], ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ3feqCQEn4func15FuncDeclaration", "FuncDeclaration"], ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ4fcmpCQEo4func15FuncDeclaration", "FuncDeclaration"], ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ5fhashCQEp4func15FuncDeclaration", "FuncDeclaration"], @@ -1026,7 +1069,8 @@ version(all) // new mangling with dmd version >= 2.077 ["_D3dmd9dtemplate16TemplateInstance16tryExpandMembersMFPSQCc6dscope5ScopeZ4nesti", "int"], ["_D3dmd9dtemplate16TemplateInstance12trySemantic3MFPSQBy6dscope5ScopeZ4nesti", "int"], ["_D3dmd13expressionsem25ExpressionSemanticVisitor5visitMRCQCd10expression7CallExpZ4nesti", "int"], - ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ8noMemberMFQDxQDmQCxQByiZ4nesti", "int"], + //["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ11visitAArrayMFCQEwQEc10TypeAArrayZ8fd_aaLenCQFz4func15FuncDeclaration", "FuncDeclaration"], + //["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ8noMemberMFQDxQDmQCxQByiZ4nesti", "int"], ]; } else @@ -1130,6 +1174,10 @@ void clearDmdStatics() // dmd.dinterpret // ctfeStack = ctfeStack.init; + // dmd.dtemplate + emptyArrayElement = null; + TemplateValueParameter.edummies = null; + Scope.freelist = null; //Token.freelist = null; @@ -1174,6 +1222,14 @@ extern(C++) class ASTVisitor : StoppableVisitor sym.accept(this); } + // override void visit(Expression) {} + // override void visit(Parameter) {} + // override void visit(Statement) {} + // override void visit(Type) {} + // override void visit(TemplateParameter) {} + // override void visit(Condition) {} + // override void visit(Initializer) {} + override void visit(ScopeDsymbol scopesym) { // optimize to only visit members in approriate source range @@ -1198,6 +1254,28 @@ extern(C++) class ASTVisitor : StoppableVisitor visitExpression(einit.exp); } + override void visit(VoidInitializer vinit) + { + } + + override void visit(StructInitializer sinit) + { + foreach (i, const id; sinit.field) + if (auto iz = sinit.value[i]) + iz.accept(this); + } + + override void visit(ArrayInitializer ainit) + { + foreach (i, ex; ainit.index) + { + if (ex) + ex.accept(this); + if (auto iz = ainit.value[i]) + iz.accept(this); + } + } + override void visit(FuncDeclaration decl) { visit(cast(Declaration)decl); @@ -1525,6 +1603,27 @@ extern(C++) class FindASTVisitor : ASTVisitor if (matchIdentifier(de.identloc, de.ident)) foundNode(de); } + + override void visit(DotTemplateExp dte) + { + if (!found && dte.td && dte.td.ident) + if (matchIdentifier(dte.identloc, dte.td.ident)) + foundNode(dte); + } + + override void visit(TemplateExp te) + { + if (!found && te.td && te.td.ident) + if (matchIdentifier(te.identloc, te.td.ident)) + foundNode(te); + } + + override void visit(DotVarExp dve) + { + if (!found && dve.var && dve.var.ident) + if (matchIdentifier(dve.varloc, dve.var.ident)) + foundNode(dve); + } } extern(C++) class FindTipVisitor : FindASTVisitor @@ -1594,6 +1693,9 @@ extern(C++) class FindTipVisitor : FindASTVisitor case TOK.symbolOffset: tip = tipForDeclaration((cast(SymbolExp)e).var); break; + case TOK.dotVariable: + tip = tipForDeclaration((cast(DotVarExp)e).var); + break; default: if (e.type) toc = e.type.toPrettyChars(); diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index fdbefdb6..5cab7d38 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -292,7 +292,7 @@ 0 MARS NoBackend 0 - 0 + 1 0 0 @@ -508,7 +508,7 @@ 0 MARS NoBackend GC 0 - 2 + 1 0 0 From c4d01df67283998504322a0134f932c361c372a3 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 19 Jul 2019 11:20:00 +0200 Subject: [PATCH 13/73] other output paths for x64 builds --- c2d/c2d.visualdproj | 2 +- c2d/cpp2d.visualdproj | 306 ++++++++++++++++++++++++++------ c2d/vsi2d.visualdproj | 2 +- sdk/vsi.visualdproj | 356 +++++++++++++++++++++++++++++--------- stdext/stdext.visualdproj | 2 +- vdc/parser.visualdproj | 275 ++++++++++++++--------------- visuald_vs10.sln | 18 +- 7 files changed, 671 insertions(+), 290 deletions(-) diff --git a/c2d/c2d.visualdproj b/c2d/c2d.visualdproj index 88d6ecb5..4e98f056 100644 --- a/c2d/c2d.visualdproj +++ b/c2d/c2d.visualdproj @@ -1400,7 +1400,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) diff --git a/c2d/cpp2d.visualdproj b/c2d/cpp2d.visualdproj index 6fde8a9e..38c530d8 100644 --- a/c2d/cpp2d.visualdproj +++ b/c2d/cpp2d.visualdproj @@ -32,7 +32,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -45,10 +45,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -86,10 +98,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -140,7 +153,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -153,10 +166,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -194,10 +219,11 @@ 0 $(VisualDInstallDir)cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -248,7 +274,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -261,10 +287,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 1 $(CC) -c @@ -302,10 +340,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -356,7 +395,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -369,10 +408,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -410,10 +461,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -464,7 +516,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -477,10 +529,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -518,10 +582,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -572,7 +637,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -585,10 +650,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -626,10 +703,11 @@ 0 $(VisualDInstallDir)cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -680,7 +758,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -693,10 +771,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 1 0 $(CC) -c @@ -734,10 +824,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin -lws2_32 -lkernel32 -lwsock32 -ladvapi32 -loleaut32 -lole32 @@ -788,7 +879,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -801,10 +892,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -842,10 +945,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin oleaut32.lib ole32.lib @@ -896,7 +1000,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -909,10 +1013,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -950,10 +1066,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1004,7 +1121,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -1017,10 +1134,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -1058,10 +1187,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin comctl32.lib ntstc_libcmt.lib @@ -1112,7 +1242,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -1125,10 +1255,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -1166,10 +1308,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -1220,7 +1363,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -1233,10 +1376,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -1245,7 +1400,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -1274,10 +1429,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -1328,7 +1484,7 @@ 0 0 0 - 1 + 3 0 0 1 @@ -1341,10 +1497,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -1382,10 +1550,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1436,7 +1605,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -1449,10 +1618,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -1490,10 +1671,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin comctl32.lib ntstc_libcmt.lib @@ -1544,7 +1726,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -1557,10 +1739,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -1598,10 +1792,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -1652,7 +1847,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -1665,10 +1860,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -1706,10 +1913,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib diff --git a/c2d/vsi2d.visualdproj b/c2d/vsi2d.visualdproj index bf156d9b..27827468 100644 --- a/c2d/vsi2d.visualdproj +++ b/c2d/vsi2d.visualdproj @@ -1158,7 +1158,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) diff --git a/sdk/vsi.visualdproj b/sdk/vsi.visualdproj index 48f433b4..c58aa684 100644 --- a/sdk/vsi.visualdproj +++ b/sdk/vsi.visualdproj @@ -1,6 +1,6 @@ {32872753-4812-40DA-9B24-1C2114621E78} - + 0 0 1 @@ -32,7 +32,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -45,10 +45,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -86,10 +98,11 @@ 1 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -108,7 +121,7 @@ *.obj - + 0 0 1 @@ -140,7 +153,7 @@ 0 0 0 - 1 + 3 0 0 1 @@ -153,10 +166,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -194,10 +219,11 @@ 0 $(VisualDInstallDir)cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -216,7 +242,7 @@ *.obj - + 0 0 1 @@ -248,7 +274,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -261,10 +287,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -302,10 +340,11 @@ 1 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -324,7 +363,7 @@ *.obj - + 0 0 1 @@ -356,7 +395,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -369,10 +408,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -410,10 +461,11 @@ 0 $(VisualDInstallDir)cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -432,7 +484,7 @@ *.obj - + 0 0 1 @@ -464,7 +516,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -477,10 +529,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 1 0 $(CC) -c @@ -518,10 +582,11 @@ 0 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -540,7 +605,7 @@ *.obj - + 0 0 1 @@ -572,7 +637,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -585,10 +650,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 1 0 $(CC) -c @@ -626,10 +703,11 @@ 0 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -648,7 +726,7 @@ *.obj - + 0 0 1 @@ -680,7 +758,7 @@ 0 0 0 - 1 + 3 0 0 1 @@ -693,10 +771,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -734,10 +824,11 @@ 0 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -756,7 +847,7 @@ *.obj - + 0 0 1 @@ -788,7 +879,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -801,10 +892,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -842,10 +945,11 @@ 0 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -864,7 +968,7 @@ *.obj - + 0 0 1 @@ -896,7 +1000,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -909,10 +1013,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -950,10 +1066,11 @@ 0 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -972,7 +1089,7 @@ *.obj - + 0 0 1 @@ -1004,7 +1121,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -1017,10 +1134,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -1058,10 +1187,11 @@ 0 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1080,7 +1210,7 @@ *.obj - + 0 0 1 @@ -1112,7 +1242,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -1125,10 +1255,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -1166,10 +1308,11 @@ 1 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1188,7 +1331,7 @@ *.obj - + 0 0 1 @@ -1220,7 +1363,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -1233,10 +1376,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -1245,7 +1400,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -1274,10 +1429,11 @@ 1 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1296,7 +1452,7 @@ *.obj - + 0 0 1 @@ -1328,7 +1484,7 @@ 0 0 0 - 1 + 3 0 0 1 @@ -1341,10 +1497,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -1382,10 +1550,11 @@ 0 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1404,7 +1573,7 @@ *.obj - + 0 0 1 @@ -1436,7 +1605,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -1449,10 +1618,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -1490,10 +1671,11 @@ 0 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1512,7 +1694,7 @@ *.obj - + 0 0 1 @@ -1544,7 +1726,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -1557,10 +1739,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -1598,10 +1792,11 @@ 1 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1620,7 +1815,7 @@ *.obj - + 0 0 1 @@ -1652,7 +1847,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -1665,10 +1860,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -1706,10 +1913,11 @@ 1 "$(VisualDInstallDir)cv2pdb.exe" - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1933,12 +2141,6 @@ - - - - - - @@ -1974,9 +2176,6 @@ - - - @@ -1993,14 +2192,6 @@ - - - - - - - - @@ -2036,7 +2227,6 @@ - diff --git a/stdext/stdext.visualdproj b/stdext/stdext.visualdproj index 2f0b6e22..05d0afd1 100644 --- a/stdext/stdext.visualdproj +++ b/stdext/stdext.visualdproj @@ -1400,7 +1400,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) diff --git a/vdc/parser.visualdproj b/vdc/parser.visualdproj index ed5f47cb..966845ef 100644 --- a/vdc/parser.visualdproj +++ b/vdc/parser.visualdproj @@ -32,7 +32,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -45,7 +45,6 @@ 0 0 0 - 2 0 0 0 @@ -54,14 +53,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 0 0 @@ -100,10 +98,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -154,7 +153,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -167,7 +166,6 @@ 0 0 0 - 2 0 0 0 @@ -176,14 +174,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 0 0 @@ -222,10 +219,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -276,7 +274,7 @@ 0 0 0 - 1 + 3 0 0 1 @@ -289,7 +287,6 @@ 0 0 0 - 2 0 0 0 @@ -298,14 +295,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 0 0 @@ -344,10 +340,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -398,7 +395,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -411,7 +408,6 @@ 0 0 0 - 2 0 0 0 @@ -420,14 +416,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 0 0 @@ -466,10 +461,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -520,7 +516,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -533,7 +529,6 @@ 0 0 0 - 2 0 0 0 @@ -542,14 +537,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 0 0 @@ -588,10 +582,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -642,7 +637,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -655,7 +650,6 @@ 0 0 0 - 2 0 0 0 @@ -664,14 +658,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 0 0 @@ -710,10 +703,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -764,7 +758,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -777,7 +771,6 @@ 0 0 0 - 2 0 0 0 @@ -786,14 +779,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 1 0 @@ -832,10 +824,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -886,7 +879,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -899,7 +892,6 @@ 0 0 0 - 2 0 0 0 @@ -908,14 +900,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 1 0 @@ -954,10 +945,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1008,7 +1000,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -1021,7 +1013,6 @@ 0 0 0 - 2 0 0 0 @@ -1030,14 +1021,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 2 0 @@ -1076,10 +1066,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1130,7 +1121,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -1143,7 +1134,6 @@ 0 0 0 - 2 0 0 0 @@ -1152,14 +1142,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 2 0 @@ -1198,10 +1187,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1252,7 +1242,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -1265,7 +1255,6 @@ 0 0 0 - 2 0 0 0 @@ -1274,14 +1263,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 0 0 @@ -1320,10 +1308,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1374,7 +1363,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -1387,7 +1376,6 @@ 0 0 0 - 2.043 0 0 0 @@ -1396,14 +1384,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 0 0 @@ -1413,7 +1400,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. . - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -1442,10 +1429,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1496,7 +1484,7 @@ 0 0 0 - 1 + 3 0 0 1 @@ -1509,7 +1497,6 @@ 0 0 0 - 2 0 0 0 @@ -1518,14 +1505,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 2 0 @@ -1564,10 +1550,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1618,7 +1605,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -1631,7 +1618,6 @@ 0 0 0 - 2 0 0 0 @@ -1640,14 +1626,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 2 0 @@ -1686,10 +1671,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1709,7 +1695,6 @@ *.obj - 0 0 0 1 @@ -1741,7 +1726,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -1754,7 +1739,6 @@ 0 0 0 - 2 0 0 0 @@ -1763,14 +1747,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 0 0 @@ -1809,10 +1792,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1863,7 +1847,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -1876,7 +1860,6 @@ 0 0 0 - 2 0 0 0 @@ -1885,14 +1868,13 @@ 0 0 0 - 0 - 0 + 0 + 0 0 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 0 0 1 @@ -1931,10 +1913,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin diff --git a/visuald_vs10.sln b/visuald_vs10.sln index 11aa2a96..9519fc3c 100644 --- a/visuald_vs10.sln +++ b/visuald_vs10.sln @@ -607,7 +607,7 @@ Global {2F75431E-B8DB-4231-AAC1-EA68D06A22E6}.TestDebug|x64.Build.0 = Debug|x64 {CD26A145-F663-473D-8908-0254FE377D48}.Debug COFF32|Win32.ActiveCfg = Debug COFF32|Win32 {CD26A145-F663-473D-8908-0254FE377D48}.Debug COFF32|Win32.Build.0 = Debug COFF32|Win32 - {CD26A145-F663-473D-8908-0254FE377D48}.Debug COFF32|x64.ActiveCfg = Debug|Win32 + {CD26A145-F663-473D-8908-0254FE377D48}.Debug COFF32|x64.ActiveCfg = Debug COFF32|Win32 {CD26A145-F663-473D-8908-0254FE377D48}.Debug GDC|Win32.ActiveCfg = Debug|Win32 {CD26A145-F663-473D-8908-0254FE377D48}.Debug GDC|Win32.Build.0 = Debug|Win32 {CD26A145-F663-473D-8908-0254FE377D48}.Debug GDC|x64.ActiveCfg = Debug|Win32 @@ -644,10 +644,10 @@ Global {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug LDC|Win32.Build.0 = Debug|Win32 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug LDC|x64.ActiveCfg = Debug LDC|x64 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug LDC|x64.Build.0 = Debug LDC|x64 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug|Win32.ActiveCfg = Debug|Win32 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug|Win32.Build.0 = Debug|Win32 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug|x64.ActiveCfg = Debug|x64 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug|x64.Build.0 = Debug|x64 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug OMF|Win32.ActiveCfg = Debug|Win32 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug OMF|Win32.Build.0 = Debug|Win32 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug OMF|x64.ActiveCfg = Debug|x64 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Debug OMF|x64.Build.0 = Debug|x64 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release COFF32|Win32.ActiveCfg = Release COFF32|Win32 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release COFF32|Win32.Build.0 = Release COFF32|Win32 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release COFF32|x64.ActiveCfg = Release COFF32|x64 @@ -656,10 +656,10 @@ Global {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release LDC|Win32.Build.0 = Release|Win32 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release LDC|x64.ActiveCfg = Release|x64 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release LDC|x64.Build.0 = Release|x64 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release|Win32.ActiveCfg = Release|Win32 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release|Win32.Build.0 = Release|Win32 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release|x64.ActiveCfg = Release|x64 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release|x64.Build.0 = Release|x64 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release OMF|Win32.ActiveCfg = Release|Win32 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release OMF|Win32.Build.0 = Release|Win32 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release OMF|x64.ActiveCfg = Release|x64 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Release OMF|x64.Build.0 = Release|x64 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Test|Win32.ActiveCfg = Release|Win32 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Test|Win32.Build.0 = Release|Win32 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Test|x64.ActiveCfg = Release|x64 From b689f45108c90863e25f21af8b8c53c7e883b5b8 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 19 Jul 2019 11:23:05 +0200 Subject: [PATCH 14/73] adapt to recent dmd/GC --- tools/tracegc.d | 235 ++++++++++++++++++++------- vdc/dmdserver/ddmderrors.d | 2 +- vdc/dmdserver/ddmdrmem.d | 21 ++- vdc/dmdserver/dmdserver.d | 142 ++++++++++------ vdc/dmdserver/dmdserver.visualdproj | 244 +++++++++++++++++++++++----- vdc/ivdserver.idl | 2 +- vdc/vdserver.idl | 1 - 7 files changed, 480 insertions(+), 167 deletions(-) diff --git a/tools/tracegc.d b/tools/tracegc.d index 80e83edb..b44b107c 100644 --- a/tools/tracegc.d +++ b/tools/tracegc.d @@ -2,7 +2,7 @@ module tracegc; import core.stdc.string; -//version = traceGC; +version = traceGC; // tiny helper to clear a page of the stack below the current stack pointer to avoid false pointers there void wipeStack() @@ -207,11 +207,11 @@ bool validFilename(const(char)* fn) r"\gc\proxy.d", r"\core\memory.d", r"\std\array.d", - r"\ddmd\root\rmem.d", - r"\ddmd\root\array.d", - r"\ddmd\root\aav.d", - r"\ddmd\root\outbuffer.d", - r"\ddmd\root\stringtable.d", + r"\dmd\root\rmem.d", + r"\dmd\root\array.d", + r"\dmd\root\aav.d", + r"\dmd\root\outbuffer.d", + r"\dmd\root\stringtable.d", r"\stdext\com.d", r"\ddmdrmem.d", ]; @@ -224,17 +224,53 @@ bool validFilename(const(char)* fn) //////////////////////////////////////////////////////////// -import gc.gcinterface; +import core.gc.gcinterface; +import core.gc.registry; import gc.os; import core.exception; +extern (C) pragma(crt_constructor) void register_tracegc() +{ + registerGCFactory("trace", &GCTraceProxy.initialize); +} + class GCTraceProxy : GC { GC gc; - void Dtor() + static GC initialize() { - gc.Dtor(); + __gshared ubyte[__traits(classInstanceSize, GCTraceProxy)] buf; + + initRtlCaptureStackBackTrace(); + // initTraceMalloc(); + + auto init = typeid(GCTraceProxy).initializer(); + assert(init.length == buf.length); + auto instance = cast(GCTraceProxy) memcpy(buf.ptr, init.ptr, init.length); + instance.__ctor(); + return instance; + } + + this() + { + // unfortunately, registry cannot be invoked twice, and + // initialize for ConservativeGC is private + __gshared ubyte[__traits(classInstanceSize, ConservativeGC)] buf; + + ConservativeGC.isPrecise = true; + auto init = typeid(ConservativeGC).initializer(); + assert(init.length == __traits(classInstanceSize, ConservativeGC)); + auto instance = cast(ConservativeGC) memcpy(buf.ptr, init.ptr, init.length); + instance.__ctor(); + + gc = instance; + tracer = this; + } + + ~this() + { + destroy(gc); } void enable() @@ -340,6 +376,11 @@ class GCTraceProxy : GC return gc.stats(); } + core.memory.GC.ProfileStats profileStats() nothrow + { + return gc.profileStats(); + } + void addRoot(void* p) nothrow @nogc { return gc.addRoot(p); @@ -386,14 +427,36 @@ class GCTraceProxy : GC /////////////////////////////////////////////////////////// static struct TraceEntry { + enum eagerResolve = true; + void* addr; - size_t[15] buffer; + static if (eagerResolve) + { + StackAddrInfo* ai; + + StackAddrInfo* resolve() nothrow { return ai; } + } + else + { + size_t[15] buffer; - StackAddrInfo* resolve() nothrow + StackAddrInfo* resolve() nothrow { return _resolve(buffer[]); } + } + + void initialize(void* addr, ref size_t[15] buf) nothrow { - for (size_t sp = 0; sp < buffer.length && buffer[sp]; sp++) + this.addr = addr; + static if (eagerResolve) + ai = _resolve(buf[]); + else + buffer[] = buf[]; + } + + StackAddrInfo* _resolve(size_t[] buf) nothrow + { + for (size_t sp = 0; sp < buf.length && buf[sp]; sp++) { - StackAddrInfo* ai = resolveAddr(buffer[sp]); + StackAddrInfo* ai = resolveAddr(buf[sp]); if (ai.line != uint.max) return ai; } @@ -527,7 +590,7 @@ nothrow: size_t memUsage() { - size_t sum = _cap * Range.sizeof; + size_t sum = _cap * Range.sizeof; for (size_t r = 0; r < _length; r++) sum += _p[r]._capacity * TraceEntry.sizeof; return sum; @@ -554,6 +617,9 @@ private: size_t _cap; } +__gshared GCTraceProxy tracer; + +/+ import core.demangle; extern pragma(mangle, mangle!GC("gc.proxy.instance")) __gshared GC gc_instance; @@ -561,7 +627,7 @@ __gshared GCTraceProxy tracer = new GCTraceProxy; extern(C) void gc_init() { - import gc.config; + import core.gc.config; config.initialize(); ConservativeGC.initialize(gc_instance); @@ -590,13 +656,16 @@ void removeGCTracer() { gc_instance = tracer.gc; } ++/ void traceAlloc(void* addr) nothrow { - TraceEntry te; + size_t[15] buf; + + auto backtraceLength = RtlCaptureStackBackTrace(2, cast(ULONG)buf.length, cast(void**)buf.ptr, null); - te.addr = addr; - auto backtraceLength = RtlCaptureStackBackTrace(2, cast(ULONG)te.buffer.length, cast(void**)te.buffer.ptr, null); + TraceEntry te; + te.initialize(addr, buf); tracer.traceBuffer.pushEntry(te); } @@ -626,9 +695,7 @@ void dumpAddr(AddrTracePair[] traceMap, void* addr, size_t size) else filename = ": "; - gc.impl.conservative.gc.printf("%s(%d): %p %llx\n", filename, line, addr, cast(long) size); - //sprintf(buf.ptr, "%s(%d): %p %llx\n", filename, line, addr, cast(long) size); - //OutputDebugStringA(buf.ptr); + trace_printf("%s(%d): %p %llx\n", filename, line, addr, cast(long) size); } struct AddrInfoStat @@ -666,16 +733,16 @@ void dumpAddrInfoStat() { char[256] buf; - OutputDebugStringA("Dump combined by stack location:\n"); + trace_printf("\nDump combined by stack location:\n"); foreach(ref info; addrInfoStat) if (info.ai) { const(char)* filename = stringBuffer.ptr + info.ai.filenameOff; - sprintf(buf.ptr, "%s(%d): %lld allocs %llx bytes\n", filename, info.ai.line, cast(long)info.count, cast(long)info.size); - OutputDebugStringA(buf.ptr); + trace_printf("%s(%d): %lld allocs %llx bytes\n", filename, info.ai.line, cast(long)info.count, cast(long)info.size); } + trace_printf("\n"); } /////////////////////////////////////////////////////////////// @@ -688,9 +755,9 @@ void collectReferences(ConservativeGC cgc, ref HashTab!(void*, void*) references cgc.gcLock.lock(); auto pooltable = gcx.pooltable; - alias ScanRange = gc.gcinterface.Range; + alias ScanRange = Gcx.ScanRange!false; - Gcx.ToScanStack toscan; + Gcx.ToScanStack!ScanRange toscan; /** * Search a range of memory values and mark any pointers into the GC pool. @@ -741,7 +808,7 @@ void collectReferences(ConservativeGC cgc, ref HashTab!(void*, void*) references { // We don't care abou setting pointsToBase correctly // because it's ignored for small object pools anyhow. - auto offsetBase = offset & notbinsize[bin]; + auto offsetBase = baseOffset(offset, cast(Bins)bin); biti = offsetBase >> pool.shiftBy; base = pool.baseAddr + offsetBase; //debug(PRINTF) printf("\t\tbiti = x%x\n", biti); @@ -757,7 +824,7 @@ void collectReferences(ConservativeGC cgc, ref HashTab!(void*, void*) references } else if (bin == B_PAGE) { - auto offsetBase = offset & notbinsize[bin]; + auto offsetBase = offset & ~cast(size_t)(PAGESIZE-1); base = pool.baseAddr + offsetBase; biti = offsetBase >> pool.shiftBy; //debug(PRINTF) printf("\t\tbiti = x%x\n", biti); @@ -862,13 +929,14 @@ void dumpGC(GC _gc) assert(cgc); auto gcx = cgc.gcx; + core.memory.GC.Stats stats = _gc.stats(); + cgc.gcLock.lock(); - char[256] buf; - sprintf(buf.ptr, "Dump of GC %p: %d pools\n", _gc, gcx.npools); - OutputDebugStringA(buf.ptr); - sprintf(buf.ptr, "Trace buffer memory: %lld bytes\n", cast(long)tracer.traceBuffer.memUsage()); - OutputDebugStringA(buf.ptr); + trace_printf("Dump of GC %p: %d pools\n", _gc, gcx.pooltable.length); + trace_printf("Trace buffer memory: %lld bytes\n", cast(long)tracer.traceBuffer.memUsage()); + + trace_printf("GC stats: %lld used, %lld free\n", cast(long)stats.usedSize, cast(long)stats.freeSize); AddrTracePair[] traceMap = tracer.traceBuffer.createTraceMap(); memset(addrInfoStat.ptr, 0, addrInfoStat.sizeof); @@ -880,7 +948,7 @@ void dumpGC(GC _gc) { size_t usedSize = 0; size_t freeSize = 0; - foreach (pool; gcx.pooltable[0 .. gcx.npools]) + foreach (pool; gcx.pooltable[0 .. gcx.pooltable.length]) { foreach (pn, bin; pool.pagetable[0 .. pool.npages]) { @@ -922,10 +990,8 @@ void dumpGC(GC _gc) } } - sprintf(buf.ptr, "Sum of used memory: %lld bytes\n", cast(long)usedSize); - OutputDebugStringA(buf.ptr); - sprintf(buf.ptr, "Sum of free memory: %lld bytes\n", cast(long)freeSize); - OutputDebugStringA(buf.ptr); + trace_printf("Sum of used memory: %lld bytes\n", cast(long)usedSize); + trace_printf("Sum of free memory: %lld bytes\n", cast(long)freeSize); } dumpObjectAddrs(); @@ -938,15 +1004,13 @@ void dumpGC(GC _gc) if (StackAddrInfo* ai = te.resolve()) { const(char)* filename = stringBuffer.ptr + ai.filenameOff; - sprintf(buf.ptr, "%s(%d): root %p\n", filename, ai.line, root); + trace_printf("%s(%d): root %p\n", filename, ai.line, root); } else - sprintf(buf.ptr, ": root %p\n", root); + trace_printf(": root %p\n", root); } else - sprintf(buf.ptr, ": root %p\n", root); - - OutputDebugStringA(buf.ptr); + trace_printf(": root %p\n", root); } void dumpRange(void *pbot, void *ptop) scope nothrow @@ -970,7 +1034,7 @@ void dumpGC(GC _gc) if (bin < B_PAGE) { - auto offsetBase = offset & notbinsize[bin]; + auto offsetBase = baseOffset(offset, cast(Bins)bin); base = pool.baseAddr + offsetBase; biti = offsetBase >> pool.shiftBy; if (pool.freebits.test(biti)) @@ -978,7 +1042,7 @@ void dumpGC(GC _gc) } else if (bin == B_PAGE) { - auto offsetBase = offset & notbinsize[bin]; + auto offsetBase = offset & ~cast(size_t)(PAGESIZE-1); base = pool.baseAddr + offsetBase; } else if (bin == B_PAGEPLUS) @@ -991,31 +1055,29 @@ void dumpGC(GC _gc) if (!rangeShown) { - sprintf(buf.ptr, "within range %p - %p:\n", pbot, ptop); - OutputDebugStringA(buf.ptr); + trace_printf("within range %p - %p:\n", pbot, ptop); rangeShown = true; } - int len; + if (auto te = tracer.traceBuffer.findTraceEntry(traceMap, base)) { if (StackAddrInfo* ai = te.resolve()) { const(char)* filename = stringBuffer.ptr + ai.filenameOff; - len = sprintf(buf.ptr, "%s(%d): @range+%llx %p", filename, ai.line, cast(long)(cast(void*)p - pbot), root); + trace_printf("%s(%d): @range+%llx %p", filename, ai.line, cast(long)(cast(void*)p - pbot), root); } else - len = sprintf(buf.ptr, ": @range+%llx %p", cast(long)(cast(void*)p - pbot), root); + trace_printf(": @range+%llx %p", cast(long)(cast(void*)p - pbot), root); } else { - len = sprintf(buf.ptr, ": @range+%llx %p", cast(long)(cast(void*)p - pbot), root); + trace_printf(": @range+%llx %p", cast(long)(cast(void*)p - pbot), root); } if (root != base) - len += sprintf(buf.ptr + len, " base %p", base); - buf.ptr[len++] = '\n'; - buf.ptr[len] = 0; - OutputDebugStringA(buf.ptr); + trace_printf(" base %p\n", base); + else + trace_printf("\n"); } } foreach(range; _gc.rangeIter) @@ -1049,6 +1111,10 @@ void findRoot(void* sobj) const(void*) minAddr = cgc.gcx.pooltable.minAddr; const(void*) maxAddr = cgc.gcx.pooltable.maxAddr; + import core.sys.windows.dbghelp; + auto dbghelp = DbgHelp.get(); + HANDLE hProcess = GetCurrentProcess(); + char[256] buf; nextLoc: for ( ; ; ) @@ -1058,15 +1124,21 @@ nextLoc: if (te && (ai = te.resolve()) !is null) { const(char)* filename = stringBuffer.ptr + ai.filenameOff; - sprintf(buf.ptr, "%s(%d): %p\n", filename, ai.line, sobj); + trace_printf("%s(%d): %p\n", filename, ai.line, sobj); } else - sprintf(buf.ptr, "no location: %p\n", sobj); - OutputDebugStringA(buf.ptr); + trace_printf("no location: %p\n", sobj); ulong src; if (auto psrc = sobj in references) { + BlkInfo info = cgc.queryNoSync(*psrc); + if (info.base) + { + sobj = info.base; + continue nextLoc; + } + for (void* base = *psrc; base >= minAddr && base <= maxAddr; ) { if (auto pobj = base in objects) @@ -1083,9 +1155,52 @@ nextLoc: else base -= 0x1000; } - sprintf(buf.ptr, "%p not a heap object\n", *psrc); - OutputDebugStringA(buf.ptr); + trace_printf("%p not a heap object\n", *psrc); + + DWORD64 disp; + char[300] symbuf; + auto sym = cast(IMAGEHLP_SYMBOLA64*) symbuf.ptr; + sym.SizeOfStruct = IMAGEHLP_SYMBOLA64.sizeof; + sym.MaxNameLength = 300 - IMAGEHLP_SYMBOLA64.sizeof; + + if (dbghelp.SymGetSymFromAddr64(hProcess, cast(size_t)*psrc, &disp, sym)) + trace_printf(" sym %s + %lld\n", sym.Name.ptr, disp); } break; } } + +//////////////////////////////////////////////////////////////// +private __gshared MonoTime gcStartTick; +private __gshared FILE* gcx_fh; +private __gshared bool hadNewline = false; + +private int trace_printf(ARGS...)(const char* fmt, ARGS args) nothrow +{ + if (!gcx_fh) + gcx_fh = fopen("tracegc.log", "w"); + if (!gcx_fh) + return 0; + + int len; + if (MonoTime.ticksPerSecond == 0) + { + len = fprintf(gcx_fh, "before init: "); + } + else if (hadNewline) + { + if (gcStartTick == MonoTime.init) + gcStartTick = MonoTime.currTime; + immutable timeElapsed = MonoTime.currTime - gcStartTick; + immutable secondsAsDouble = timeElapsed.total!"hnsecs" / cast(double)convert!("seconds", "hnsecs")(1); + len = fprintf(gcx_fh, "%10.6lf: ", secondsAsDouble); + } + len += fprintf(gcx_fh, fmt, args); + fflush(gcx_fh); + import core.stdc.string; + hadNewline = fmt && fmt[0] && fmt[strlen(fmt) - 1] == '\n'; + return len; +} + +//sprintf(buf.ptr, "%s(%d): %p %llx\n", filename, line, addr, cast(long) size); +//OutputDebugStringA(buf.ptr); diff --git a/vdc/dmdserver/ddmderrors.d b/vdc/dmdserver/ddmderrors.d index accc9db8..2bc4843b 100644 --- a/vdc/dmdserver/ddmderrors.d +++ b/vdc/dmdserver/ddmderrors.d @@ -8,7 +8,7 @@ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/ddmd/errors.d, _errors.d) */ -module dmd.errors; +module dmderrors; // Online documentation: https://dlang.org/phobos/ddmd_errors.html diff --git a/vdc/dmdserver/ddmdrmem.d b/vdc/dmdserver/ddmdrmem.d index 711301e1..c10595a7 100644 --- a/vdc/dmdserver/ddmdrmem.d +++ b/vdc/dmdserver/ddmdrmem.d @@ -10,24 +10,24 @@ extern (C++) struct Mem return p[0 .. strlen(p) + 1].dup.ptr; } - static void xfree(void* p) nothrow + static void xfree(void* p) nothrow pure { return GC.free(p); } - static void* xmalloc(size_t n) nothrow + static void* xmalloc(size_t n) nothrow pure { - if (cancel) - throw cancelError; + if (*pcancel) + throw *pcancelError; return GC.malloc(n); } - static void* xcalloc(size_t size, size_t n) nothrow + static void* xcalloc(size_t size, size_t n) nothrow pure { return GC.calloc(size * n); } - static void* xrealloc(void* p, size_t size) nothrow + static void* xrealloc(void* p, size_t size) nothrow pure { return GC.realloc(p, size); } @@ -37,8 +37,11 @@ extern (C++) struct Mem throw oom; } - __gshared cancelError = new Error("cancel malloc"); - __gshared bool cancel; + extern(D) __gshared immutable cancelError = new Error("cancel malloc"); + extern(D) __gshared bool cancel; + // fake purity + enum pcancel = cast(immutable) &cancel; + enum pcancelError = cast(immutable) &cancelError; } extern (C++) const __gshared Mem mem; @@ -53,7 +56,7 @@ Params: Returns: A null-terminated copy of the input array. */ -extern (D) char[] xarraydup(const(char)[] s) nothrow +extern (D) char[] xarraydup(const(char)[] s) nothrow pure { if (!s) return null; diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index 585509f1..fe5dffea 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -29,6 +29,7 @@ import dmd.dstruct; import dmd.dsymbol; import dmd.dsymbolsem; import dmd.dtemplate; +import dmd.errors; import dmd.expression; import dmd.func; import dmd.globals; @@ -47,6 +48,8 @@ import dmd.tokens; import dmd.visitor; import dmd.root.outbuffer; +import dmd.root.file; +import dmd.root.filename; import dmd.root.rmem; import dmd.root.rootobject; @@ -74,6 +77,7 @@ import stdext.array; version = SingleThread; //import std.stdio; +import std.ascii; import std.parallelism; import std.path; import std.string; @@ -90,7 +94,7 @@ import core.stdc.stdio; import core.stdc.stdlib; import core.stdc.string; -//version = traceGC; +// version = traceGC; version (traceGC) import tracegc; debug version = DebugServer; @@ -99,7 +103,11 @@ debug version = DebugServer; shared(Object) gDMDSync = new Object; // no multi-instances/multi-threading with DMD shared(Object) gOptSync = new Object; // no multi-instances/multi-threading with DMD -extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise" ]; +version (traceGC) + extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise", "gcopt=gc:trace" ]; +else + // precise GC doesn't help much because dmd erases most type info + extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise", "gcopt=gc:precise" ]; /////////////////////////////////////////////////////////////////////// version(DebugServer) @@ -153,13 +161,6 @@ class DMDServer : ComObject, IVDServer version(unittest) {} else version(SingleThread) mTid = spawn(&taskLoop, thisTid); mOptions = new Options; - - synchronized(gDMDSync) - { - global._init(); - global.params.isWindows = true; - global.params.errorLimit = 0; - } } override ULONG Release() @@ -306,17 +307,16 @@ class DMDServer : ComObject, IVDServer mod = findModule(fname, false); if (mod) { - if (auto pErr = cast(void*)mod in mErrors) + if (auto pErr = fname in mErrors) if (*pErr == "__parsing__") doCancel = true; } // always create new module mod = findModule(fname, true); - mod.srcfile.setbuffer(cast(char*)(text.ptr), text.length); - mod.srcfile._ref = 1; // do not own buffer + mod.srcBuffer = new FileBuffer(cast(ubyte[])text); - mErrors[cast(void*)mod] = "__pending__"; + mErrors[fname] = "__pending__"; } if (doCancel) { @@ -334,7 +334,7 @@ class DMDServer : ComObject, IVDServer synchronized(gErrorSync) { - auto pErr = cast(void*)mod in mErrors; + auto pErr = fname in mErrors; if (!pErr) return; // already relaced by a new request @@ -360,7 +360,7 @@ class DMDServer : ComObject, IVDServer } synchronized(gErrorSync) { - if (auto pErr = cast(void*)mod in mErrors) + if (auto pErr = fname in mErrors) *pErr = errors; } @@ -380,7 +380,7 @@ class DMDServer : ComObject, IVDServer { synchronized(gErrorSync) { - if (auto pError = cast(void*)mod in mErrors) + if (auto pError = fname in mErrors) { if (*pError != "__pending__" && *pError != "__parsing__") { @@ -646,7 +646,7 @@ class DMDServer : ComObject, IVDServer return S_OK; } - override HRESULT GetReferences(in BSTR filename, in BSTR tok, uint line, uint idx, in BSTR expr) + override HRESULT GetReferences(in BSTR filename, in BSTR tok, uint line, uint idx, in BSTR expr, in BOOL moduleOnly) { return E_NOTIMPL; } @@ -699,20 +699,20 @@ class DMDServer : ComObject, IVDServer { clearDmdStatics(); - // Initialization - Token._init(); - Type._init(); - Id.initialize(); - Module._init(); - Target._init(); - Expression._init(); - Objc._init(); - builtin_init(); + // (de-)initialization + Type.deinitialize(); + Id.deinitialize(); + Module.deinitialize(); + target.deinitialize(); + Expression.deinitialize(); + Objc.deinitialize(); + builtinDeinitialize(); + Module.rootModule = null; - global.gag = false; - global.gaggedErrors = 0; - global.errors = 0; - global.warnings = 0; + global = global.init; + + core.memory.GC.Stats stats = GC.stats(); + dbglog(text("before collect GC stats: ", stats.usedSize, " used, ", stats.freeSize, " free\n")); version(traceGC) { @@ -721,10 +721,20 @@ class DMDServer : ComObject, IVDServer dumpGC(); } else + { GC.collect(); + } + + stats = GC.stats(); + dbglog(text("after collect GC stats: ", stats.usedSize, " used, ", stats.freeSize, " free\n")); + + Token._init(); synchronized(gOptSync) { + global._init(); + global.params.isWindows = true; + global.params.errorLimit = 0; global.params.color = false; global.params.link = true; global.params.useAssert = mOptions.debugOn ? CHECKENABLE.on : CHECKENABLE.off; @@ -736,7 +746,7 @@ class DMDServer : ComObject, IVDServer global.params.useSwitchError = CHECKENABLE.on; global.params.useInline = false; global.params.obj = false; - global.params.useDeprecated = mOptions.noDeprecated ? Diagnostic.error : Diagnostic.off; + global.params.useDeprecated = mOptions.noDeprecated ? DiagnosticReporting.error : DiagnosticReporting.off; global.params.linkswitches = Strings(); global.params.libfiles = Strings(); global.params.dllfiles = Strings(); @@ -822,10 +832,19 @@ class DMDServer : ComObject, IVDServer global.filePath.push(toStringz(i)); } + Type._init(); + Id.initialize(); + Module._init(); + Expression._init(); + Objc._init(); + builtin_init(); + + target._init(global.params); + // redo module name with the new Identifier.stringtable foreach (m; modules) { - auto fname = m.srcfile.name.toString(); + auto fname = m.srcfile.toString(); auto name = stripExtension(baseName(fname)); m.ident = Identifier.idPool(name); } @@ -833,7 +852,7 @@ class DMDServer : ComObject, IVDServer for (size_t i = 0; i < modules.length; i++) { Module m = modules[i]; - m.read(Loc()); + m.read(Loc.initial); } size_t filecount = modules.length; for (size_t filei = 0, modi = 0; filei < filecount; filei++, modi++) @@ -909,7 +928,7 @@ private: { size_t pos = mModules.length; foreach (i, m; mModules) - if (_stricmp(m.srcfile.name.toChars(), fname) == 0) + if (FileName.equals(m.srcfile.toString(), fname)) { if (createNew) { @@ -922,10 +941,10 @@ private: if (!createNew) return null; - auto m = new Module(toStringz(fname), null, false, false); + auto m = new Module(fname, null, false, false); if (pos < mModules.length) { - mErrors.remove(cast(void*)mModules[pos]); + mErrors.remove(fname); mModules[pos] = m; } else @@ -937,7 +956,7 @@ private: Options mOptions; Module[] mModules; - string[void*] mErrors; // cannot index by C++ class Module + string[string] mErrors; // cannot index by C++ class Module bool mSemanticExpansionsRunning; bool mSemanticTipRunning; @@ -961,19 +980,20 @@ __gshared char[] gErrorMessages; __gshared char[] gOtherErrorMessages; __gshared bool gErrorWasSupplemental; -extern(C++) -void verrorPrint(const ref Loc loc, Color headerColor, const(char)* header, - const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) +void errorPrint(const ref Loc loc, Color headerColor, const(char)* header, + const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) nothrow { if (!loc.filename) return; import dmd.errors; - synchronized(gErrorSync) + try synchronized(gErrorSync) { bool other = _stricmp(loc.filename, gErrorFile) != 0; - bool supplemental = (cast(Classification)headerColor == Classification.supplemental); + while (header && std.ascii.isWhite(*header)) + header++; + bool supplemental = !header && !*header; __gshared char[4096] buf; int len = 0; @@ -1026,6 +1046,10 @@ void verrorPrint(const ref Loc loc, Color headerColor, const(char)* header, gErrorWasSupplemental = supplemental; } } + catch(Exception e) + { + + } } void initErrorFile(string fname) @@ -1036,16 +1060,19 @@ void initErrorFile(string fname) gErrorMessages = null; gOtherErrorMessages = null; gErrorWasSupplemental = false; + + import std.functional; + diagnosticHandler = toDelegate(&errorPrint); } } -int _stricmp(const(char)*str1, string s2) +int _stricmp(const(char)*str1, string s2) nothrow { const(char)[] s1 = str1[0..strlen(str1)]; return icmp(s1, s2); } -int _stricmp(const(wchar)*str1, wstring s2) +int _stricmp(const(wchar)*str1, wstring s2) nothrow { const(wchar)[] s1 = str1[0..wcslen(str1)]; return icmp(s1, s2); @@ -1054,6 +1081,8 @@ int _stricmp(const(wchar)*str1, wstring s2) //////////////////////////////////////////////////////////////// version(all) // new mangling with dmd version >= 2.077 { + alias countersType = uint[uint]; // actually uint[Key] + enum string[2][] dmdStatics = [ ["_D3dmd5clone12buildXtoHashFCQBa7dstruct17StructDeclarationPSQCg6dscope5ScopeZ8tftohashCQDh5mtype12TypeFunction", "TypeFunction"], @@ -1069,6 +1098,14 @@ version(all) // new mangling with dmd version >= 2.077 ["_D3dmd9dtemplate16TemplateInstance16tryExpandMembersMFPSQCc6dscope5ScopeZ4nesti", "int"], ["_D3dmd9dtemplate16TemplateInstance12trySemantic3MFPSQBy6dscope5ScopeZ4nesti", "int"], ["_D3dmd13expressionsem25ExpressionSemanticVisitor5visitMRCQCd10expression7CallExpZ4nesti", "int"], + ["_D3dmd5lexer5Lexer12stringbufferSQBf4root9outbuffer9OutBuffer", "OutBuffer"], + ["_D3dmd10expression10IntegerExp__T7literalVii0ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], + ["_D3dmd10expression10IntegerExp__T7literalVii1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], + ["_D3dmd10expression10IntegerExp__T7literalViN1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], + ["_D3dmd10identifier10Identifier17generateIdWithLocFNbAyaKxSQCe7globals3LocZ8countersHSQDfQDeQCvQCmFNbQBwKxQBwZ3Keyk", "countersType"], + + + //["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ11visitAArrayMFCQEwQEc10TypeAArrayZ8fd_aaLenCQFz4func15FuncDeclaration", "FuncDeclaration"], //["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ8noMemberMFQDxQDmQCxQByiZ4nesti", "int"], ]; @@ -1171,8 +1208,7 @@ void clearDmdStatics() // static __gshared FuncDeclaration* fdapply = [null, null]; // static __gshared TypeDelegate* fldeTy = [null, null]; - // dmd.dinterpret - // ctfeStack = ctfeStack.init; + dinterpret_init(); // dmd.dtemplate emptyArrayElement = null; @@ -1258,6 +1294,10 @@ extern(C++) class ASTVisitor : StoppableVisitor { } + override void visit(ErrorInitializer einit) + { + } + override void visit(StructInitializer sinit) { foreach (i, const id; sinit.field) @@ -1492,7 +1532,7 @@ extern(C++) class FindASTVisitor : ASTVisitor return stop; } - bool matchIdentifier(ref Loc loc, Identifier ident) + bool matchIdentifier(ref const Loc loc, Identifier ident) { if (ident) if (loc.filename is filename) @@ -1665,7 +1705,7 @@ extern(C++) class FindTipVisitor : FindASTVisitor else buf.writestring(decl.toPrettyChars()); auto res = buf.peekSlice(); - buf.extractString(); // take ownership + buf.extractSlice(); // take ownership return cast(string)res; } @@ -1732,13 +1772,13 @@ RootObject _findAST(Dsymbol sym, const(char*) filename, int startLine, int start RootObject findAST(Module mod, int startLine, int startIndex, int endLine, int endIndex) { - auto filename = mod.srcfile.name.toChars(); + auto filename = mod.srcfile.toChars(); return _findAST(mod, filename, startLine, startIndex, endLine, endIndex); } string findTip(Module mod, int startLine, int startIndex, int endLine, int endIndex) { - auto filename = mod.srcfile.name.toChars(); + auto filename = mod.srcfile.toChars(); scope FindTipVisitor ftv = new FindTipVisitor(filename, startLine, startIndex, endLine, endIndex); mod.accept(ftv); @@ -1792,7 +1832,7 @@ extern(C++) class FindDefinitionVisitor : FindASTVisitor string findDefinition(Module mod, ref int line, ref int index) { - auto filename = mod.srcfile.name.toChars(); + auto filename = mod.srcfile.toChars(); scope FindDefinitionVisitor fdv = new FindDefinitionVisitor(filename, line, index, line, index + 1); mod.accept(fdv); diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index 5cab7d38..9d014c77 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -32,7 +32,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -45,10 +45,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c -cpp -Isrc;src\backend;src\tk;src\root -DMARS -e -wx -DTARGET_WINDOS=1 -DDM_TARGET_CPU_X86=1 @@ -86,10 +98,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -140,7 +153,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -153,10 +166,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c -cpp -Isrc;src\backend;src\tk;src\root -DMARS -e -wx -DTARGET_WINDOS=1 -DDM_TARGET_CPU_X86=1 @@ -194,10 +219,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -248,7 +274,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -261,10 +287,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -nologo -c -TP -Idmd\src -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\vcbuild -DTARGET_WINDOS=1 -FIwarnings.h @@ -302,10 +340,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -356,7 +395,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -369,10 +408,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -nologo -c -TP -Isrc -Isrc\backend -Isrc\tk -Isrc\root -Isrc\vcbuild -DTARGET_WINDOS=1 -FIvcbuild\warnings.h @@ -410,10 +461,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -464,7 +516,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -477,10 +529,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c -nologo -c -TP -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 @@ -518,10 +582,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -572,7 +637,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -585,17 +650,29 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c -nologo -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 1 0 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src ..\.. + dmd\src ..\.. $(DMDInstallDir)\src\druntime\src dmd dmd\res ..\..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -626,10 +703,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -680,7 +758,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -693,10 +771,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c -nologo -c -TP -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 @@ -734,10 +824,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -788,7 +879,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -801,10 +892,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c -nologo -c -TP -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 @@ -842,10 +945,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -896,7 +1000,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -909,10 +1013,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c -nologo -c -TP -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 @@ -950,10 +1066,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -1004,7 +1121,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -1017,10 +1134,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c -nologo -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 @@ -1058,10 +1187,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -1112,7 +1242,7 @@ 0 0 0 - 0 + 0 0 1 0 @@ -1125,10 +1255,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 c:\l\dmc\bin\dmc -c -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DMARS -e -wx -DTARGET_WINDOS=1 -DDM_TARGET_CPU_X86=1 @@ -1166,10 +1308,11 @@ 2 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 -s. + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -1220,7 +1363,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -1233,10 +1376,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -nologo -c -TP -Idmd\src -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\vcbuild -DTARGET_WINDOS=1 -FIwarnings.h @@ -1274,10 +1429,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -1297,7 +1453,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + @@ -1308,8 +1464,6 @@ - - @@ -1317,7 +1471,7 @@ - + @@ -1326,7 +1480,8 @@ - + + @@ -1367,10 +1522,11 @@ - + + @@ -1446,7 +1602,7 @@ - + diff --git a/vdc/ivdserver.idl b/vdc/ivdserver.idl index b63d0759..52e1af1c 100644 --- a/vdc/ivdserver.idl +++ b/vdc/ivdserver.idl @@ -34,7 +34,7 @@ interface IVDServer : IUnknown HRESULT GetIdentifierTypesResult([out, retval] BSTR* types); HRESULT GetDefinition([in] BSTR filename, [in] DWORD startLine, [in] DWORD startIndex, [in] DWORD endLine, [in] DWORD endIndex); HRESULT GetDefinitionResult([out] DWORD *startLine, [out] DWORD *startIndex, [out] DWORD *endLine, [out] DWORD *endIndex, [out,retval] BSTR* filename); - HRESULT GetReferences([in] BSTR filename, [in] BSTR tok, [in] DWORD line, [in] DWORD idx, [in] BSTR expr); + HRESULT GetReferences([in] BSTR filename, [in] BSTR tok, [in] DWORD line, [in] DWORD idx, [in] BSTR expr, [in] BOOL moduleOnly); HRESULT GetReferencesResult([out,retval] BSTR* stringList); HRESULT ConfigureCommentTasks([in] BSTR tasks); HRESULT GetCommentTasks([in] BSTR filename, [out,retval] BSTR* tasks); diff --git a/vdc/vdserver.idl b/vdc/vdserver.idl index 95c7b313..3c10aa06 100644 --- a/vdc/vdserver.idl +++ b/vdc/vdserver.idl @@ -10,7 +10,6 @@ import "oaidl.idl"; import "ivdserver.idl"; - HRESULT GetReferences([in] BSTR filename, [in] BSTR tok, [in] DWORD line, [in] DWORD idx, [in] BSTR expr, [in] BOOL moduleOnly); // library statement [uuid(002a2de9-8bb6-484d-9903-7e4ad4084715), version(1.0), helpstring("Visual D Semantic Server")] From edc1d53d18b2c7ce810adf5fac2256402d7d1137 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Thu, 25 Jul 2019 22:08:11 +0200 Subject: [PATCH 15/73] dmdserver: keep parsed AST, syntaxCopy before analyze --- build/build.visualdproj | 3 +- c2d/vsi2d.visualdproj | 6 +- vdc/dmdserver/ddmderrors.d | 106 +-- vdc/dmdserver/dmdserver.d | 1115 +++++++-------------------- vdc/dmdserver/dmdserver.visualdproj | 29 +- vdc/dmdserver/semvisitor.d | 670 ++++++++++++++++ vdc/vdserverfactory.d | 9 +- visuald_vs10.sln | 4 +- 8 files changed, 1050 insertions(+), 892 deletions(-) create mode 100644 vdc/dmdserver/semvisitor.d diff --git a/build/build.visualdproj b/build/build.visualdproj index 65156fb1..cf1695c2 100644 --- a/build/build.visualdproj +++ b/build/build.visualdproj @@ -628,6 +628,7 @@ dmd -map "$(IntDir)\$(InputName).map" "-of$(OutDir)\$(InputName). + +dmd -map $(OutDir)\$(InputName).map -of$(OutDir)\$(InputName).exe $(InputPath) ..\tools\nostacktrace.d" dependencies="..\tools\nostacktrace.d" outfile="$(OutDir)\$(InputName).exe" name="Release|Win32" /> = 2.077 -{ - alias countersType = uint[uint]; // actually uint[Key] +alias countersType = uint[uint]; // actually uint[Key] - enum string[2][] dmdStatics = - [ +enum string[2][] dmdStatics = +[ ["_D3dmd5clone12buildXtoHashFCQBa7dstruct17StructDeclarationPSQCg6dscope5ScopeZ8tftohashCQDh5mtype12TypeFunction", "TypeFunction"], ["_D3dmd7dstruct15search_toStringRCQBfQBe17StructDeclarationZ10tftostringCQCs5mtype12TypeFunction", "TypeFunction"], ["_D3dmd13expressionsem11loadStdMathFZ10impStdMathCQBv7dimport6Import", "Import"], @@ -1103,34 +1170,12 @@ version(all) // new mangling with dmd version >= 2.077 ["_D3dmd10expression10IntegerExp__T7literalVii1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], ["_D3dmd10expression10IntegerExp__T7literalViN1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], ["_D3dmd10identifier10Identifier17generateIdWithLocFNbAyaKxSQCe7globals3LocZ8countersHSQDfQDeQCvQCmFNbQBwKxQBwZ3Keyk", "countersType"], - - + ["_D3dmd10identifier10Identifier10generateIdRNbPxaZ1im", "int"], + ["_D3dmd5lexer5Lexer4scanMFNbPSQBb6tokens5TokenZ8initdoneb", "bool"], //["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ11visitAArrayMFCQEwQEc10TypeAArrayZ8fd_aaLenCQFz4func15FuncDeclaration", "FuncDeclaration"], //["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ8noMemberMFQDxQDmQCxQByiZ4nesti", "int"], - ]; -} -else -{ - enum string[2][] dmdStatics = - [ - ["D4ddmd5clone12buildXtoHashRC4ddmd7dstruct17StructDeclarationPS4ddmd6dscope5ScopeZ8tftohashC4ddmd5mtype12TypeFunction", "TypeFunction"], - ["D4ddmd7dstruct15search_toStringRC4ddmd7dstruct17StructDeclarationZ10tftostringC4ddmd5mtype12TypeFunction", "TypeFunction"], - ["D4ddmd10expression11loadStdMathRZ10impStdMathC4ddmd7dimport6Import", "Import"], - ["D4ddmd4func15FuncDeclaration8genCfuncRPS4ddmd4root5array33__T5ArrayTC4ddmd5mtype9ParameterZ5ArrayC4ddmd5mtype4TypeC4ddmd10identifier10IdentifiermZ2stC4ddmd7dsymbol12DsymbolTable", "DsymbolTable"], - ["D4ddmd5mtype10TypeAArray6dotExpMRPS4ddmd6dscope5ScopeC4ddmd10expression10ExpressionC4ddmd10identifier10IdentifieriZ8fd_aaLenC4ddmd4func15FuncDeclaration", "FuncDeclaration"], - ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ3feqC4ddmd4func15FuncDeclaration", "FuncDeclaration"], - ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ4fcmpC4ddmd4func15FuncDeclaration", "FuncDeclaration"], - ["D4ddmd7typesem19TypeSemanticVisitor5visitMRC4ddmd5mtype10TypeAArrayZ5fhashC4ddmd4func15FuncDeclaration", "FuncDeclaration"], - - ["D4ddmd7dmodule6Module19runDeferredSemanticRZ6nestedi", "int"], - ["D4ddmd10dsymbolsem22DsymbolSemanticVisitor5visitMRC4ddmd9dtemplate13TemplateMixinZ4nesti", "int"], - ["D4ddmd9dtemplate16TemplateInstance16tryExpandMembersMRPS4ddmd6dscope5ScopeZ4nesti", "int"], - ["D4ddmd9dtemplate16TemplateInstance12trySemantic3MRPS4ddmd6dscope5ScopeZ4nesti", "int"], - ["D4ddmd13expressionsem25ExpressionSemanticVisitor5visitMRC4ddmd10expression7CallExpZ4nesti", "int"], - ["D4ddmd5mtype4Type8noMemberMRPS4ddmd6dscope5ScopeC4ddmd10expression10ExpressionC4ddmd10identifier10IdentifieriZ4nesti", "int"], - ]; -} +]; string cmangled(string s) { @@ -1139,6 +1184,7 @@ string cmangled(string s) return "_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBuffermPmAxaZ4nesti"; return s; } + string genDeclDmdStatics() { string s; @@ -1157,7 +1203,13 @@ string genInitDmdStatics() mixin(genDeclDmdStatics); -void clearDmdStatics() +pragma(mangle, "_D3dmd12statementsem24StatementSemanticVisitor5visitMRCQCb9statement16ForeachStatementZ7fdapplyPCQDr4func15FuncDeclaration") +extern __gshared FuncDeclaration* statementsem_fdapply; +pragma(mangle, "_D3dmd12statementsem24StatementSemanticVisitor5visitMRCQCb9statement16ForeachStatementZ6fldeTyPCQDq5mtype12TypeDelegate") +extern __gshared TypeDelegate* statementsem_fldeTy; + + +void clearSemanticStatics() { /* import core.demangle; @@ -1166,683 +1218,116 @@ void clearDmdStatics() */ mixin(genInitDmdStatics); - Module.rootModule = null; - Module.modules = null; // symbol table of all modules - Module.amodules = Modules(); // array of all modules - Module.deferred = Dsymbols(); // deferred Dsymbol's needing semantic() run on them - Module.deferred2 = Dsymbols(); // deferred Dsymbol's needing semantic2() run on them - Module.deferred3 = Dsymbols(); // deferred Dsymbol's needing semantic3() run on them - Module.dprogress = 0; // progress resolving the deferred list - Module.moduleinfo = null; - - ClassDeclaration.object = null; - ClassDeclaration.throwable = null; - ClassDeclaration.exception = null; - ClassDeclaration.errorException = null; - ClassDeclaration.cpp_type_info_ptr = null; - - StructDeclaration.xerreq = null; - StructDeclaration.xerrcmp = null; - - Type.dtypeinfo = null; - Type.typeinfoclass = null; - Type.typeinfointerface = null; - Type.typeinfostruct = null; - Type.typeinfopointer = null; - Type.typeinfoarray = null; - Type.typeinfostaticarray = null; - Type.typeinfoassociativearray = null; - Type.typeinfovector = null; - Type.typeinfoenum = null; - Type.typeinfofunction = null; - Type.typeinfodelegate = null; - Type.typeinfotypelist = null; - Type.typeinfoconst = null; - Type.typeinfoinvariant = null; - Type.typeinfoshared = null; - Type.typeinfowild = null; - Type.rtinfo = null; - Type.stringtable.reset(); - // statementsem // static __gshared FuncDeclaration* fdapply = [null, null]; // static __gshared TypeDelegate* fldeTy = [null, null]; - - dinterpret_init(); + statementsem_fdapply[0] = statementsem_fdapply[1] = null; + statementsem_fldeTy[0] = statementsem_fldeTy[1] = null; // dmd.dtemplate emptyArrayElement = null; TemplateValueParameter.edummies = null; + TemplateTypeParameter.tdummy = null; + TemplateAliasParameter.sdummy = null; - Scope.freelist = null; - //Token.freelist = null; - - Identifier.initTable(); -} - -//////////////////////////////////////////////////////////////// -Loc endLoc(Dsymbol sym) -{ - return Loc(); -} - -// walk the complete AST (declarations, statement and expressions) -// assumes being started on module/declaration level -extern(C++) class ASTVisitor : StoppableVisitor -{ - alias visit = super.visit; - - void visitExpression(Expression expr) - { - if (stop || !expr) - return; - - if (walkPostorder(expr, this)) - stop = true; - } - - void visitStatement(Statement stmt) - { - if (stop || !stmt) - return; - - if (walkPostorder(stmt, this)) - stop = true; - } - - void visitDeclaration(Dsymbol sym) - { - if (stop || !sym) - return; - - sym.accept(this); - } - - // override void visit(Expression) {} - // override void visit(Parameter) {} - // override void visit(Statement) {} - // override void visit(Type) {} - // override void visit(TemplateParameter) {} - // override void visit(Condition) {} - // override void visit(Initializer) {} - - override void visit(ScopeDsymbol scopesym) - { - // optimize to only visit members in approriate source range - size_t mcnt = scopesym.members ? scopesym.members.dim : 0; - for (size_t m = 0; !stop && m < mcnt; m++) - { - Dsymbol s = (*scopesym.members)[m]; - s.accept(this); - } - } - - override void visit(VarDeclaration decl) - { - visit(cast(Declaration)decl); - - if (!stop && decl._init) - decl._init.accept(this); - } - - override void visit(ExpInitializer einit) - { - visitExpression(einit.exp); - } - - override void visit(VoidInitializer vinit) - { - } - - override void visit(ErrorInitializer einit) - { - } - - override void visit(StructInitializer sinit) - { - foreach (i, const id; sinit.field) - if (auto iz = sinit.value[i]) - iz.accept(this); - } - - override void visit(ArrayInitializer ainit) - { - foreach (i, ex; ainit.index) - { - if (ex) - ex.accept(this); - if (auto iz = ainit.value[i]) - iz.accept(this); - } - } - - override void visit(FuncDeclaration decl) - { - visit(cast(Declaration)decl); - - if (decl.parameters) - foreach(p; *decl.parameters) - if (!stop) - p.accept(this); - - visitStatement(decl.frequire); - visitStatement(decl.fensure); - visitStatement(decl.fbody); - } - - override void visit(ErrorStatement stmt) - { - visitStatement(stmt.errStmt); - if (!stop) - visit(cast(Statement)stmt); - } - - override void visit(ExpStatement stmt) - { - visitExpression(stmt.exp); - if (!stop) - visit(cast(Statement)stmt); - } + CtfeStatus.callDepth = 0; + CtfeStatus.stackTraceCallsToSuppress = 0; + CtfeStatus.maxCallDepth = 0; + CtfeStatus.numAssignments = 0; - override void visit(CompileStatement stmt) - { - if (stmt.exps) - foreach(e; *stmt.exps) - if (!stop) - e.accept(this); - if (!stop) - visit(cast(Statement)stmt); - } + VarDeclaration.nextSequenceNumber = 0; - override void visit(WhileStatement stmt) - { - visitExpression(stmt.condition); - if (!stop) - visit(cast(Statement)stmt); - } - - override void visit(DoStatement stmt) - { - visitExpression(stmt.condition); - if (!stop) - visit(cast(Statement)stmt); - } - - override void visit(ForStatement stmt) - { - visitExpression(stmt.condition); - visitExpression(stmt.increment); - if (!stop) - visit(cast(Statement)stmt); - } - - override void visit(ForeachStatement stmt) - { - if (stmt.parameters) - foreach(p; *stmt.parameters) - if (!stop) - p.accept(this); - visitExpression(stmt.aggr); - if (!stop) - visit(cast(Statement)stmt); - } - - override void visit(ForeachRangeStatement stmt) - { - if (!stop && stmt.prm) - stmt.prm.accept(this); - visitExpression(stmt.lwr); - visitExpression(stmt.upr); - if (!stop) - visit(cast(Statement)stmt); - } - - override void visit(IfStatement stmt) - { - if (!stop && stmt.prm) - stmt.prm.accept(this); - visitExpression(stmt.condition); - if (!stop) - visit(cast(Statement)stmt); - } - - override void visit(PragmaStatement stmt) - { - if (!stop && stmt.args) - foreach(a; *stmt.args) - if (!stop) - a.accept(this); - if (!stop) - visit(cast(Statement)stmt); - } - - override void visit(StaticAssertStatement stmt) - { - visitExpression(stmt.sa.exp); - visitExpression(stmt.sa.msg); - visit(cast(Statement)stmt); - } - - override void visit(SwitchStatement stmt) - { - visitExpression(stmt.condition); - visit(cast(Statement)stmt); - } - - override void visit(CaseStatement stmt) - { - visitExpression(stmt.exp); - visit(cast(Statement)stmt); - } - - override void visit(CaseRangeStatement stmt) - { - visitExpression(stmt.first); - visitExpression(stmt.last); - visit(cast(Statement)stmt); - } - - override void visit(GotoCaseStatement stmt) - { - visitExpression(stmt.exp); - visit(cast(Statement)stmt); - } - - override void visit(ReturnStatement stmt) - { - visitExpression(stmt.exp); - visit(cast(Statement)stmt); - } - - override void visit(SynchronizedStatement stmt) - { - visitExpression(stmt.exp); - visit(cast(Statement)stmt); - } - - override void visit(WithStatement stmt) - { - visitExpression(stmt.exp); - visit(cast(Statement)stmt); - } - - override void visit(TryCatchStatement stmt) - { - if (!stop && stmt.catches) - foreach(c; *stmt.catches) - visitDeclaration(c.var); - visit(cast(Statement)stmt); - } - - override void visit(ThrowStatement stmt) - { - visitExpression(stmt.exp); - visit(cast(Statement)stmt); - } - - override void visit(ImportStatement stmt) - { - if (!stop && stmt.imports) - foreach(i; *stmt.imports) - visitDeclaration(i); - visit(cast(Statement)stmt); - } + // Package.this.packageTag? + // funcDeclarationSemantic.printedMain? +/+ + Type.stringtable.reset(); - override void visit(DeclarationExp expr) - { - visitDeclaration(expr.declaration); - } + dinterpret_init(); - override void visit(ErrorExp expr) - { - visitExpression(expr.errExp); - if (!stop) - visit(cast(Expression)expr); - } + Scope.freelist = null; + //Token.freelist = null; + Identifier.initTable(); ++/ } -extern(C++) class FindASTVisitor : ASTVisitor +// initialization that are necessary once +void dmdInit() { - const(char*) filename; - int startLine; - int startIndex; - int endLine; - int endIndex; - - alias visit = super.visit; - RootObject found; - - this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) - { - this.filename = filename; - this.startLine = startLine; - this.startIndex = startIndex; - this.endLine = endLine; - this.endIndex = endIndex; - } - - bool foundNode(RootObject obj) - { - if (!obj) - { - found = obj; - stop = true; - } - return stop; - } - - bool matchIdentifier(ref const Loc loc, Identifier ident) - { - if (ident) - if (loc.filename is filename) - if (loc.linnum == startLine && loc.linnum == endLine) - if (loc.charnum <= startIndex && loc.charnum + ident.toString().length >= endIndex) - return true; - return false; - } - - bool matchLoc(ref Loc loc) - { - if (loc.filename is filename) - if (loc.linnum == startLine && loc.linnum == endLine) - if (loc.charnum <= startIndex /*&& loc.charnum + ident.toString().length >= endIndex*/) - return true; - return false; - } - - override void visit(Dsymbol sym) - { - if (!found && matchIdentifier(sym.loc, sym.ident)) - foundNode(sym); - } - - override void visit(Parameter sym) - { - //if (!found && matchIdentifier(sym.loc, sym.ident)) - // foundNode(sym); - } - - override void visit(ScopeDsymbol scopesym) - { - // optimize to only visit members in approriate source range - size_t mcnt = scopesym.members ? scopesym.members.dim : 0; - for (size_t m = 0; m < mcnt; m++) - { - Dsymbol s = (*scopesym.members)[m]; - if (s.isTemplateInstance) - continue; - if (s.loc.filename !is filename) - continue; - - if (s.loc.linnum > endLine || (s.loc.linnum == endLine && s.loc.charnum > endIndex)) - continue; - - Loc nextloc; - for (m++; m < mcnt; m++) - { - auto ns = (*scopesym.members)[m]; - if (ns.isTemplateInstance) - continue; - if (ns.loc.filename is filename) - { - nextloc = ns.loc; - break; - } - } - m--; - - if (nextloc.filename) - if (nextloc.linnum < startLine || (nextloc.linnum == startLine && nextloc.charnum < startIndex)) - continue; - - s.accept(this); - - if (!found) - foundNode(s); - break; - } - } - override void visit(TemplateInstance) - { - // skip members added by semantic - } - - override void visit(Statement stmt) - { - // default to nothing - } - - override void visit(CallExp expr) - { - super.visit(expr); - } - - override void visit(Expression expr) - { - // default to nothing - } - override void visit(SymbolExp expr) - { - if (!found && expr.var) - if (matchIdentifier(expr.loc, expr.var.ident)) - foundNode(expr); - } - override void visit(NewExp ne) - { - if (!found && matchLoc(ne.loc)) - if (ne.member) - foundNode(ne.member); - else - foundNode(ne.type); - } + __gshared bool initialized; + if (initialized) + return; + initialized = true; - override void visit(DotIdExp de) - { - if (!found && de.ident) - if (matchIdentifier(de.identloc, de.ident)) - foundNode(de); - } + import dmd.root.longdouble; + // Initialization + version(CRuntime_Microsoft) + initFPU(); - override void visit(DotTemplateExp dte) - { - if (!found && dte.td && dte.td.ident) - if (matchIdentifier(dte.identloc, dte.td.ident)) - foundNode(dte); - } + global.params.isWindows = true; + global._init(); + Token._init(); + Id.initialize(); + Expression._init(); + builtin_init(); - override void visit(TemplateExp te) - { - if (!found && te.td && te.td.ident) - if (matchIdentifier(te.identloc, te.td.ident)) - foundNode(te); - } - - override void visit(DotVarExp dve) - { - if (!found && dve.var && dve.var.ident) - if (matchIdentifier(dve.varloc, dve.var.ident)) - foundNode(dve); - } + dmdReinit(true); } -extern(C++) class FindTipVisitor : FindASTVisitor +// initialization that are necessary before restarting an analysis +void dmdReinit(bool configChanged) { - string tip; - - alias visit = super.visit; - - this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) - { - super(filename, startLine, startIndex, endLine, endIndex); - } - - void visitCallExpression(CallExp expr) + if (configChanged) { - if (!found) - { - // replace function type with actual - visitExpression(expr); - if (found is expr.e1) - { - foundNode(expr); - } - } - } - - override bool foundNode(RootObject obj) - { - found = obj; - if (obj) - { - string tipForDeclaration(Declaration decl) - { - if (auto func = decl.isFuncDeclaration()) - { - OutBuffer buf; - if (decl.type) - functionToBufferWithIdent(decl.type.toTypeFunction(), &buf, decl.toPrettyChars()); - else - buf.writestring(decl.toPrettyChars()); - auto res = buf.peekSlice(); - buf.extractSlice(); // take ownership - return cast(string)res; - } - - string txt; - if (decl.isParameter()) - txt = "(parameter) "; - else if (!decl.isDataseg() && !decl.isCodeseg() && !decl.isField()) - txt = "(local variable) "; - bool fqn = txt.empty; - - if (decl.type) - txt ~= to!string(decl.type.toPrettyChars()) ~ " "; - txt ~= to!string(fqn ? decl.toPrettyChars(fqn) : decl.toChars()); - return txt; - } - - const(char)* toc = null; - if (auto t = obj.isType()) - toc = t.toChars(); - else if (auto e = obj.isExpression()) - { - switch(e.op) - { - case TOK.variable: - case TOK.symbolOffset: - tip = tipForDeclaration((cast(SymbolExp)e).var); - break; - case TOK.dotVariable: - tip = tipForDeclaration((cast(DotVarExp)e).var); - break; - default: - if (e.type) - toc = e.type.toPrettyChars(); - break; - } - } - else if (auto s = obj.isDsymbol()) - { - if (auto decl = s.isDeclaration) - tip = tipForDeclaration(decl); - else - toc = s.toPrettyChars(true); - } - if (!tip.length) - { - if (!toc) - toc = obj.toChars(); - tip = to!string(toc); - } - // append doc - stop = true; - } - return stop; - } -} + target._init(global.params); // needed by Type._init + Type._init(); -RootObject _findAST(Dsymbol sym, const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) -{ - scope FindASTVisitor fav = new FindASTVisitor(filename, startLine, startIndex, endLine, endIndex); - sym.accept(fav); + // assume object.d unmodified otherwis + Module.moduleinfo = null; + + ClassDeclaration.object = null; + ClassDeclaration.throwable = null; + ClassDeclaration.exception = null; + ClassDeclaration.errorException = null; + ClassDeclaration.cpp_type_info_ptr = null; + + StructDeclaration.xerreq = null; + StructDeclaration.xerrcmp = null; + + Type.dtypeinfo = null; + Type.typeinfoclass = null; + Type.typeinfointerface = null; + Type.typeinfostruct = null; + Type.typeinfopointer = null; + Type.typeinfoarray = null; + Type.typeinfostaticarray = null; + Type.typeinfoassociativearray = null; + Type.typeinfovector = null; + Type.typeinfoenum = null; + Type.typeinfofunction = null; + Type.typeinfodelegate = null; + Type.typeinfotypelist = null; + Type.typeinfoconst = null; + Type.typeinfoinvariant = null; + Type.typeinfoshared = null; + Type.typeinfowild = null; + Type.rtinfo = null; + } + Objc._init(); + + Module._init(); + Module.deferred = Dsymbols(); // deferred Dsymbol's needing semantic() run on them + Module.deferred2 = Dsymbols(); // deferred Dsymbol's needing semantic2() run on them + Module.deferred3 = Dsymbols(); // deferred Dsymbol's needing semantic3() run on them + Module.dprogress = 0; // progress resolving the deferred list - return fav.found; -} + dinterpret_init(); -RootObject findAST(Module mod, int startLine, int startIndex, int endLine, int endIndex) -{ - auto filename = mod.srcfile.toChars(); - return _findAST(mod, filename, startLine, startIndex, endLine, endIndex); + clearSemanticStatics(); } -string findTip(Module mod, int startLine, int startIndex, int endLine, int endIndex) -{ - auto filename = mod.srcfile.toChars(); - scope FindTipVisitor ftv = new FindTipVisitor(filename, startLine, startIndex, endLine, endIndex); - mod.accept(ftv); - - return ftv.tip; -} //////////////////////////////////////////////////////////////// -extern(C++) class FindDefinitionVisitor : FindASTVisitor -{ - Loc loc; - - alias visit = super.visit; - - this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) - { - super(filename, startLine, startIndex, endLine, endIndex); - } - - override bool foundNode(RootObject obj) - { - found = obj; - if (obj) - { - if (auto t = obj.isType()) - { - if (t.ty == Tstruct) - loc = (cast(TypeStruct)t).sym.loc; - } - else if (auto e = obj.isExpression()) - { - switch(e.op) - { - case TOK.variable: - case TOK.symbolOffset: - loc = (cast(SymbolExp)e).var.loc; - break; - default: - loc = e.loc; - break; - } - } - else if (auto s = obj.isDsymbol()) - { - loc = s.loc; - } - stop = true; - } - return stop; - } -} - -string findDefinition(Module mod, ref int line, ref int index) -{ - auto filename = mod.srcfile.toChars(); - scope FindDefinitionVisitor fdv = new FindDefinitionVisitor(filename, line, index, line, index + 1); - mod.accept(fdv); - - if (!fdv.loc.filename) - return null; - line = fdv.loc.linnum; - index = fdv.loc.charnum; - return to!string(fdv.loc.filename); -} - extern(C) int _CrtDumpMemoryLeaks(); extern(C) void dumpGC(); @@ -1854,6 +1339,7 @@ unittest dumpGC(); DMDServer srv = newCom!DMDServer; + srv.mPredefineVersions = true; addref(srv); scope(exit) release(srv); @@ -1959,8 +1445,7 @@ unittest for (int i = 0; i < 2; i++) { srv.mModules = null; - srv.mErrors = null; - clearDmdStatics (); + //clearDmdStatics (); source = q{ import std.stdio; diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index 9d014c77..86949207 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -617,7 +617,7 @@ 0 0 0 - 0 + 1 0 1 1 @@ -706,7 +706,7 @@ 0 0 - 0 + 1 $(IntDir)\$(SafeProjectName).mixin @@ -1124,7 +1124,7 @@ 0 0 0 - 1 + 0 1 0 0 @@ -1156,7 +1156,7 @@ 1 0 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src ..\.. + dmd\src ..\.. $(DMDInstallDir)\src\druntime\src dmd dmd\res ..\..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -1204,7 +1204,7 @@ $(IntDir)\$(SafeProjectName).map 1 2 - 1 + 0 -L/STACK:8388608 -gf @@ -1277,7 +1277,7 @@ 1 0 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src ..\.. + dmd\src ..\.. $(DMDInstallDir)\src\druntime\src dmd dmd\res ..\..\bin\$(ConfigurationName) $(OutDir)\$(PlatformName)\$(ProjectName) @@ -1306,12 +1306,12 @@ 0 - 2 + 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe 0 0 -s. - 0 + 1 $(IntDir)\$(SafeProjectName).mixin @@ -1365,7 +1365,7 @@ 0 0 0 - 0 + 1 0 0 0 @@ -1398,7 +1398,7 @@ 1 1 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src ..\.. + dmd\src ..\.. $(DMDInstallDir)\src\druntime\src dmd dmd\res ..\..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -1419,7 +1419,7 @@ 0 MARS NoBackend 0 - 0 + 3 0 0 @@ -1432,11 +1432,11 @@ 0 0 - 0 + 1 $(IntDir)\$(SafeProjectName).mixin - + ole32.lib oleaut32.lib @@ -1483,7 +1483,7 @@ - + @@ -1621,6 +1621,7 @@ if exist "%WindowsSdkDir%\bin\%WindowsSDKVersion%x86\rc.exe" set rc=&q %rc% /fo"$(OutDir)\$(InputName).res" /I"$(IntDir)" $(InputPath)" dependencies=""$(IntDir)\dmdserver.tlb" ..\..\version" outfile="$(OutDir)\dmdserver.res" path="dmdserver.rc" linkoutput="true" tool="Custom" /> + diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d new file mode 100644 index 00000000..d916584c --- /dev/null +++ b/vdc/dmdserver/semvisitor.d @@ -0,0 +1,670 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2012 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +module vdc.semvisitor; + +import vdc.semanticopt; + +import dmd.apply; +import dmd.arraytypes; +import dmd.builtin; +import dmd.cond; +import dmd.console; +import dmd.dclass; +import dmd.declaration; +import dmd.dimport; +import dmd.dinterpret; +import dmd.dmodule; +import dmd.dscope; +import dmd.dstruct; +import dmd.dsymbol; +import dmd.dsymbolsem; +import dmd.dtemplate; +import dmd.errors; +import dmd.expression; +import dmd.func; +import dmd.globals; +import dmd.hdrgen; +import dmd.id; +import dmd.identifier; +import dmd.init; +import dmd.mtype; +import dmd.objc; +import dmd.sapply; +import dmd.semantic2; +import dmd.semantic3; +import dmd.statement; +import dmd.target; +import dmd.tokens; +import dmd.visitor; + +import dmd.root.outbuffer; +import dmd.root.file; +import dmd.root.filename; +import dmd.root.rmem; +import dmd.root.rootobject; + +import std.string; +import std.conv; + +// walk the complete AST (declarations, statement and expressions) +// assumes being started on module/declaration level +extern(C++) class ASTVisitor : StoppableVisitor +{ + alias visit = super.visit; + + void visitExpression(Expression expr) + { + if (stop || !expr) + return; + + if (walkPostorder(expr, this)) + stop = true; + } + + void visitStatement(Statement stmt) + { + if (stop || !stmt) + return; + + if (walkPostorder(stmt, this)) + stop = true; + } + + void visitDeclaration(Dsymbol sym) + { + if (stop || !sym) + return; + + sym.accept(this); + } + + // override void visit(Expression) {} + // override void visit(Parameter) {} + // override void visit(Statement) {} + // override void visit(Type) {} + // override void visit(TemplateParameter) {} + // override void visit(Condition) {} + // override void visit(Initializer) {} + + override void visit(ScopeDsymbol scopesym) + { + // optimize to only visit members in approriate source range + size_t mcnt = scopesym.members ? scopesym.members.dim : 0; + for (size_t m = 0; !stop && m < mcnt; m++) + { + Dsymbol s = (*scopesym.members)[m]; + s.accept(this); + } + } + + override void visit(VarDeclaration decl) + { + visit(cast(Declaration)decl); + + if (!stop && decl._init) + decl._init.accept(this); + } + + override void visit(ExpInitializer einit) + { + visitExpression(einit.exp); + } + + override void visit(VoidInitializer vinit) + { + } + + override void visit(ErrorInitializer einit) + { + } + + override void visit(StructInitializer sinit) + { + foreach (i, const id; sinit.field) + if (auto iz = sinit.value[i]) + iz.accept(this); + } + + override void visit(ArrayInitializer ainit) + { + foreach (i, ex; ainit.index) + { + if (ex) + ex.accept(this); + if (auto iz = ainit.value[i]) + iz.accept(this); + } + } + + override void visit(FuncDeclaration decl) + { + visit(cast(Declaration)decl); + + if (decl.parameters) + foreach(p; *decl.parameters) + if (!stop) + p.accept(this); + + visitStatement(decl.frequire); + visitStatement(decl.fensure); + visitStatement(decl.fbody); + } + + override void visit(ErrorStatement stmt) + { + visitStatement(stmt.errStmt); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(ExpStatement stmt) + { + visitExpression(stmt.exp); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(CompileStatement stmt) + { + if (stmt.exps) + foreach(e; *stmt.exps) + if (!stop) + e.accept(this); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(WhileStatement stmt) + { + visitExpression(stmt.condition); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(DoStatement stmt) + { + visitExpression(stmt.condition); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(ForStatement stmt) + { + visitExpression(stmt.condition); + visitExpression(stmt.increment); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(ForeachStatement stmt) + { + if (stmt.parameters) + foreach(p; *stmt.parameters) + if (!stop) + p.accept(this); + visitExpression(stmt.aggr); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(ForeachRangeStatement stmt) + { + if (!stop && stmt.prm) + stmt.prm.accept(this); + visitExpression(stmt.lwr); + visitExpression(stmt.upr); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(IfStatement stmt) + { + if (!stop && stmt.prm) + stmt.prm.accept(this); + visitExpression(stmt.condition); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(PragmaStatement stmt) + { + if (!stop && stmt.args) + foreach(a; *stmt.args) + if (!stop) + a.accept(this); + if (!stop) + visit(cast(Statement)stmt); + } + + override void visit(StaticAssertStatement stmt) + { + visitExpression(stmt.sa.exp); + visitExpression(stmt.sa.msg); + visit(cast(Statement)stmt); + } + + override void visit(SwitchStatement stmt) + { + visitExpression(stmt.condition); + visit(cast(Statement)stmt); + } + + override void visit(CaseStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(CaseRangeStatement stmt) + { + visitExpression(stmt.first); + visitExpression(stmt.last); + visit(cast(Statement)stmt); + } + + override void visit(GotoCaseStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(ReturnStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(SynchronizedStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(WithStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(TryCatchStatement stmt) + { + if (!stop && stmt.catches) + foreach(c; *stmt.catches) + visitDeclaration(c.var); + visit(cast(Statement)stmt); + } + + override void visit(ThrowStatement stmt) + { + visitExpression(stmt.exp); + visit(cast(Statement)stmt); + } + + override void visit(ImportStatement stmt) + { + if (!stop && stmt.imports) + foreach(i; *stmt.imports) + visitDeclaration(i); + visit(cast(Statement)stmt); + } + + override void visit(DeclarationExp expr) + { + visitDeclaration(expr.declaration); + } + + override void visit(ErrorExp expr) + { + visitExpression(expr.errExp); + if (!stop) + visit(cast(Expression)expr); + } + +} + +extern(C++) class FindASTVisitor : ASTVisitor +{ + const(char*) filename; + int startLine; + int startIndex; + int endLine; + int endIndex; + + alias visit = super.visit; + RootObject found; + + this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) + { + this.filename = filename; + this.startLine = startLine; + this.startIndex = startIndex; + this.endLine = endLine; + this.endIndex = endIndex; + } + + bool foundNode(RootObject obj) + { + if (!obj) + { + found = obj; + stop = true; + } + return stop; + } + + bool matchIdentifier(ref const Loc loc, Identifier ident) + { + if (ident) + if (loc.filename is filename) + if (loc.linnum == startLine && loc.linnum == endLine) + if (loc.charnum <= startIndex && loc.charnum + ident.toString().length >= endIndex) + return true; + return false; + } + + bool matchLoc(ref Loc loc) + { + if (loc.filename is filename) + if (loc.linnum == startLine && loc.linnum == endLine) + if (loc.charnum <= startIndex /*&& loc.charnum + ident.toString().length >= endIndex*/) + return true; + return false; + } + + override void visit(Dsymbol sym) + { + if (!found && matchIdentifier(sym.loc, sym.ident)) + foundNode(sym); + } + + override void visit(Parameter sym) + { + //if (!found && matchIdentifier(sym.loc, sym.ident)) + // foundNode(sym); + } + + override void visit(ScopeDsymbol scopesym) + { + // optimize to only visit members in approriate source range + size_t mcnt = scopesym.members ? scopesym.members.dim : 0; + for (size_t m = 0; m < mcnt; m++) + { + Dsymbol s = (*scopesym.members)[m]; + if (s.isTemplateInstance) + continue; + if (s.loc.filename !is filename) + continue; + + if (s.loc.linnum > endLine || (s.loc.linnum == endLine && s.loc.charnum > endIndex)) + continue; + + Loc nextloc; + for (m++; m < mcnt; m++) + { + auto ns = (*scopesym.members)[m]; + if (ns.isTemplateInstance) + continue; + if (ns.loc.filename is filename) + { + nextloc = ns.loc; + break; + } + } + m--; + + if (nextloc.filename) + if (nextloc.linnum < startLine || (nextloc.linnum == startLine && nextloc.charnum < startIndex)) + continue; + + s.accept(this); + + if (!found) + foundNode(s); + break; + } + } + override void visit(TemplateInstance) + { + // skip members added by semantic + } + + override void visit(Statement stmt) + { + // default to nothing + } + + override void visit(CallExp expr) + { + super.visit(expr); + } + + override void visit(Expression expr) + { + // default to nothing + } + override void visit(SymbolExp expr) + { + if (!found && expr.var) + if (matchIdentifier(expr.loc, expr.var.ident)) + foundNode(expr); + } + override void visit(NewExp ne) + { + if (!found && matchLoc(ne.loc)) + if (ne.member) + foundNode(ne.member); + else + foundNode(ne.type); + } + + override void visit(DotIdExp de) + { + if (!found && de.ident) + if (matchIdentifier(de.identloc, de.ident)) + foundNode(de); + } + + override void visit(DotTemplateExp dte) + { + if (!found && dte.td && dte.td.ident) + if (matchIdentifier(dte.identloc, dte.td.ident)) + foundNode(dte); + } + + override void visit(TemplateExp te) + { + if (!found && te.td && te.td.ident) + if (matchIdentifier(te.identloc, te.td.ident)) + foundNode(te); + } + + override void visit(DotVarExp dve) + { + if (!found && dve.var && dve.var.ident) + if (matchIdentifier(dve.varloc, dve.var.ident)) + foundNode(dve); + } +} + +extern(C++) class FindTipVisitor : FindASTVisitor +{ + string tip; + + alias visit = super.visit; + + this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) + { + super(filename, startLine, startIndex, endLine, endIndex); + } + + void visitCallExpression(CallExp expr) + { + if (!found) + { + // replace function type with actual + visitExpression(expr); + if (found is expr.e1) + { + foundNode(expr); + } + } + } + + override bool foundNode(RootObject obj) + { + found = obj; + if (obj) + { + string tipForDeclaration(Declaration decl) + { + if (auto func = decl.isFuncDeclaration()) + { + OutBuffer buf; + if (decl.type) + functionToBufferWithIdent(decl.type.toTypeFunction(), &buf, decl.toPrettyChars()); + else + buf.writestring(decl.toPrettyChars()); + auto res = buf.peekSlice(); + buf.extractSlice(); // take ownership + return cast(string)res; + } + + string txt; + if (decl.isParameter()) + txt = "(parameter) "; + else if (!decl.isDataseg() && !decl.isCodeseg() && !decl.isField()) + txt = "(local variable) "; + bool fqn = txt.empty; + + if (decl.type) + txt ~= to!string(decl.type.toPrettyChars()) ~ " "; + txt ~= to!string(fqn ? decl.toPrettyChars(fqn) : decl.toChars()); + return txt; + } + + const(char)* toc = null; + if (auto t = obj.isType()) + toc = t.toChars(); + else if (auto e = obj.isExpression()) + { + switch(e.op) + { + case TOK.variable: + case TOK.symbolOffset: + tip = tipForDeclaration((cast(SymbolExp)e).var); + break; + case TOK.dotVariable: + tip = tipForDeclaration((cast(DotVarExp)e).var); + break; + default: + if (e.type) + toc = e.type.toPrettyChars(); + break; + } + } + else if (auto s = obj.isDsymbol()) + { + if (auto decl = s.isDeclaration) + tip = tipForDeclaration(decl); + else + toc = s.toPrettyChars(true); + } + if (!tip.length) + { + if (!toc) + toc = obj.toChars(); + tip = to!string(toc); + } + // append doc + stop = true; + } + return stop; + } +} + +RootObject _findAST(Dsymbol sym, const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) +{ + scope FindASTVisitor fav = new FindASTVisitor(filename, startLine, startIndex, endLine, endIndex); + sym.accept(fav); + + return fav.found; +} + +RootObject findAST(Module mod, int startLine, int startIndex, int endLine, int endIndex) +{ + auto filename = mod.srcfile.toChars(); + return _findAST(mod, filename, startLine, startIndex, endLine, endIndex); +} + +string findTip(Module mod, int startLine, int startIndex, int endLine, int endIndex) +{ + auto filename = mod.srcfile.toChars(); + scope FindTipVisitor ftv = new FindTipVisitor(filename, startLine, startIndex, endLine, endIndex); + mod.accept(ftv); + + return ftv.tip; +} +//////////////////////////////////////////////////////////////// + +extern(C++) class FindDefinitionVisitor : FindASTVisitor +{ + Loc loc; + + alias visit = super.visit; + + this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) + { + super(filename, startLine, startIndex, endLine, endIndex); + } + + override bool foundNode(RootObject obj) + { + found = obj; + if (obj) + { + if (auto t = obj.isType()) + { + if (t.ty == Tstruct) + loc = (cast(TypeStruct)t).sym.loc; + } + else if (auto e = obj.isExpression()) + { + switch(e.op) + { + case TOK.variable: + case TOK.symbolOffset: + loc = (cast(SymbolExp)e).var.loc; + break; + default: + loc = e.loc; + break; + } + } + else if (auto s = obj.isDsymbol()) + { + loc = s.loc; + } + stop = true; + } + return stop; + } +} + +string findDefinition(Module mod, ref int line, ref int index) +{ + auto filename = mod.srcfile.toChars(); + scope FindDefinitionVisitor fdv = new FindDefinitionVisitor(filename, line, index, line, index + 1); + mod.accept(fdv); + + if (!fdv.loc.filename) + return null; + line = fdv.loc.linnum; + index = fdv.loc.charnum; + return to!string(fdv.loc.filename); +} diff --git a/vdc/vdserverfactory.d b/vdc/vdserverfactory.d index a74f969a..b8985152 100644 --- a/vdc/vdserverfactory.d +++ b/vdc/vdserverfactory.d @@ -53,9 +53,10 @@ static ~this() class VDServerClassFactory : ComObject, IClassFactory { - version(MARS) static GUID iid = uuid("002a2de9-8bb6-484d-9906-7e4ad4084715"); - else debug static GUID iid = uuid("002a2de9-8bb6-484d-9A02-7e4ad4084715"); - else static GUID iid = uuid("002a2de9-8bb6-484d-9902-7e4ad4084715"); + version(MARS) static immutable GUID iid = uuid("002a2de9-8bb6-484d-9906-7e4ad4084715"); + else debug static immutable GUID iid = uuid("002a2de9-8bb6-484d-9A02-7e4ad4084715"); + else debug static immutable GUID iid = uuid("002a2de9-8bb6-484d-9902-7e4ad4084715"); + else static immutable GUID iid = uuid("002a2de9-8bb6-484d-9A02-7e4ad4084715"); override HRESULT QueryInterface(in IID* riid, void** pvObject) { @@ -106,7 +107,7 @@ extern(C) int vdserver_main() // Register the Factory. DWORD regID = 0; - hr = CoRegisterClassObject(VDServerClassFactory.iid, cf, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, ®ID); + hr = CoRegisterClassObject(*cast(GUID*)&VDServerClassFactory.iid, cf, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, ®ID); if(FAILED(hr)) { ShowErrorMessage("CoRegisterClassObject()", hr); diff --git a/visuald_vs10.sln b/visuald_vs10.sln index 9519fc3c..ca8c0bbf 100644 --- a/visuald_vs10.sln +++ b/visuald_vs10.sln @@ -666,8 +666,8 @@ Global {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.Test|x64.Build.0 = Release|x64 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|Win32.ActiveCfg = TestDebug|Win32 {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|Win32.Build.0 = TestDebug|Win32 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|x64.ActiveCfg = Debug|x64 - {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|x64.Build.0 = Debug|x64 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|x64.ActiveCfg = TestDebug|x64 + {34289BD7-AB7E-4264-B146-8139DDE9F0BF}.TestDebug|x64.Build.0 = TestDebug|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 0acdb80ba506e1a39bb419755c24c1cbafb6f16f Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Tue, 30 Jul 2019 22:03:47 +0200 Subject: [PATCH 16/73] dmdserver: tweak reinit, ASTVisitor cleanup projects --- vdc/dmdserver/dmdserver.d | 28 +-- vdc/dmdserver/dmdserver.visualdproj | 2 +- vdc/dmdserver/semvisitor.d | 111 ++++++++-- vdc/parser.visualdproj | 6 +- vdc/vdserver.visualdproj | 322 ++++++++++++++++++++++------ vdc/vdserverfactory.d | 2 +- 6 files changed, 369 insertions(+), 102 deletions(-) diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index f12d25fd..faa0844a 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -6,8 +6,8 @@ // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt -module vdc.dmdserver; -import vdc.semvisitor; +module vdc.dmdserver.dmdserver; +import vdc.dmdserver.semvisitor; version(MAIN) {} else version = noServer; @@ -100,7 +100,7 @@ import core.stdc.string; // version = traceGC; version (traceGC) import tracegc; -debug version = DebugServer; +version = DebugServer; //debug version = vdlog; // log through visual D logging (needs version = InProc in vdserverclient) shared(Object) gDMDSync = new Object; // no multi-instances/multi-threading with DMD @@ -898,15 +898,7 @@ class DMDServer : ComObject, IVDServer global.filePath.push(toStringz(i)); } - //Id.initialize(); - Type._reinit(); - Module._init(); - Module.amodules = Module.amodules.init; - //Expression._init(); - //Objc._init(); - //builtin_init(); - - target._init(global.params); + dmdReinit(true); for (size_t i = 0; i < mModules.length; i++) { @@ -919,6 +911,10 @@ class DMDServer : ComObject, IVDServer Module.modules.insert(m); } Module.rootModule = rootModule.analyzedModule; + Module.loadModuleHandler = (const ref Loc location, Identifiers* packages, Identifier ident) + { + return Module.loadFromFile(location, packages, ident); + }; for (size_t i = 0; i < mModules.length; i++) { @@ -1049,7 +1045,7 @@ __gshared char[] gErrorMessages; __gshared char[] gOtherErrorMessages; __gshared bool gErrorWasSupplemental; -void errorPrint(const ref Loc loc, Color headerColor, const(char)* header, +void errorPrint(const ref Loc loc, Color headerColor, const(char)* header, const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) nothrow { if (!loc.filename) @@ -1271,6 +1267,9 @@ void dmdInit() Expression._init(); builtin_init(); + target._init(global.params); // needed by Type._init + Type._init(); + dmdReinit(true); } @@ -1280,7 +1279,7 @@ void dmdReinit(bool configChanged) if (configChanged) { target._init(global.params); // needed by Type._init - Type._init(); + Type._reinit(); // assume object.d unmodified otherwis Module.moduleinfo = null; @@ -1316,6 +1315,7 @@ void dmdReinit(bool configChanged) Objc._init(); Module._init(); + Module.amodules = Module.amodules.init; Module.deferred = Dsymbols(); // deferred Dsymbol's needing semantic() run on them Module.deferred2 = Dsymbols(); // deferred Dsymbol's needing semantic2() run on them Module.deferred3 = Dsymbols(); // deferred Dsymbol's needing semantic3() run on them diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index 86949207..d3a746c9 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -671,7 +671,7 @@ $(CC) -c -nologo -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 1 0 - c:\l\d\dmd2\windows\bin\dmd.exe + dmd\src ..\.. $(DMDInstallDir)\src\druntime\src dmd dmd\res ..\..\bin\$(ConfigurationName)\$(PlatformName) diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index d916584c..a8a60149 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -6,12 +6,14 @@ // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt -module vdc.semvisitor; +module vdc.dmdserver.semvisitor; import vdc.semanticopt; +import dmd.aggregate; import dmd.apply; import dmd.arraytypes; +import dmd.attrib; import dmd.builtin; import dmd.cond; import dmd.console; @@ -111,6 +113,29 @@ extern(C++) class ASTVisitor : StoppableVisitor decl._init.accept(this); } + override void visit(AttribDeclaration decl) + { + visit(cast(Declaration)decl); + + if (!stop) + if (auto inc = decl.include(null)) + foreach(d; *inc) + if (!stop) + d.accept(this); + } + + override void visit(ConditionalDeclaration decl) + { + if (!stop && decl.condition) + decl.condition.accept(this); + + visit(cast(AttribDeclaration)decl); + } + + override void visit(Condition) + { + } + override void visit(ExpInitializer einit) { visitExpression(einit.exp); @@ -389,44 +414,50 @@ extern(C++) class FindASTVisitor : ASTVisitor // foundNode(sym); } + override void visit(DVCondition cond) + { + if (!found && matchIdentifier(cond.loc, cond.ident)) + foundNode(cond); + } + + version(none) override void visit(ScopeDsymbol scopesym) { // optimize to only visit members in approriate source range + // unfortunately, some members don't have valid locations size_t mcnt = scopesym.members ? scopesym.members.dim : 0; + size_t minMember = 0; + size_t maxMember = mcnt; for (size_t m = 0; m < mcnt; m++) { Dsymbol s = (*scopesym.members)[m]; if (s.isTemplateInstance) continue; - if (s.loc.filename !is filename) - continue; - - if (s.loc.linnum > endLine || (s.loc.linnum == endLine && s.loc.charnum > endIndex)) - continue; - - Loc nextloc; - for (m++; m < mcnt; m++) + if (s.loc.filename) { - auto ns = (*scopesym.members)[m]; - if (ns.isTemplateInstance) + if (s.loc.filename !is filename) continue; - if (ns.loc.filename is filename) + + if (s.loc.linnum > endLine || (s.loc.linnum == endLine && s.loc.charnum > endIndex)) { - nextloc = ns.loc; + maxMember = m; break; } + if (s.loc.linnum < startLine || (s.loc.linnum == startLine && s.loc.charnum < startIndex)) + minMember = m; } - m--; + } - if (nextloc.filename) - if (nextloc.linnum < startLine || (nextloc.linnum == startLine && nextloc.charnum < startIndex)) - continue; + for (size_t m = minMember; m < maxMember; m++) + { + Dsymbol s = (*scopesym.members)[m]; + if (s.loc.filename && s.loc.filename !is filename) + continue; s.accept(this); - if (!found) - foundNode(s); - break; + if (found) + break; } } override void visit(TemplateInstance) @@ -490,6 +521,46 @@ extern(C++) class FindASTVisitor : ASTVisitor if (matchIdentifier(dve.varloc, dve.var.ident)) foundNode(dve); } + + override void visit(AggregateDeclaration ad) + { + visit(cast(ScopeDsymbol)ad); + } + + override void visit(ClassDeclaration cd) + { + if (cd.baseclasses) + { + foreach (bc; *(cd.baseclasses)) + { + if (bc.originalType && bc.originalType.ty == Tident) + { + visitTypeIdentifier(cast(TypeIdentifier) bc.originalType, bc.type); + } + } + } + visit(cast(AggregateDeclaration)cd); + } + + void visitTypeIdentifier(TypeIdentifier originalType, Type resolvedType) + { + Loc loc = originalType.loc; + if (matchIdentifier(loc, originalType.ident)) + foundNode(resolvedType); + + // guess qualified name to be without spaces + loc.charnum += originalType.ident.toString().length + 1; + foreach (id; originalType.idents) + { + if (id.dyncast() == DYNCAST.identifier) + { + auto ident = cast(Identifier)id; + if (matchIdentifier(loc, ident)) + foundNode(resolvedType); + loc.charnum += ident.toString().length + 1; + } + } + } } extern(C++) class FindTipVisitor : FindASTVisitor diff --git a/vdc/parser.visualdproj b/vdc/parser.visualdproj index 966845ef..75a2505e 100644 --- a/vdc/parser.visualdproj +++ b/vdc/parser.visualdproj @@ -1397,7 +1397,7 @@ $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. . ..\bin\$(ConfigurationName)\$(PlatformName) @@ -1877,11 +1877,11 @@ 0 0 0 - 1 + 0 $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. . ..\bin\$(ConfigurationName) diff --git a/vdc/vdserver.visualdproj b/vdc/vdserver.visualdproj index ccee8e7f..4730d198 100644 --- a/vdc/vdserver.visualdproj +++ b/vdc/vdserver.visualdproj @@ -1,6 +1,6 @@ {2F75431E-B8DB-4231-AAC1-EA68D06A22E6} - + 0 0 0 @@ -15,6 +15,7 @@ 0 0 1 + 1 0 0 0 @@ -31,7 +32,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -44,10 +45,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -85,10 +98,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -107,7 +121,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -122,6 +136,7 @@ 0 0 0 + 1 0 0 0 @@ -138,7 +153,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -151,10 +166,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -192,10 +219,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -214,7 +242,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -229,6 +257,7 @@ 0 0 1 + 1 0 0 1 @@ -245,7 +274,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -258,10 +287,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -299,10 +340,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -321,7 +363,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -336,6 +378,7 @@ 0 0 0 + 1 0 0 1 @@ -352,7 +395,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -365,10 +408,22 @@ 0 0 0 - 2.043 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -406,10 +461,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin @@ -428,7 +484,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -443,6 +499,7 @@ 0 0 0 + 1 0 0 0 @@ -459,7 +516,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -472,10 +529,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 1 0 $(CC) -c @@ -513,10 +582,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -535,7 +605,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -550,6 +620,7 @@ 0 0 1 + 1 0 0 1 @@ -566,7 +637,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -579,10 +650,22 @@ 0 0 0 - 2.043 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 1 0 $(CC) -c @@ -620,10 +703,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -642,7 +726,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -657,6 +741,7 @@ 0 0 0 + 1 0 0 0 @@ -673,7 +758,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -686,10 +771,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -727,10 +824,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -749,7 +847,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -764,6 +862,7 @@ 0 0 1 + 1 0 0 1 @@ -780,7 +879,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -793,10 +892,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -834,10 +945,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -856,7 +968,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -871,6 +983,7 @@ 0 0 1 + 1 0 0 0 @@ -887,7 +1000,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -900,10 +1013,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -941,10 +1066,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -963,7 +1089,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -978,6 +1104,7 @@ 0 0 1 + 1 0 0 1 @@ -994,7 +1121,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -1007,10 +1134,22 @@ 0 0 0 - 2.043 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -1048,10 +1187,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -1070,7 +1210,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -1085,6 +1225,7 @@ 0 0 0 + 1 1 0 0 @@ -1101,7 +1242,7 @@ 0 0 0 - 1 + 3 0 0 1 @@ -1114,10 +1255,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -1155,10 +1308,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -1177,7 +1331,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -1192,6 +1346,7 @@ 0 0 1 + 1 0 0 1 @@ -1208,7 +1363,7 @@ 0 0 0 - 0 + 0 0 0 0 @@ -1221,10 +1376,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 2 0 $(CC) -c @@ -1262,10 +1429,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -1284,7 +1452,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -1299,6 +1467,7 @@ 0 0 1 + 1 1 0 0 @@ -1315,7 +1484,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -1328,10 +1497,22 @@ 0 0 0 - 2 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 0 $(CC) -c @@ -1369,10 +1550,11 @@ 0 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -1391,7 +1573,7 @@ *.obj;*.cmd;*.build;*.json;*.dep - + 0 0 0 @@ -1406,6 +1588,7 @@ 0 0 1 + 1 1 0 1 @@ -1422,7 +1605,7 @@ 0 0 0 - 0 + 0 0 0 1 @@ -1435,16 +1618,28 @@ 0 0 0 - 2.043 0 0 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 0 - 1 + 0 $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. ..\bin\$(ConfigurationName) @@ -1476,10 +1671,11 @@ 1 $(VisualDInstallDir)cv2pdb\cv2pdb.exe - 0 0 0 + 0 + $(IntDir)\$(SafeProjectName).mixin ole32.lib oleaut32.lib @@ -1500,16 +1696,16 @@ - - + +rc /fo"$(OutDir)\vdserver.res" "/I$(OutDir)" $(InputPath)" dependencies=""$(OutDir)\vdserver.tlb" ..\version" outfile="$(OutDir)\vdserver.res" path="vdserver.rc" linkoutput="true" tool="Custom" /> - + diff --git a/vdc/vdserverfactory.d b/vdc/vdserverfactory.d index b8985152..8f8ef1ad 100644 --- a/vdc/vdserverfactory.d +++ b/vdc/vdserverfactory.d @@ -11,7 +11,7 @@ module vdc.vdserverfactory; import vdc.ivdserver; version(MARS) { - import vdc.dmdserver; + import vdc.dmdserver.dmdserver; alias VDServer = DMDServer; } else From 9e4f54b80e496c666a6d4c4ea31439fa780dc97f Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Thu, 1 Aug 2019 20:31:09 +0200 Subject: [PATCH 17/73] dmdserver: tweak AST finder, tooltips, goto def improve module cloning --- vdc/dmdserver/dmdserver.d | 15 +++-- vdc/dmdserver/semvisitor.d | 123 ++++++++++++++++++++++++++++--------- 2 files changed, 100 insertions(+), 38 deletions(-) diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index faa0844a..ed133f91 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -501,9 +501,9 @@ class DMDServer : ComObject, IVDServer string fname = makeFilenameCanonical(to_string(filename), null); mDefSpan.start.line = startLine; - mDefSpan.start.index = startIndex; + mDefSpan.start.index = startIndex + 1; mDefSpan.end.line = endLine; - mDefSpan.end.index = endIndex; + mDefSpan.end.index = endIndex + 1; ModuleData* md; synchronized(gErrorSync) @@ -555,9 +555,9 @@ class DMDServer : ComObject, IVDServer version(DebugServer) dbglog("GetDefinitionResult: " ~ mLastDefFile); writeReadyMessage(); startLine = mDefSpan.start.line; - startIndex = mDefSpan.start.index; + startIndex = mDefSpan.start.index - 1; endLine = mDefSpan.start.line; - endIndex = mDefSpan.start.index + 1; + endIndex = mDefSpan.start.index; *answer = allocBSTR(mLastDefFile); return S_OK; } @@ -902,12 +902,11 @@ class DMDServer : ComObject, IVDServer for (size_t i = 0; i < mModules.length; i++) { - Module m = new Module(mModules[i].filename, null, false, false); - memcpy(cast(void*)m, cast(void*)mModules[i].parsedModule, __traits(classInstanceSize, Module)); - m = cast(Module)mModules[i].parsedModule.syntaxCopy(m); + ModuleData* md = mModules[i]; + Module m = cloneModule(md.parsedModule); m.importedFrom = m; m = m.resolvePackage(); - mModules[i].analyzedModule = m; + md.analyzedModule = m; Module.modules.insert(m); } Module.rootModule = rootModule.analyzedModule; diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index a8a60149..c7e63b48 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -19,6 +19,7 @@ import dmd.cond; import dmd.console; import dmd.dclass; import dmd.declaration; +import dmd.denum; import dmd.dimport; import dmd.dinterpret; import dmd.dmodule; @@ -86,13 +87,15 @@ extern(C++) class ASTVisitor : StoppableVisitor sym.accept(this); } - // override void visit(Expression) {} - // override void visit(Parameter) {} - // override void visit(Statement) {} - // override void visit(Type) {} - // override void visit(TemplateParameter) {} - // override void visit(Condition) {} - // override void visit(Initializer) {} + // default to being permissve + override void visit(Dsymbol) {} + override void visit(Expression) {} + override void visit(Parameter) {} + override void visit(Statement) {} + override void visit(Type) {} + override void visit(TemplateParameter) {} + override void visit(Condition) {} + override void visit(Initializer) {} override void visit(ScopeDsymbol scopesym) { @@ -132,10 +135,6 @@ extern(C++) class ASTVisitor : StoppableVisitor visit(cast(AttribDeclaration)decl); } - override void visit(Condition) - { - } - override void visit(ExpInitializer einit) { visitExpression(einit.exp); @@ -319,6 +318,7 @@ extern(C++) class ASTVisitor : StoppableVisitor override void visit(TryCatchStatement stmt) { + // variables not looked at by PostorderStatementVisitor if (!stop && stmt.catches) foreach(c; *stmt.catches) visitDeclaration(c.var); @@ -410,8 +410,8 @@ extern(C++) class FindASTVisitor : ASTVisitor override void visit(Parameter sym) { - //if (!found && matchIdentifier(sym.loc, sym.ident)) - // foundNode(sym); + if (!found && matchIdentifier(sym.identloc, sym.ident)) + foundNode(sym); } override void visit(DVCondition cond) @@ -465,20 +465,11 @@ extern(C++) class FindASTVisitor : ASTVisitor // skip members added by semantic } - override void visit(Statement stmt) - { - // default to nothing - } - override void visit(CallExp expr) { super.visit(expr); } - override void visit(Expression expr) - { - // default to nothing - } override void visit(SymbolExp expr) { if (!found && expr.var) @@ -491,7 +482,7 @@ extern(C++) class FindASTVisitor : ASTVisitor if (ne.member) foundNode(ne.member); else - foundNode(ne.type); + foundNode(ne.newtype); } override void visit(DotIdExp de) @@ -518,12 +509,33 @@ extern(C++) class FindASTVisitor : ASTVisitor override void visit(DotVarExp dve) { if (!found && dve.var && dve.var.ident) - if (matchIdentifier(dve.varloc, dve.var.ident)) + if (matchIdentifier(dve.varloc.filename ? dve.varloc : dve.loc, dve.var.ident)) foundNode(dve); } + override void visit(VarDeclaration decl) + { + if (decl.originalType && decl.originalType.ty == Tident) + visitTypeIdentifier(cast(TypeIdentifier) decl.originalType, decl.type); + + super.visit(decl); + } + + override void visit(EnumDeclaration ed) + { + if (!found && ed.ident) + if (matchIdentifier(ed.loc, ed.ident)) + foundNode(ed); + + visit(cast(ScopeDsymbol)ed); + } + override void visit(AggregateDeclaration ad) { + if (!found && ad.ident) + if (matchIdentifier(ad.loc, ad.ident)) + foundNode(ad); + visit(cast(ScopeDsymbol)ad); } @@ -609,6 +621,10 @@ extern(C++) class FindTipVisitor : FindASTVisitor string txt; if (decl.isParameter()) txt = "(parameter) "; + else if (decl.isEnumMember()) + txt = "(enum member) "; + else if (decl.isAliasDeclaration()) + txt = "(alias) "; else if (!decl.isDataseg() && !decl.isCodeseg() && !decl.isField()) txt = "(local variable) "; bool fqn = txt.empty; @@ -616,12 +632,15 @@ extern(C++) class FindTipVisitor : FindASTVisitor if (decl.type) txt ~= to!string(decl.type.toPrettyChars()) ~ " "; txt ~= to!string(fqn ? decl.toPrettyChars(fqn) : decl.toChars()); + if (auto em = decl.isEnumMember()) + if (em.origValue) + txt ~= " = " ~ em.origValue.toString(); return txt; } - const(char)* toc = null; + string toc; if (auto t = obj.isType()) - toc = t.toChars(); + toc = "(" ~ t.kind().to!string ~ ") " ~ t.toPrettyChars(true).to!string; else if (auto e = obj.isExpression()) { switch(e.op) @@ -635,7 +654,7 @@ extern(C++) class FindTipVisitor : FindASTVisitor break; default: if (e.type) - toc = e.type.toPrettyChars(); + toc = e.type.toPrettyChars(true).to!string; break; } } @@ -644,13 +663,13 @@ extern(C++) class FindTipVisitor : FindASTVisitor if (auto decl = s.isDeclaration) tip = tipForDeclaration(decl); else - toc = s.toPrettyChars(true); + toc = s.toPrettyChars(true).to!string; } if (!tip.length) { if (!toc) - toc = obj.toChars(); - tip = to!string(toc); + toc = obj.toString().dup; + tip = toc; } // append doc stop = true; @@ -712,6 +731,9 @@ extern(C++) class FindDefinitionVisitor : FindASTVisitor case TOK.symbolOffset: loc = (cast(SymbolExp)e).var.loc; break; + case TOK.dotVariable: + loc = (cast(DotVarExp)e).var.loc; + break; default: loc = e.loc; break; @@ -739,3 +761,44 @@ string findDefinition(Module mod, ref int line, ref int index) index = fdv.loc.charnum; return to!string(fdv.loc.filename); } + +Module cloneModule(Module mo) +{ + Module m = new Module(mo.srcfile.toString(), mo.ident, mo.isDocFile, mo.isHdrFile); + *cast(FileName*)&(m.srcfile) = mo.srcfile; // keep identical source file name pointer + m.isPackageFile = mo.isPackageFile; + mo.syntaxCopy(m); + + extern(C++) class AdjustModuleVisitor : ASTVisitor + { + // avoid allocating capture + Module m; + this (Module m) + { + this.m = m; + } + + alias visit = super.visit; + + override void visit(ConditionalStatement cond) + { + if (auto dbg = cond.condition.isDebugCondition()) + cond.condition = new DebugCondition(dbg.loc, m, dbg.level, dbg.ident); + else if (auto ver = cond.condition.isVersionCondition()) + cond.condition = new VersionCondition(ver.loc, m, ver.level, ver.ident); + } + + override void visit(ConditionalDeclaration cond) + { + if (auto dbg = cond.condition.isDebugCondition()) + cond.condition = new DebugCondition(dbg.loc, m, dbg.level, dbg.ident); + else if (auto ver = cond.condition.isVersionCondition()) + cond.condition = new VersionCondition(ver.loc, m, ver.level, ver.ident); + } + } + + import dmd.permissivevisitor; + scope v = new AdjustModuleVisitor(m); + m.accept(v); + return m; +} From 51041611ebec5c02cc2650a81ace0cf44de067f6 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Thu, 1 Aug 2019 20:31:59 +0200 Subject: [PATCH 18/73] cleanup projects --- c2d/c2d.visualdproj | 2 +- c2d/cpp2d.visualdproj | 2 +- c2d/vsi2d.visualdproj | 2 +- sdk/vsi.visualdproj | 240 ++++++++++++++++++------------------ stdext/stdext.visualdproj | 4 +- visuald/visuald.visualdproj | 4 +- 6 files changed, 127 insertions(+), 127 deletions(-) diff --git a/c2d/c2d.visualdproj b/c2d/c2d.visualdproj index 4e98f056..26b8b618 100644 --- a/c2d/c2d.visualdproj +++ b/c2d/c2d.visualdproj @@ -1397,7 +1397,7 @@ $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. .. ..\bin\$(ConfigurationName)\$(PlatformName) diff --git a/c2d/cpp2d.visualdproj b/c2d/cpp2d.visualdproj index 38c530d8..f52707d3 100644 --- a/c2d/cpp2d.visualdproj +++ b/c2d/cpp2d.visualdproj @@ -1397,7 +1397,7 @@ $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. .. ..\bin\$(ConfigurationName)\$(PlatformName) diff --git a/c2d/vsi2d.visualdproj b/c2d/vsi2d.visualdproj index 77b4e3a4..ddeb0ae6 100644 --- a/c2d/vsi2d.visualdproj +++ b/c2d/vsi2d.visualdproj @@ -1155,7 +1155,7 @@ $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. .. ..\bin\$(ConfigurationName)\$(PlatformName) diff --git a/sdk/vsi.visualdproj b/sdk/vsi.visualdproj index c58aa684..f076eb3f 100644 --- a/sdk/vsi.visualdproj +++ b/sdk/vsi.visualdproj @@ -1397,7 +1397,7 @@ $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. ..\bin\$(ConfigurationName)\$(PlatformName) @@ -1881,7 +1881,7 @@ $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. ..\bin\$(ConfigurationName) @@ -1986,103 +1986,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -2091,12 +1997,16 @@ + + + + @@ -2104,6 +2014,7 @@ + @@ -2135,6 +2046,7 @@ + @@ -2150,8 +2062,14 @@ + + + + + + @@ -2163,12 +2081,17 @@ + + + + + @@ -2182,10 +2105,13 @@ + + + @@ -2198,38 +2124,112 @@ + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stdext/stdext.visualdproj b/stdext/stdext.visualdproj index 05d0afd1..fad21f77 100644 --- a/stdext/stdext.visualdproj +++ b/stdext/stdext.visualdproj @@ -1397,7 +1397,7 @@ $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. ..\bin\$(ConfigurationName)\$(PlatformName) @@ -1881,7 +1881,7 @@ $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. ..\bin\$(ConfigurationName) diff --git a/visuald/visuald.visualdproj b/visuald/visuald.visualdproj index df3fa912..aa6d4c91 100644 --- a/visuald/visuald.visualdproj +++ b/visuald/visuald.visualdproj @@ -550,7 +550,7 @@ $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. ..;resources ..\bin\$(ConfigurationName) @@ -792,7 +792,7 @@ $(CC) -c 1 0 - m:\s\d\rainers\windows\bin\dmd_msc.exe + .. ..;resources ..\bin\$(ConfigurationName) From b4cc8f17c80b64d72d6114ad491278f0e5adecd6 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 2 Aug 2019 14:24:55 +0200 Subject: [PATCH 19/73] implement GetBinaryIsInLocations --- vdc/dmdserver/dmdserver.d | 30 ++++++++++++------------------ vdc/dmdserver/semvisitor.d | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index ed133f91..477c59e9 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -640,24 +640,18 @@ class DMDServer : ComObject, IVDServer override HRESULT GetBinaryIsInLocations(in BSTR filename, VARIANT* locs) { // array of pairs of DWORD - int[] locData; string fname = makeFilenameCanonical(to_string(filename), null); - /+ - synchronized(mSemanticProject) - if(auto src = mSemanticProject.getModuleByFilename(fname)) - if(auto mod = src.parsed) - { - mod.visit(delegate bool (ast.Node n) { - if(n.id == TOK_in || n.id == TOK_is) - if(cast(ast.BinaryExpression) n) - { - locData ~= n.span.start.line; - locData ~= n.span.start.index; - } - return true; - }); - } - +/ + + ModuleData* md; + synchronized(gErrorSync) + { + md = findModule(fname, false); + if (!md || !md.parsedModule) + return S_FALSE; + } + + int[] locData = findBinaryIsInLocations(md.parsedModule); + SAFEARRAY *sa = SafeArrayCreateVector(VT_INT, 0, cast(ULONG) locData.length); if(!sa) return E_OUTOFMEMORY; @@ -665,7 +659,7 @@ class DMDServer : ComObject, IVDServer for(LONG index = 0; index < locData.length; index++) SafeArrayPutElement(sa, &index, &locData[index]); - locs.vt = VT_ARRAY; + locs.vt = VT_ARRAY | VT_INT; locs.parray = sa; return S_OK; } diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index c7e63b48..6be1c3e9 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -762,6 +762,41 @@ string findDefinition(Module mod, ref int line, ref int index) return to!string(fdv.loc.filename); } +int[] findBinaryIsInLocations(Module mod) +{ + extern(C++) class BinaryIsInVisitor : ASTVisitor + { + int[] locdata; + + alias visit = super.visit; + + final void addLocation(const ref Loc loc) + { + if (loc.filename) + { + locdata ~= loc.linnum; + locdata ~= loc.charnum - 1; + } + } + + override void visit(InExp e) + { + addLocation(e.oploc); + super.visit(e); + } + override void visit(IdentityExp e) + { + addLocation(e.oploc); + super.visit(e); + } + } + + scope BinaryIsInVisitor biiv = new BinaryIsInVisitor; + mod.accept(biiv); + + return biiv.locdata; +} + Module cloneModule(Module mo) { Module m = new Module(mo.srcfile.toString(), mo.ident, mo.isDocFile, mo.isHdrFile); From f18056538b95132e29e13dab7dbb2e5550db8fdd Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 2 Aug 2019 17:46:48 +0200 Subject: [PATCH 20/73] implement GetIdentifierTypes --- vdc/dmdserver/dmdserver.d | 64 +++++++++++-- vdc/dmdserver/semvisitor.d | 185 ++++++++++++++++++++++++++++++++----- vdc/ivdserver.d | 29 ++++++ 3 files changed, 247 insertions(+), 31 deletions(-) diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index 477c59e9..bbe9d230 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -691,12 +691,61 @@ class DMDServer : ComObject, IVDServer HRESULT GetIdentifierTypes(in BSTR filename, int startLine, int endLine, int flags) { - return E_NOTIMPL; + string fname = makeFilenameCanonical(to_string(filename), null); + + mIdTypesSpan.start.line = startLine; // unused so far + mIdTypesSpan.start.index = 0; + mIdTypesSpan.end.line = endLine; + mIdTypesSpan.end.index = 0; + + ModuleData* md; + synchronized(gErrorSync) + { + md = findModule(fname, false); + if (!md) + return S_FALSE; + } + + void _getIdentifierTypes() + { + string identiferTypes; + synchronized(gDMDSync) + { + try + { + if (auto m = md.analyzedModule) + identiferTypes = findIdentifierTypes(m); + else + identiferTypes = "identifying..."; + } + catch(OutOfMemoryError e) + { + throw e; // terminate + } + catch(Throwable t) + { + version(DebugServer) dbglog("GetIdentifierTypes: exception " ~ t.msg); + } + } + mLastIdentiferTypes = identiferTypes; + mSemanticIdentierTypesRunning = false; + } + version(DebugServer) dbglog(" schedule GetIdentifierTypes: " ~ fname); + mSemanticIdentierTypesRunning = true; + schedule(&_getIdentifierTypes); + + return S_OK; } HRESULT GetIdentifierTypesResult(BSTR* types) { - return E_NOTIMPL; + if(mSemanticIdentierTypesRunning) + { + *types = allocBSTR("__pending__"); + return S_OK; + } + *types = allocBSTR(mLastIdentiferTypes); + return S_OK; } /////////////////////////////////////////////////////////////// @@ -1017,6 +1066,7 @@ private: bool mSemanticExpansionsRunning; bool mSemanticTipRunning; bool mSemanticDefinitionRunning; + bool mSemanticIdentierTypesRunning; bool mPredefineVersions; @@ -1025,6 +1075,8 @@ private: TextSpan mTipSpan; string mLastDefFile; TextSpan mDefSpan; + string mLastIdentiferTypes; + TextSpan mIdTypesSpan; string[] mLastSymbols; string mLastMessage; string mLastError; @@ -1148,6 +1200,8 @@ enum string[2][] dmdStatics = ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ3feqCQEn4func15FuncDeclaration", "FuncDeclaration"], ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ4fcmpCQEo4func15FuncDeclaration", "FuncDeclaration"], ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ5fhashCQEp4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDdQBc8DotIdExpiZ11visitAArrayMFCQEkQDq10TypeAArrayZ8fd_aaLenCQFn4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDdQBc8DotIdExpiZ8noMemberMFQDlQDaQClCQEp10identifier10IdentifieriZ4nesti", "int"], ["_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBufferkPkAxaZ4nesti", "int"], // x86 ["_D3dmd7dmodule6Module19runDeferredSemanticRZ6nestedi", "int"], ["_D3dmd10dsymbolsem22DsymbolSemanticVisitor5visitMRCQBx9dtemplate13TemplateMixinZ4nesti", "int"], @@ -1161,9 +1215,6 @@ enum string[2][] dmdStatics = ["_D3dmd10identifier10Identifier17generateIdWithLocFNbAyaKxSQCe7globals3LocZ8countersHSQDfQDeQCvQCmFNbQBwKxQBwZ3Keyk", "countersType"], ["_D3dmd10identifier10Identifier10generateIdRNbPxaZ1im", "int"], ["_D3dmd5lexer5Lexer4scanMFNbPSQBb6tokens5TokenZ8initdoneb", "bool"], - - //["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ11visitAArrayMFCQEwQEc10TypeAArrayZ8fd_aaLenCQFz4func15FuncDeclaration", "FuncDeclaration"], - //["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDd10identifier10IdentifieriZ8noMemberMFQDxQDmQCxQByiZ4nesti", "int"], ]; string cmangled(string s) @@ -1266,7 +1317,8 @@ void dmdInit() dmdReinit(true); } -// initialization that are necessary before restarting an analysis +// initialization that are necessary before restarting an analysis (which might run +// for another platform/architecture) void dmdReinit(bool configChanged) { if (configChanged) diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 6be1c3e9..40390147 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -8,7 +8,7 @@ module vdc.dmdserver.semvisitor; -import vdc.semanticopt; +import vdc.ivdserver; import dmd.aggregate; import dmd.apply; @@ -575,6 +575,22 @@ extern(C++) class FindASTVisitor : ASTVisitor } } +RootObject _findAST(Dsymbol sym, const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) +{ + scope FindASTVisitor fav = new FindASTVisitor(filename, startLine, startIndex, endLine, endIndex); + sym.accept(fav); + + return fav.found; +} + +RootObject findAST(Module mod, int startLine, int startIndex, int endLine, int endIndex) +{ + auto filename = mod.srcfile.toChars(); + return _findAST(mod, filename, startLine, startIndex, endLine, endIndex); +} + +//////////////////////////////////////////////////////////////////////////////// + extern(C++) class FindTipVisitor : FindASTVisitor { string tip; @@ -623,15 +639,29 @@ extern(C++) class FindTipVisitor : FindASTVisitor txt = "(parameter) "; else if (decl.isEnumMember()) txt = "(enum member) "; + else if (decl.storage_class & STC.manifest) + txt = "(constant) "; else if (decl.isAliasDeclaration()) txt = "(alias) "; - else if (!decl.isDataseg() && !decl.isCodeseg() && !decl.isField()) + else if (decl.isField()) + txt = "(field) "; + else if (!decl.isDataseg() && !decl.isCodeseg()) txt = "(local variable) "; + else if (decl.isThreadlocal()) + txt = "(thread local variable) "; + else if (decl.type && decl.type.isShared()) + txt = "(shared variable) "; + else + txt = "(__gshared variable) "; bool fqn = txt.empty; if (decl.type) txt ~= to!string(decl.type.toPrettyChars()) ~ " "; txt ~= to!string(fqn ? decl.toPrettyChars(fqn) : decl.toChars()); + if (decl.storage_class & STC.manifest) + if (auto var = decl.isVarDeclaration()) + if (var._init) + txt ~= " = " ~ var._init.toString(); if (auto em = decl.isEnumMember()) if (em.origValue) txt ~= " = " ~ em.origValue.toString(); @@ -678,20 +708,6 @@ extern(C++) class FindTipVisitor : FindASTVisitor } } -RootObject _findAST(Dsymbol sym, const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) -{ - scope FindASTVisitor fav = new FindASTVisitor(filename, startLine, startIndex, endLine, endIndex); - sym.accept(fav); - - return fav.found; -} - -RootObject findAST(Module mod, int startLine, int startIndex, int endLine, int endIndex) -{ - auto filename = mod.srcfile.toChars(); - return _findAST(mod, filename, startLine, startIndex, endLine, endIndex); -} - string findTip(Module mod, int startLine, int startIndex, int endLine, int endIndex) { auto filename = mod.srcfile.toChars(); @@ -762,17 +778,20 @@ string findDefinition(Module mod, ref int line, ref int index) return to!string(fdv.loc.filename); } +//////////////////////////////////////////////////////////////////////////////// + int[] findBinaryIsInLocations(Module mod) { extern(C++) class BinaryIsInVisitor : ASTVisitor { int[] locdata; + const(char)* filename; alias visit = super.visit; final void addLocation(const ref Loc loc) { - if (loc.filename) + if (loc.filename is filename) { locdata ~= loc.linnum; locdata ~= loc.charnum - 1; @@ -792,17 +811,133 @@ int[] findBinaryIsInLocations(Module mod) } scope BinaryIsInVisitor biiv = new BinaryIsInVisitor; + biiv.filename = mod.srcfile.toChars(); mod.accept(biiv); return biiv.locdata; } +//////////////////////////////////////////////////////////////////////////////// +string findIdentifierTypes(Module mod) +{ + static struct IdTypePos + { + int type; + int line; + int col; + } + extern(C++) class IdentifierTypesVisitor : ASTVisitor + { + IdTypePos[][const(char)[]] idTypes; + const(char)* filename; + + alias visit = super.visit; + + extern(D) + final void addTypePos(const(char)[] ident, int type, int line, int col) + { + if (auto pid = ident in idTypes) + { + if (type != (*pid)[$-1].type) + *pid ~= IdTypePos(type, line, col); + } + else + idTypes[ident] = [IdTypePos(type, line, col)]; + } + + void addIdent(ref const Loc loc, Identifier ident, int type) + { + if (ident && loc.filename is filename) + addTypePos(ident.toString(), type, loc.linnum, loc.charnum); + } + + void addDeclaration(ref const Loc loc, Declaration decl) + { + auto ident = decl.ident; + if (auto func = decl.isFuncDeclaration()) + { + auto p = decl.toParent2; + if (p && p.isAggregateDeclaration) + addIdent(loc, ident, TypeReferenceKind.Function); + else + addIdent(loc, ident, TypeReferenceKind.Method); + } + else if (decl.isParameter()) + addIdent(loc, ident, TypeReferenceKind.ParameterVariable); + else if (decl.isEnumMember()) + addIdent(loc, ident, TypeReferenceKind.EnumValue); + else if (decl.storage_class & STC.manifest) + addIdent(loc, ident, TypeReferenceKind.Constant); + else if (decl.isAliasDeclaration()) + addIdent(loc, ident, TypeReferenceKind.Alias); + else if (decl.isField()) + addIdent(loc, ident, TypeReferenceKind.MemberVariable); + else if (!decl.isDataseg() && !decl.isCodeseg()) + addIdent(loc, ident, TypeReferenceKind.LocalVariable); + else if (decl.isThreadlocal()) + addIdent(loc, ident, TypeReferenceKind.TLSVariable); + else if (decl.type && decl.type.isShared()) + addIdent(loc, ident, TypeReferenceKind.SharedVariable); + else + addIdent(loc, ident, TypeReferenceKind.GSharedVariable); + } + + override void visit(Dsymbol sym) + { + if (auto decl = sym.isDeclaration) + addDeclaration(sym.loc, decl); + else + addIdent(sym.loc, sym.ident, TypeReferenceKind.Variable); + } + + override void visit(Parameter sym) + { + addIdent(sym.identloc, sym.ident, TypeReferenceKind.ParameterVariable); + } + + override void visit(EnumDeclaration ed) + { + addIdent(ed.loc, ed.ident, TypeReferenceKind.Enum); + super.visit(ed); + } + + override void visit(AggregateDeclaration ad) + { + if (ad.isInterfaceDeclaration) + addIdent(ad.loc, ad.ident, TypeReferenceKind.Interface); + else if (ad.isClassDeclaration) + addIdent(ad.loc, ad.ident, TypeReferenceKind.Class); + else if (ad.isUnionDeclaration) + addIdent(ad.loc, ad.ident, TypeReferenceKind.Union); + else + addIdent(ad.loc, ad.ident, TypeReferenceKind.Struct); + super.visit(ad); + } + } + + scope IdentifierTypesVisitor itv = new IdentifierTypesVisitor; + itv.filename = mod.srcfile.toChars(); + mod.accept(itv); + + string s; + foreach(id, pos; itv.idTypes) + { + string ids = id.idup ~ ":" ~ pos[0].type.to!string(); + foreach (ref p; pos[1..$]) + ids ~= ";" ~ p.type.to!string() ~ "," ~ p.line.to!string() ~ "," ~ p.col.to!string(); + s ~= ids ~ "\n"; + } + return s; +} + +//////////////////////////////////////////////////////////////////////////////// + Module cloneModule(Module mo) { - Module m = new Module(mo.srcfile.toString(), mo.ident, mo.isDocFile, mo.isHdrFile); - *cast(FileName*)&(m.srcfile) = mo.srcfile; // keep identical source file name pointer - m.isPackageFile = mo.isPackageFile; - mo.syntaxCopy(m); + Module m = new Module(mo.srcfile.toString(), mo.ident, mo.isDocFile, mo.isHdrFile); + *cast(FileName*)&(m.srcfile) = mo.srcfile; // keep identical source file name pointer + m.isPackageFile = mo.isPackageFile; + mo.syntaxCopy(m); extern(C++) class AdjustModuleVisitor : ASTVisitor { @@ -832,8 +967,8 @@ Module cloneModule(Module mo) } } - import dmd.permissivevisitor; - scope v = new AdjustModuleVisitor(m); - m.accept(v); - return m; + import dmd.permissivevisitor; + scope v = new AdjustModuleVisitor(m); + m.accept(v); + return m; } diff --git a/vdc/ivdserver.d b/vdc/ivdserver.d index cac03a08..a5849e5b 100644 --- a/vdc/ivdserver.d +++ b/vdc/ivdserver.d @@ -239,3 +239,32 @@ uint ConfigureFlags()(bool unittestOn, bool debugOn, bool x64, bool cov, bool do | (msvcrt ? 0x8_00_00_00 : 0); } +// from D_Parser: types returned by GetIdentifierTypes +enum TypeReferenceKind : uint +{ + Unknown, + + Interface, + Enum, + EnumValue, + Template, + Class, + Struct, + Union, + TemplateTypeParameter, + + Constant, + LocalVariable, + ParameterVariable, + TLSVariable, + SharedVariable, + GSharedVariable, + MemberVariable, + Variable, + + Alias, + Module, + Function, + Method, + BasicType, +} From 566829a8438fe437a3f17e2708d548ec57f9ae9f Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 2 Aug 2019 20:00:20 +0200 Subject: [PATCH 21/73] implement basic GetReferences --- vdc/dmdserver/dmdserver.d | 67 +++++++++++++++++++++---- vdc/dmdserver/dmdserver.visualdproj | 4 +- vdc/dmdserver/semvisitor.d | 77 +++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 11 deletions(-) diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index bbe9d230..a29f40d8 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -681,12 +681,56 @@ class DMDServer : ComObject, IVDServer override HRESULT GetReferences(in BSTR filename, in BSTR tok, uint line, uint idx, in BSTR expr, in BOOL moduleOnly) { - return E_NOTIMPL; + string fname = makeFilenameCanonical(to_string(filename), null); + + ModuleData* md; + synchronized(gErrorSync) + { + md = findModule(fname, false); + if (!md) + return S_FALSE; + } + + void _getReferences() + { + string references; + synchronized(gDMDSync) + { + try + { + if (auto m = md.analyzedModule) + references = findReferences(m, line, idx + 1); + else + references = "analyzing..."; + } + catch(OutOfMemoryError e) + { + throw e; // terminate + } + catch(Throwable t) + { + version(DebugServer) dbglog("GetReferences: exception " ~ t.msg); + } + } + mLastReferences = references; + mSemanticGetReferencesRunning = false; + } + version(DebugServer) dbglog(" schedule GetReferences: " ~ fname); + mSemanticGetReferencesRunning = true; + schedule(&_getReferences); + + return S_OK; } override HRESULT GetReferencesResult(BSTR* stringList) { - return E_NOTIMPL; + if(mSemanticGetReferencesRunning) + { + *stringList = allocBSTR("__pending__"); + return S_OK; + } + *stringList = allocBSTR(mLastReferences); + return S_OK; } HRESULT GetIdentifierTypes(in BSTR filename, int startLine, int endLine, int flags) @@ -727,11 +771,11 @@ class DMDServer : ComObject, IVDServer version(DebugServer) dbglog("GetIdentifierTypes: exception " ~ t.msg); } } - mLastIdentiferTypes = identiferTypes; - mSemanticIdentierTypesRunning = false; + mLastIdentifierTypes = identiferTypes; + mSemanticIdentifierTypesRunning = false; } version(DebugServer) dbglog(" schedule GetIdentifierTypes: " ~ fname); - mSemanticIdentierTypesRunning = true; + mSemanticIdentifierTypesRunning = true; schedule(&_getIdentifierTypes); return S_OK; @@ -739,12 +783,12 @@ class DMDServer : ComObject, IVDServer HRESULT GetIdentifierTypesResult(BSTR* types) { - if(mSemanticIdentierTypesRunning) + if(mSemanticIdentifierTypesRunning) { *types = allocBSTR("__pending__"); return S_OK; } - *types = allocBSTR(mLastIdentiferTypes); + *types = allocBSTR(mLastIdentifierTypes); return S_OK; } @@ -1066,17 +1110,22 @@ private: bool mSemanticExpansionsRunning; bool mSemanticTipRunning; bool mSemanticDefinitionRunning; - bool mSemanticIdentierTypesRunning; + bool mSemanticIdentifierTypesRunning; + bool mSemanticGetReferencesRunning; bool mPredefineVersions; string mModuleToParse; string mLastTip; TextSpan mTipSpan; + string mLastDefFile; TextSpan mDefSpan; - string mLastIdentiferTypes; + + string mLastIdentifierTypes; TextSpan mIdTypesSpan; + + string mLastReferences; string[] mLastSymbols; string mLastMessage; string mLastError; diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index d3a746c9..02bfdcca 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -1296,7 +1296,7 @@ 0 0 - MARS NoBackend + MARS NoBackend GC 0 0 0 @@ -1417,7 +1417,7 @@ 0 0 - MARS NoBackend + MARS NoBackend GC 0 3 0 diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 40390147..939a1b7f 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -930,6 +930,83 @@ string findIdentifierTypes(Module mod) return s; } +//////////////////////////////////////////////////////////////////////////////// +string findReferences(Module mod, int line, int index) +{ + auto filename = mod.srcfile.toChars(); + scope FindDefinitionVisitor fdv = new FindDefinitionVisitor(filename, line, index, line, index + 1); + mod.accept(fdv); + + if (!fdv.found) + return null; + + extern(C++) class FindReferencesVisitor : ASTVisitor + { + RootObject search; + string references; + + alias visit = super.visit; + + extern(D) + void addReference(ref const Loc loc, Identifier ident) + { + if (loc.filename && ident) + { + import core.stdc.stdio; + char[128] buf; + int llen = snprintf(buf.ptr, buf.length, "%d,%d,%d,%d:\n", + loc.linnum, loc.charnum - 1, + loc.linnum, loc.charnum + ident.toString().length - 1); + references ~= buf[0..llen]; + } + + } + + override void visit(Dsymbol sym) + { + if (sym is search) + addReference(sym.loc, sym.ident); + } + override void visit(SymbolExp expr) + { + if (expr.var is search) + addReference(expr.loc, expr.var.ident); + } + override void visit(DotVarExp dve) + { + if (dve.var is search) + addReference(dve.varloc.filename ? dve.varloc : dve.loc, dve.var.ident); + } + } + + scope FindReferencesVisitor frv = new FindReferencesVisitor(); + + if (auto t = fdv.found.isType()) + { + if (t.ty == Tstruct) + fdv.found = (cast(TypeStruct)t).sym; + } + else if (auto e = fdv.found.isExpression()) + { + switch(e.op) + { + case TOK.variable: + case TOK.symbolOffset: + fdv.found = (cast(SymbolExp)e).var; + break; + case TOK.dotVariable: + fdv.found = (cast(DotVarExp)e).var; + break; + default: + break; + } + } + frv.search = fdv.found; + mod.accept(frv); + + return frv.references; +} + //////////////////////////////////////////////////////////////////////////////// Module cloneModule(Module mo) From 5f11574ed48ea64364f1239de0495cc98e760bfa Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 3 Aug 2019 16:27:17 +0200 Subject: [PATCH 22/73] basic implementation of GetSemanticExpansions --- vdc/dmdserver/dmdserver.d | 28 +++--- vdc/dmdserver/semvisitor.d | 173 +++++++++++++++++++++++++++++++------ 2 files changed, 164 insertions(+), 37 deletions(-) diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index a29f40d8..7d8503d8 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -564,21 +564,25 @@ class DMDServer : ComObject, IVDServer override HRESULT GetSemanticExpansions(in BSTR filename, in BSTR tok, uint line, uint idx, in BSTR expr) { - string[] symbols; string fname = makeFilenameCanonical(to_string(filename), null); - /+ - auto src = mSemanticProject.getModuleByFilename(fname); - if(!src) - return S_FALSE; + + ModuleData* md; + synchronized(gErrorSync) + { + md = findModule(fname, false); + if (!md) + return S_FALSE; + } string stok = to_string(tok); string sexpr = to_string(expr); - void calcExpansions() + void _calcExpansions() { - fnSemanticWriteError = &semanticWriteError; + string[] symbols; try { - mLastSymbols = null; //_GetSemanticExpansions(src, stok, line, idx, sexpr); + if (auto m = md.analyzedModule) + symbols = findExpansions(m, line, idx + 1, stok); } catch(OutOfMemoryError e) { @@ -586,16 +590,16 @@ class DMDServer : ComObject, IVDServer } catch(Throwable t) { - version(DebugServer) dbglog("GetSemanticExpansions.calcExpansions: exception " ~ t.msg); - logInfo(t.msg); + version(DebugServer) dbglog("calcExpansions: exception " ~ t.msg); } mSemanticExpansionsRunning = false; + mLastSymbols = symbols; } version(DebugServer) dbglog(" schedule GetSemanticExpansions: " ~ fname); mLastSymbols = null; mSemanticExpansionsRunning = true; - schedule(&calcExpansions); - +/ + schedule(&_calcExpansions); + return S_OK; } diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 939a1b7f..981e98eb 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -10,6 +10,7 @@ module vdc.dmdserver.semvisitor; import vdc.ivdserver; +import dmd.access; import dmd.aggregate; import dmd.apply; import dmd.arraytypes; @@ -363,6 +364,7 @@ extern(C++) class FindASTVisitor : ASTVisitor alias visit = super.visit; RootObject found; + ScopeDsymbol foundScope; this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) { @@ -420,46 +422,69 @@ extern(C++) class FindASTVisitor : ASTVisitor foundNode(cond); } - version(none) - override void visit(ScopeDsymbol scopesym) + override void visit(CompoundStatement cs) { // optimize to only visit members in approriate source range - // unfortunately, some members don't have valid locations - size_t mcnt = scopesym.members ? scopesym.members.dim : 0; - size_t minMember = 0; - size_t maxMember = mcnt; - for (size_t m = 0; m < mcnt; m++) + size_t scnt = cs.statements ? cs.statements.dim : 0; + for (size_t i = 0; i < scnt && !stop; i++) { - Dsymbol s = (*scopesym.members)[m]; - if (s.isTemplateInstance) + Statement s = (*cs.statements)[i]; + if (!s) continue; if (s.loc.filename) { - if (s.loc.filename !is filename) + if (s.loc.filename !is filename || s.loc.linnum > endLine) + continue; + Loc endloc; + if (auto ss = s.isScopeStatement()) + endloc = ss.endloc; + else if (auto ws = s.isWhileStatement()) + endloc = ws.endloc; + else if (auto ds = s.isDoStatement()) + endloc = ds.endloc; + else if (auto fs = s.isForStatement()) + endloc = fs.endloc; + else if (auto fs = s.isForeachStatement()) + endloc = fs.endloc; + else if (auto fs = s.isForeachRangeStatement()) + endloc = fs.endloc; + else if (auto ifs = s.isIfStatement()) + endloc = ifs.endloc; + else if (auto ws = s.isWithStatement()) + endloc = ws.endloc; + if (endloc.filename && endloc.linnum < startLine) continue; - - if (s.loc.linnum > endLine || (s.loc.linnum == endLine && s.loc.charnum > endIndex)) - { - maxMember = m; - break; - } - if (s.loc.linnum < startLine || (s.loc.linnum == startLine && s.loc.charnum < startIndex)) - minMember = m; } + s.accept(this); } + } - for (size_t m = minMember; m < maxMember; m++) + override void visit(ScopeDsymbol scopesym) + { + // optimize to only visit members in approriate source range + // unfortunately, some members don't have valid locations + size_t mcnt = scopesym.members ? scopesym.members.dim : 0; + for (size_t m = 0; m < mcnt && !stop; m++) { Dsymbol s = (*scopesym.members)[m]; - if (s.loc.filename && s.loc.filename !is filename) + if (s.isTemplateInstance) continue; - + if (s.loc.filename) + { + if (s.loc.filename !is filename || s.loc.linnum > endLine) + continue; + Loc endloc; + if (auto fd = s.isFuncDeclaration()) + endloc = fd.endloc; + if (endloc.filename && endloc.linnum < startLine) + continue; + } s.accept(this); - - if (found) - break; } + if (found && !foundScope) + foundScope = scopesym; } + override void visit(TemplateInstance) { // skip members added by semantic @@ -559,7 +584,7 @@ extern(C++) class FindASTVisitor : ASTVisitor Loc loc = originalType.loc; if (matchIdentifier(loc, originalType.ident)) foundNode(resolvedType); - + // guess qualified name to be without spaces loc.charnum += originalType.ident.toString().length + 1; foreach (id; originalType.idents) @@ -1007,6 +1032,104 @@ string findReferences(Module mod, int line, int index) return frv.references; } +//////////////////////////////////////////////////////////////////////////////// +string[] findExpansions(Module mod, int line, int index, string tok) +{ + auto filename = mod.srcfile.toChars(); + scope FindDefinitionVisitor fdv = new FindDefinitionVisitor(filename, line, index - cast(int) tok.length, line, index + 1); + mod.accept(fdv); + + if (!fdv.found) + return null; + + Type type = fdv.found.isType(); + if (auto e = fdv.found.isExpression()) + { + switch(e.op) + { + case TOK.variable: + case TOK.symbolOffset: + type = (cast(SymbolExp)e).var.type; + break; + case TOK.dotVariable: + type = (cast(DotVarExp)e).e1.type; + break; + default: + break; + } + } + + auto sds = fdv.foundScope; + if (type) + { + if (auto ts = type.isTypeStruct()) + sds = ts.sym; + else if (auto tc = type.isTypeClass()) + sds = tc.sym; + else if (auto te = type.isTypeEnum()) + sds = te.sym; + } + + string[void*] idmap; // doesn't work with extern(C++) classes + void searchScope(ScopeDsymbol sds, int flags) + { + // TODO: properties + // TODO: base classes + // TODO: struct/class not going to parent if accessed from elsewhere (but does if nested) + for (Dsymbol ds = sds; ds; ds = ds.toParent) + { + ScopeDsymbol sd = ds.isScopeDsymbol(); + if (!ds) + continue; + + foreach (pair; sd.symtab.tab.asRange) + { + Dsymbol s = pair.value; + if (!symbolIsVisible(mod, s)) + continue; + auto ident = pair.key.toString(); + if (ident.startsWith(tok)) + idmap[cast(void*)s] = ident.idup; + } + + // TODO: alias this + + // imported modules + size_t cnt = sd.importedScopes ? sd.importedScopes.dim : 0; + for (size_t i = 0; i < cnt; i++) + { + if ((flags & IgnorePrivateImports) && sd.prots[i] == Prot.Kind.private_) + continue; + auto ss = (*sd.importedScopes)[i].isScopeDsymbol(); + if (!ss) + continue; + + int sflags = 0; + if (ss.isModule()) + { + if (flags & SearchLocalsOnly) + continue; + sflags |= IgnorePrivateImports; + } + else // mixin template + { + if (flags & SearchImportsOnly) + continue; + sflags |= SearchLocalsOnly; + } + searchScope(ss, sflags | IgnorePrivateImports); + } + } + } + searchScope(sds, 0); + + string[] idlist; + foreach(sym, id; idmap) + idlist ~= id ~ ":" ~ cast(string) (cast(Dsymbol)sym).toString(); + return idlist; +} + + //////////////////////////////////////////////////////////////////////////////// Module cloneModule(Module mo) From fe3f9c5281dd0d6bed39450d138f562d28d8927f Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 4 Aug 2019 11:34:50 +0200 Subject: [PATCH 23/73] split off dmd initialization into separate module --- vdc/dmdserver/dmdinit.d | 334 ++++++++++++++++++++++++++++ vdc/dmdserver/dmdserver.d | 281 +---------------------- vdc/dmdserver/dmdserver.visualdproj | 1 + 3 files changed, 337 insertions(+), 279 deletions(-) create mode 100644 vdc/dmdserver/dmdinit.d diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d new file mode 100644 index 00000000..95622f8f --- /dev/null +++ b/vdc/dmdserver/dmdinit.d @@ -0,0 +1,334 @@ +module vdc.dmdserver.dmdinit; + +import dmd.arraytypes; +import dmd.builtin; +import dmd.cond; +import dmd.ctfeexpr; +import dmd.dclass; +import dmd.declaration; +import dmd.dimport; +import dmd.dinterpret; +import dmd.dmodule; +import dmd.dstruct; +import dmd.dsymbol; +import dmd.dtemplate; +import dmd.expression; +import dmd.func; +import dmd.globals; +import dmd.id; +import dmd.mtype; +import dmd.objc; +import dmd.target; + +import dmd.root.outbuffer; + +//////////////////////////////////////////////////////////////// +alias countersType = uint[uint]; // actually uint[Key] + +enum string[2][] dmdStatics = +[ + ["_D3dmd5clone12buildXtoHashFCQBa7dstruct17StructDeclarationPSQCg6dscope5ScopeZ8tftohashCQDh5mtype12TypeFunction", "TypeFunction"], + ["_D3dmd7dstruct15search_toStringRCQBfQBe17StructDeclarationZ10tftostringCQCs5mtype12TypeFunction", "TypeFunction"], + ["_D3dmd13expressionsem11loadStdMathFZ10impStdMathCQBv7dimport6Import", "Import"], + ["_D3dmd4func15FuncDeclaration8genCfuncRPSQBm4root5array__T5ArrayTCQCl5mtype9ParameterZQBcCQDjQy4TypeCQDu10identifier10IdentifiermZ2stCQFb7dsymbol12DsymbolTable", "DsymbolTable"], + ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ3feqCQEn4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ4fcmpCQEo4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ5fhashCQEp4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDdQBc8DotIdExpiZ11visitAArrayMFCQEkQDq10TypeAArrayZ8fd_aaLenCQFn4func15FuncDeclaration", "FuncDeclaration"], + ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDdQBc8DotIdExpiZ8noMemberMFQDlQDaQClCQEp10identifier10IdentifieriZ4nesti", "int"], + ["_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBufferkPkAxaZ4nesti", "int"], // x86 + ["_D3dmd7dmodule6Module19runDeferredSemanticRZ6nestedi", "int"], + ["_D3dmd10dsymbolsem22DsymbolSemanticVisitor5visitMRCQBx9dtemplate13TemplateMixinZ4nesti", "int"], + ["_D3dmd9dtemplate16TemplateInstance16tryExpandMembersMFPSQCc6dscope5ScopeZ4nesti", "int"], + ["_D3dmd9dtemplate16TemplateInstance12trySemantic3MFPSQBy6dscope5ScopeZ4nesti", "int"], + ["_D3dmd13expressionsem25ExpressionSemanticVisitor5visitMRCQCd10expression7CallExpZ4nesti", "int"], + ["_D3dmd5lexer5Lexer12stringbufferSQBf4root9outbuffer9OutBuffer", "OutBuffer"], + ["_D3dmd10expression10IntegerExp__T7literalVii0ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], + ["_D3dmd10expression10IntegerExp__T7literalVii1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], + ["_D3dmd10expression10IntegerExp__T7literalViN1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], + ["_D3dmd10identifier10Identifier17generateIdWithLocFNbAyaKxSQCe7globals3LocZ8countersHSQDfQDeQCvQCmFNbQBwKxQBwZ3Keyk", "countersType"], + ["_D3dmd10identifier10Identifier10generateIdRNbPxaZ1im", "int"], + ["_D3dmd5lexer5Lexer4scanMFNbPSQBb6tokens5TokenZ8initdoneb", "bool"], +]; + +string cmangled(string s) +{ + version (Win64) + if (s == "_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBufferkPkAxaZ4nesti") + return "_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBuffermPmAxaZ4nesti"; + return s; +} + +string genDeclDmdStatics() +{ + string s; + foreach (decl; dmdStatics) + s ~= q{extern extern(C) __gshared } ~ decl[1] ~ " " ~ cmangled(decl[0]) ~ ";\n"; + return s; +} + +string genInitDmdStatics() +{ + string s; + foreach (decl; dmdStatics) + s ~= cmangled(decl[0]) ~ " = " ~ decl[1] ~ ".init;\n"; + return s; +} + +mixin(genDeclDmdStatics); + +pragma(mangle, "_D3dmd12statementsem24StatementSemanticVisitor5visitMRCQCb9statement16ForeachStatementZ7fdapplyPCQDr4func15FuncDeclaration") +extern __gshared FuncDeclaration* statementsem_fdapply; +pragma(mangle, "_D3dmd12statementsem24StatementSemanticVisitor5visitMRCQCb9statement16ForeachStatementZ6fldeTyPCQDq5mtype12TypeDelegate") +extern __gshared TypeDelegate* statementsem_fldeTy; + + +void clearSemanticStatics() +{ + /* + import core.demangle; + static foreach(s; dmdStatics) + pragma(msg, demangle(s[0])); + */ + mixin(genInitDmdStatics); + + // statementsem + // static __gshared FuncDeclaration* fdapply = [null, null]; + // static __gshared TypeDelegate* fldeTy = [null, null]; + statementsem_fdapply[0] = statementsem_fdapply[1] = null; + statementsem_fldeTy[0] = statementsem_fldeTy[1] = null; + + // dmd.dtemplate + emptyArrayElement = null; + TemplateValueParameter.edummies = null; + TemplateTypeParameter.tdummy = null; + TemplateAliasParameter.sdummy = null; + + CtfeStatus.callDepth = 0; + CtfeStatus.stackTraceCallsToSuppress = 0; + CtfeStatus.maxCallDepth = 0; + CtfeStatus.numAssignments = 0; + + VarDeclaration.nextSequenceNumber = 0; + + // Package.this.packageTag? + // funcDeclarationSemantic.printedMain? + /+ + Type.stringtable.reset(); + + dinterpret_init(); + + Scope.freelist = null; + //Token.freelist = null; + + Identifier.initTable(); + +/ +} + +// initialization that are necessary once +void dmdInit() +{ + __gshared bool initialized; + if (initialized) + return; + initialized = true; + + import dmd.root.longdouble; + // Initialization + version(CRuntime_Microsoft) + initFPU(); + + global.params.isWindows = true; + global._init(); + //Token._init(); + Id.initialize(); + Expression._init(); + builtin_init(); + + target._init(global.params); // needed by Type._init + Type._init(); + + dmdReinit(true); +} + +// initialization that are necessary before restarting an analysis (which might run +// for another platform/architecture) +void dmdReinit(bool configChanged) +{ + if (configChanged) + { + target._init(global.params); // needed by Type._init + Type._reinit(); + + // assume object.d unmodified otherwis + Module.moduleinfo = null; + + ClassDeclaration.object = null; + ClassDeclaration.throwable = null; + ClassDeclaration.exception = null; + ClassDeclaration.errorException = null; + ClassDeclaration.cpp_type_info_ptr = null; + + StructDeclaration.xerreq = null; + StructDeclaration.xerrcmp = null; + + Type.dtypeinfo = null; + Type.typeinfoclass = null; + Type.typeinfointerface = null; + Type.typeinfostruct = null; + Type.typeinfopointer = null; + Type.typeinfoarray = null; + Type.typeinfostaticarray = null; + Type.typeinfoassociativearray = null; + Type.typeinfovector = null; + Type.typeinfoenum = null; + Type.typeinfofunction = null; + Type.typeinfodelegate = null; + Type.typeinfotypelist = null; + Type.typeinfoconst = null; + Type.typeinfoinvariant = null; + Type.typeinfoshared = null; + Type.typeinfowild = null; + Type.rtinfo = null; + } + Objc._init(); + + Module._init(); + Module.amodules = Module.amodules.init; + Module.deferred = Dsymbols(); // deferred Dsymbol's needing semantic() run on them + Module.deferred2 = Dsymbols(); // deferred Dsymbol's needing semantic2() run on them + Module.deferred3 = Dsymbols(); // deferred Dsymbol's needing semantic3() run on them + Module.dprogress = 0; // progress resolving the deferred list + + dinterpret_init(); + + clearSemanticStatics(); +} + +// plain copy of dmd.mars.addDefaultVersionIdentifiers +void addDefaultVersionIdentifiers(const ref Param params) +{ + VersionCondition.addPredefinedGlobalIdent("DigitalMars"); + if (params.isWindows) + { + VersionCondition.addPredefinedGlobalIdent("Windows"); + if (global.params.mscoff) + { + VersionCondition.addPredefinedGlobalIdent("CRuntime_Microsoft"); + VersionCondition.addPredefinedGlobalIdent("CppRuntime_Microsoft"); + } + else + { + VersionCondition.addPredefinedGlobalIdent("CRuntime_DigitalMars"); + VersionCondition.addPredefinedGlobalIdent("CppRuntime_DigitalMars"); + } + } + else if (params.isLinux) + { + VersionCondition.addPredefinedGlobalIdent("Posix"); + VersionCondition.addPredefinedGlobalIdent("linux"); + VersionCondition.addPredefinedGlobalIdent("ELFv1"); + VersionCondition.addPredefinedGlobalIdent("CRuntime_Glibc"); + VersionCondition.addPredefinedGlobalIdent("CppRuntime_Gcc"); + } + else if (params.isOSX) + { + VersionCondition.addPredefinedGlobalIdent("Posix"); + VersionCondition.addPredefinedGlobalIdent("OSX"); + VersionCondition.addPredefinedGlobalIdent("CppRuntime_Clang"); + // For legacy compatibility + VersionCondition.addPredefinedGlobalIdent("darwin"); + } + else if (params.isFreeBSD) + { + VersionCondition.addPredefinedGlobalIdent("Posix"); + VersionCondition.addPredefinedGlobalIdent("FreeBSD"); + VersionCondition.addPredefinedGlobalIdent("ELFv1"); + VersionCondition.addPredefinedGlobalIdent("CppRuntime_Clang"); + } + else if (params.isOpenBSD) + { + VersionCondition.addPredefinedGlobalIdent("Posix"); + VersionCondition.addPredefinedGlobalIdent("OpenBSD"); + VersionCondition.addPredefinedGlobalIdent("ELFv1"); + VersionCondition.addPredefinedGlobalIdent("CppRuntime_Gcc"); + } + else if (params.isDragonFlyBSD) + { + VersionCondition.addPredefinedGlobalIdent("Posix"); + VersionCondition.addPredefinedGlobalIdent("DragonFlyBSD"); + VersionCondition.addPredefinedGlobalIdent("ELFv1"); + VersionCondition.addPredefinedGlobalIdent("CppRuntime_Gcc"); + } + else if (params.isSolaris) + { + VersionCondition.addPredefinedGlobalIdent("Posix"); + VersionCondition.addPredefinedGlobalIdent("Solaris"); + VersionCondition.addPredefinedGlobalIdent("ELFv1"); + VersionCondition.addPredefinedGlobalIdent("CppRuntime_Sun"); + } + else + { + assert(0); + } + VersionCondition.addPredefinedGlobalIdent("LittleEndian"); + VersionCondition.addPredefinedGlobalIdent("D_Version2"); + VersionCondition.addPredefinedGlobalIdent("all"); + + if (params.cpu >= CPU.sse2) + { + VersionCondition.addPredefinedGlobalIdent("D_SIMD"); + if (params.cpu >= CPU.avx) + VersionCondition.addPredefinedGlobalIdent("D_AVX"); + if (params.cpu >= CPU.avx2) + VersionCondition.addPredefinedGlobalIdent("D_AVX2"); + } + + if (params.is64bit) + { + VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86_64"); + VersionCondition.addPredefinedGlobalIdent("X86_64"); + if (params.isWindows) + { + VersionCondition.addPredefinedGlobalIdent("Win64"); + } + } + else + { + VersionCondition.addPredefinedGlobalIdent("D_InlineAsm"); //legacy + VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86"); + VersionCondition.addPredefinedGlobalIdent("X86"); + if (params.isWindows) + { + VersionCondition.addPredefinedGlobalIdent("Win32"); + } + } + + if (params.isLP64) + VersionCondition.addPredefinedGlobalIdent("D_LP64"); + if (params.doDocComments) + VersionCondition.addPredefinedGlobalIdent("D_Ddoc"); + if (params.cov) + VersionCondition.addPredefinedGlobalIdent("D_Coverage"); + if (params.pic != PIC.fixed) + VersionCondition.addPredefinedGlobalIdent(params.pic == PIC.pic ? "D_PIC" : "D_PIE"); + if (params.useUnitTests) + VersionCondition.addPredefinedGlobalIdent("unittest"); + if (params.useAssert == CHECKENABLE.on) + VersionCondition.addPredefinedGlobalIdent("assert"); + if (params.useArrayBounds == CHECKENABLE.off) + VersionCondition.addPredefinedGlobalIdent("D_NoBoundsChecks"); + if (params.betterC) + { + VersionCondition.addPredefinedGlobalIdent("D_BetterC"); + } + else + { + VersionCondition.addPredefinedGlobalIdent("D_ModuleInfo"); + VersionCondition.addPredefinedGlobalIdent("D_Exceptions"); + VersionCondition.addPredefinedGlobalIdent("D_TypeInfo"); + } + + VersionCondition.addPredefinedGlobalIdent("D_HardFloat"); +} + diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index 7d8503d8..5e5bd5d6 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -8,6 +8,7 @@ module vdc.dmdserver.dmdserver; import vdc.dmdserver.semvisitor; +import vdc.dmdserver.dmdinit; version(MAIN) {} else version = noServer; @@ -15,45 +16,19 @@ version(noServer): import vdc.ivdserver; import vdc.semanticopt; -import dmd.apply; import dmd.arraytypes; -import dmd.builtin; import dmd.cond; import dmd.console; -import dmd.ctfeexpr; -import dmd.dclass; -import dmd.declaration; -import dmd.dimport; -import dmd.dinterpret; import dmd.dmodule; -import dmd.dscope; -import dmd.dstruct; -import dmd.dsymbol; import dmd.dsymbolsem; -import dmd.dtemplate; import dmd.errors; -import dmd.expression; -import dmd.func; import dmd.globals; -import dmd.hdrgen; -import dmd.id; import dmd.identifier; -import dmd.init; -import dmd.mtype; -import dmd.objc; -import dmd.sapply; import dmd.semantic2; import dmd.semantic3; -import dmd.statement; -import dmd.target; -import dmd.tokens; -import dmd.visitor; -import dmd.root.outbuffer; import dmd.root.file; -import dmd.root.filename; import dmd.root.rmem; -import dmd.root.rootobject; //import vdc.util; struct TextPos @@ -146,9 +121,6 @@ version(DebugServer) } } -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] - /////////////////////////////////////////////////////////////// enum ModuleState { @@ -926,46 +898,7 @@ class DMDServer : ComObject, IVDServer } if (mPredefineVersions) - { - VersionCondition.addPredefinedGlobalIdent("DigitalMars"); - VersionCondition.addPredefinedGlobalIdent("Windows"); - VersionCondition.addPredefinedGlobalIdent("LittleEndian"); - VersionCondition.addPredefinedGlobalIdent("D_Version2"); - VersionCondition.addPredefinedGlobalIdent("all"); - if (global.params.is64bit) - { - VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86_64"); - VersionCondition.addPredefinedGlobalIdent("X86_64"); - VersionCondition.addPredefinedGlobalIdent("Win64"); - } - else - { - VersionCondition.addPredefinedGlobalIdent("D_InlineAsm"); //legacy - VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86"); - VersionCondition.addPredefinedGlobalIdent("X86"); - VersionCondition.addPredefinedGlobalIdent("Win32"); - } - if (global.params.mscoff || global.params.is64bit) - VersionCondition.addPredefinedGlobalIdent("CRuntime_Microsoft"); - else - VersionCondition.addPredefinedGlobalIdent("CRuntime_DigitalMars"); - if (global.params.isLP64) - VersionCondition.addPredefinedGlobalIdent("D_LP64"); - if (global.params.doDocComments) - VersionCondition.addPredefinedGlobalIdent("D_Ddoc"); - if (global.params.cov) - VersionCondition.addPredefinedGlobalIdent("D_Coverage"); - if (global.params.pic) - VersionCondition.addPredefinedGlobalIdent("D_PIC"); - if (global.params.useUnitTests) - VersionCondition.addPredefinedGlobalIdent("unittest"); - if (global.params.useAssert) - VersionCondition.addPredefinedGlobalIdent("assert"); - if (global.params.useArrayBounds == CHECKENABLE.off) - VersionCondition.addPredefinedGlobalIdent("D_NoBoundsChecks"); - if (global.params.betterC) - VersionCondition.addPredefinedGlobalIdent("D_betterC"); - } + addDefaultVersionIdentifiers(global.params); // always enable for tooltips global.params.doDocComments = true; @@ -1053,33 +986,6 @@ else } private: - static void clearModule(Module m) - { - m.insearch = 0; - m.searchCacheIdent = null; - m.searchCacheSymbol = null; // cached value of search - m.searchCacheFlags = 0; // cached flags - - m.importedFrom = null; - m.decldefs = null; // top level declarations for this Module - m.aimports = Modules(); // all imported modules - - m.debuglevel = 0; // debug level - m.debugids = null; // debug identifiers - m.debugidsNot = null; // forward referenced debug identifiers - - m.versionlevel = 0; // version level - m.versionids = null; // version identifiers - m.versionidsNot = null; // forward referenced version identifiers - - m.macrotable = null; // document comment macros - m.escapetable = null; // document comment escapes - - m._scope = null; // !=null means context to use for semantic() - m.prettystring = null; // cached value of toPrettyChars() - m.errors = 0; // this symbol failed to pass semantic() - } - ModuleData* findModule(string fname, bool createNew) { size_t pos = mModules.length; @@ -1241,189 +1147,6 @@ int _stricmp(const(wchar)*str1, wstring s2) nothrow return icmp(s1, s2); } -//////////////////////////////////////////////////////////////// -alias countersType = uint[uint]; // actually uint[Key] - -enum string[2][] dmdStatics = -[ - ["_D3dmd5clone12buildXtoHashFCQBa7dstruct17StructDeclarationPSQCg6dscope5ScopeZ8tftohashCQDh5mtype12TypeFunction", "TypeFunction"], - ["_D3dmd7dstruct15search_toStringRCQBfQBe17StructDeclarationZ10tftostringCQCs5mtype12TypeFunction", "TypeFunction"], - ["_D3dmd13expressionsem11loadStdMathFZ10impStdMathCQBv7dimport6Import", "Import"], - ["_D3dmd4func15FuncDeclaration8genCfuncRPSQBm4root5array__T5ArrayTCQCl5mtype9ParameterZQBcCQDjQy4TypeCQDu10identifier10IdentifiermZ2stCQFb7dsymbol12DsymbolTable", "DsymbolTable"], - ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ3feqCQEn4func15FuncDeclaration", "FuncDeclaration"], - ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ4fcmpCQEo4func15FuncDeclaration", "FuncDeclaration"], - ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ5fhashCQEp4func15FuncDeclaration", "FuncDeclaration"], - ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDdQBc8DotIdExpiZ11visitAArrayMFCQEkQDq10TypeAArrayZ8fd_aaLenCQFn4func15FuncDeclaration", "FuncDeclaration"], - ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDdQBc8DotIdExpiZ8noMemberMFQDlQDaQClCQEp10identifier10IdentifieriZ4nesti", "int"], - ["_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBufferkPkAxaZ4nesti", "int"], // x86 - ["_D3dmd7dmodule6Module19runDeferredSemanticRZ6nestedi", "int"], - ["_D3dmd10dsymbolsem22DsymbolSemanticVisitor5visitMRCQBx9dtemplate13TemplateMixinZ4nesti", "int"], - ["_D3dmd9dtemplate16TemplateInstance16tryExpandMembersMFPSQCc6dscope5ScopeZ4nesti", "int"], - ["_D3dmd9dtemplate16TemplateInstance12trySemantic3MFPSQBy6dscope5ScopeZ4nesti", "int"], - ["_D3dmd13expressionsem25ExpressionSemanticVisitor5visitMRCQCd10expression7CallExpZ4nesti", "int"], - ["_D3dmd5lexer5Lexer12stringbufferSQBf4root9outbuffer9OutBuffer", "OutBuffer"], - ["_D3dmd10expression10IntegerExp__T7literalVii0ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], - ["_D3dmd10expression10IntegerExp__T7literalVii1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], - ["_D3dmd10expression10IntegerExp__T7literalViN1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], - ["_D3dmd10identifier10Identifier17generateIdWithLocFNbAyaKxSQCe7globals3LocZ8countersHSQDfQDeQCvQCmFNbQBwKxQBwZ3Keyk", "countersType"], - ["_D3dmd10identifier10Identifier10generateIdRNbPxaZ1im", "int"], - ["_D3dmd5lexer5Lexer4scanMFNbPSQBb6tokens5TokenZ8initdoneb", "bool"], -]; - -string cmangled(string s) -{ - version (Win64) - if (s == "_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBufferkPkAxaZ4nesti") - return "_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBuffermPmAxaZ4nesti"; - return s; -} - -string genDeclDmdStatics() -{ - string s; - foreach (decl; dmdStatics) - s ~= q{extern extern(C) __gshared } ~ decl[1] ~ " " ~ cmangled(decl[0]) ~ ";\n"; - return s; -} - -string genInitDmdStatics() -{ - string s; - foreach (decl; dmdStatics) - s ~= cmangled(decl[0]) ~ " = " ~ decl[1] ~ ".init;\n"; - return s; -} - -mixin(genDeclDmdStatics); - -pragma(mangle, "_D3dmd12statementsem24StatementSemanticVisitor5visitMRCQCb9statement16ForeachStatementZ7fdapplyPCQDr4func15FuncDeclaration") -extern __gshared FuncDeclaration* statementsem_fdapply; -pragma(mangle, "_D3dmd12statementsem24StatementSemanticVisitor5visitMRCQCb9statement16ForeachStatementZ6fldeTyPCQDq5mtype12TypeDelegate") -extern __gshared TypeDelegate* statementsem_fldeTy; - - -void clearSemanticStatics() -{ - /* - import core.demangle; - static foreach(s; dmdStatics) - pragma(msg, demangle(s[0])); - */ - mixin(genInitDmdStatics); - - // statementsem - // static __gshared FuncDeclaration* fdapply = [null, null]; - // static __gshared TypeDelegate* fldeTy = [null, null]; - statementsem_fdapply[0] = statementsem_fdapply[1] = null; - statementsem_fldeTy[0] = statementsem_fldeTy[1] = null; - - // dmd.dtemplate - emptyArrayElement = null; - TemplateValueParameter.edummies = null; - TemplateTypeParameter.tdummy = null; - TemplateAliasParameter.sdummy = null; - - CtfeStatus.callDepth = 0; - CtfeStatus.stackTraceCallsToSuppress = 0; - CtfeStatus.maxCallDepth = 0; - CtfeStatus.numAssignments = 0; - - VarDeclaration.nextSequenceNumber = 0; - - // Package.this.packageTag? - // funcDeclarationSemantic.printedMain? -/+ - Type.stringtable.reset(); - - dinterpret_init(); - - Scope.freelist = null; - //Token.freelist = null; - - Identifier.initTable(); -+/ -} - -// initialization that are necessary once -void dmdInit() -{ - __gshared bool initialized; - if (initialized) - return; - initialized = true; - - import dmd.root.longdouble; - // Initialization - version(CRuntime_Microsoft) - initFPU(); - - global.params.isWindows = true; - global._init(); - Token._init(); - Id.initialize(); - Expression._init(); - builtin_init(); - - target._init(global.params); // needed by Type._init - Type._init(); - - dmdReinit(true); -} - -// initialization that are necessary before restarting an analysis (which might run -// for another platform/architecture) -void dmdReinit(bool configChanged) -{ - if (configChanged) - { - target._init(global.params); // needed by Type._init - Type._reinit(); - - // assume object.d unmodified otherwis - Module.moduleinfo = null; - - ClassDeclaration.object = null; - ClassDeclaration.throwable = null; - ClassDeclaration.exception = null; - ClassDeclaration.errorException = null; - ClassDeclaration.cpp_type_info_ptr = null; - - StructDeclaration.xerreq = null; - StructDeclaration.xerrcmp = null; - - Type.dtypeinfo = null; - Type.typeinfoclass = null; - Type.typeinfointerface = null; - Type.typeinfostruct = null; - Type.typeinfopointer = null; - Type.typeinfoarray = null; - Type.typeinfostaticarray = null; - Type.typeinfoassociativearray = null; - Type.typeinfovector = null; - Type.typeinfoenum = null; - Type.typeinfofunction = null; - Type.typeinfodelegate = null; - Type.typeinfotypelist = null; - Type.typeinfoconst = null; - Type.typeinfoinvariant = null; - Type.typeinfoshared = null; - Type.typeinfowild = null; - Type.rtinfo = null; - } - Objc._init(); - - Module._init(); - Module.amodules = Module.amodules.init; - Module.deferred = Dsymbols(); // deferred Dsymbol's needing semantic() run on them - Module.deferred2 = Dsymbols(); // deferred Dsymbol's needing semantic2() run on them - Module.deferred3 = Dsymbols(); // deferred Dsymbol's needing semantic3() run on them - Module.dprogress = 0; // progress resolving the deferred list - - dinterpret_init(); - - clearSemanticStatics(); -} - //////////////////////////////////////////////////////////////// extern(C) int _CrtDumpMemoryLeaks(); diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index 02bfdcca..e7d2854d 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -1606,6 +1606,7 @@ + Date: Sun, 4 Aug 2019 19:54:58 +0200 Subject: [PATCH 25/73] move error code to dmderrors.d --- vdc/dmdserver/ddmdmars.d | 23 ------ vdc/dmdserver/dmderrors.d | 118 ++++++++++++++++++++++++++++ vdc/dmdserver/dmdinit.d | 3 + vdc/dmdserver/dmdserver.d | 118 +--------------------------- vdc/dmdserver/dmdserver.visualdproj | 2 +- vdc/dmdserver/semvisitor.d | 18 ++++- 6 files changed, 141 insertions(+), 141 deletions(-) delete mode 100644 vdc/dmdserver/ddmdmars.d create mode 100644 vdc/dmdserver/dmderrors.d diff --git a/vdc/dmdserver/ddmdmars.d b/vdc/dmdserver/ddmdmars.d deleted file mode 100644 index 1728ceeb..00000000 --- a/vdc/dmdserver/ddmdmars.d +++ /dev/null @@ -1,23 +0,0 @@ - -module dmd.mars; -import dmd.dscope; -import dmd.root.rmem; - -extern (C++) void genCmain(Scope* sc) -{ -} - -extern (C++) void *mem_malloc(size_t u) -{ - return mem.xmalloc(u); -} - -extern (C++) void mem_free(void* p) -{ - mem.xfree(p); -} - -extern (C) void* allocmemory(size_t size) nothrow -{ - return GC.malloc(size); -} diff --git a/vdc/dmdserver/dmderrors.d b/vdc/dmdserver/dmderrors.d new file mode 100644 index 00000000..18fb45d7 --- /dev/null +++ b/vdc/dmdserver/dmderrors.d @@ -0,0 +1,118 @@ + +module vdc.dmdserver.dmderrors; + +import dmd.console; +import dmd.errors; +import dmd.globals; + +import std.ascii; +import std.string; + +import core.stdc.stdarg; +import core.stdc.stdio; +import core.stdc.stdlib; +import core.stdc.string; +import core.stdc.wchar_ : wcslen; + +shared(Object) gErrorSync = new Object; +__gshared string gErrorFile; +__gshared char[] gErrorMessages; +__gshared char[] gOtherErrorMessages; +__gshared bool gErrorWasSupplemental; + +void errorPrint(const ref Loc loc, Color headerColor, const(char)* header, + const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) nothrow +{ + if (!loc.filename) + return; + + try synchronized(gErrorSync) + { + bool other = _stricmp(loc.filename, gErrorFile) != 0; + while (header && std.ascii.isWhite(*header)) + header++; + bool supplemental = !header && !*header; + + __gshared char[4096] buf; + int len = 0; + if (other) + { + len = snprintf(buf.ptr, buf.length, "%s(%d):", loc.filename, loc.linnum); + } + else + { + int llen = snprintf(buf.ptr, buf.length, "%d,%d,%d,%d:", loc.linnum, loc.charnum - 1, loc.linnum, loc.charnum); + gErrorMessages ~= buf[0..llen]; + if (supplemental) + gErrorMessages ~= gOtherErrorMessages; + gOtherErrorMessages = null; + } + if (p1 && len < buf.length) + len += snprintf(buf.ptr + len, buf.length - len, "%s ", p1); + if (p2 && len < buf.length) + len += snprintf(buf.ptr + len, buf.length - len, "%s ", p2); + if (len < buf.length) + len += vsnprintf(buf.ptr + len, buf.length - len, format, ap); + char nl = other ? '\a' : '\n'; + if (len < buf.length) + buf[len++] = nl; + else + buf[$-1] = nl; + + version(DebugServer) dbglog(buf[0..len]); + + if (other) + { + if (gErrorWasSupplemental) + { + if (gErrorMessages.length && gErrorMessages[$-1] == '\n') + gErrorMessages[$-1] = '\a'; + gErrorMessages ~= buf[0..len]; + gErrorMessages ~= '\n'; + } + else if (supplemental) + gOtherErrorMessages ~= buf[0..len]; + else + { + gErrorWasSupplemental = false; + gOtherErrorMessages = buf[0..len].dup; + } + } + else + { + gErrorMessages ~= buf[0..len]; + gErrorWasSupplemental = supplemental; + } + } + catch(Exception e) + { + + } +} + +void initErrorFile(string fname) +{ + synchronized(gErrorSync) + { + gErrorFile = fname; + gErrorMessages = null; + gOtherErrorMessages = null; + gErrorWasSupplemental = false; + + import std.functional; + diagnosticHandler = toDelegate(&errorPrint); + } +} + +int _stricmp(const(char)*str1, string s2) nothrow +{ + const(char)[] s1 = str1[0..strlen(str1)]; + return icmp(s1, s2); +} + +int _stricmp(const(wchar)*str1, wstring s2) nothrow +{ + const(wchar)[] s1 = str1[0..wcslen(str1)]; + return icmp(s1, s2); +} + diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d index d12adc50..31631bf3 100644 --- a/vdc/dmdserver/dmdinit.d +++ b/vdc/dmdserver/dmdinit.d @@ -3,6 +3,7 @@ module vdc.dmdserver.dmdinit; import dmd.arraytypes; import dmd.builtin; import dmd.cond; +import dmd.compiler; import dmd.ctfeexpr; import dmd.dclass; import dmd.declaration; @@ -111,6 +112,8 @@ void clearSemanticStatics() VarDeclaration.nextSequenceNumber = 0; + entrypoint = cast(Module)&entrypoint; // disable generation of C main + // Package.this.packageTag? // funcDeclarationSemantic.printedMain? /+ diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index 65d664f4..fcf55076 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -9,6 +9,7 @@ module vdc.dmdserver.dmdserver; import vdc.dmdserver.semvisitor; import vdc.dmdserver.dmdinit; +import vdc.dmdserver.dmderrors; version(MAIN) {} else version = noServer; @@ -18,7 +19,6 @@ import vdc.semanticopt; import dmd.arraytypes; import dmd.cond; -import dmd.console; import dmd.dmodule; import dmd.dsymbolsem; import dmd.errors; @@ -334,7 +334,7 @@ class DMDServer : ComObject, IVDServer try { initErrorFile(fname); - parseModule(modData, text); + modData.parsedModule = createModuleFromText(fname, text); } catch(OutOfMemoryError e) { @@ -797,16 +797,6 @@ class DMDServer : ComObject, IVDServer } } - void parseModule(ModuleData* md, string text) - { - string name = stripExtension(baseName(md.filename)); - auto id = Identifier.idPool(name); - md.parsedModule = new Module(md.filename, id, true, false); - md.parsedModule.srcBuffer = new FileBuffer(cast(ubyte[])text); - md.parsedModule.read(Loc.initial); - md.parsedModule.parse(); - } - void analyzeModules(ModuleData* rootModule) { version(none) @@ -1043,110 +1033,6 @@ private: SysTime mNextReadyMessage; } -shared(Object) gErrorSync = new Object; -__gshared string gErrorFile; -__gshared char[] gErrorMessages; -__gshared char[] gOtherErrorMessages; -__gshared bool gErrorWasSupplemental; - -void errorPrint(const ref Loc loc, Color headerColor, const(char)* header, - const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) nothrow -{ - if (!loc.filename) - return; - - import dmd.errors; - - try synchronized(gErrorSync) - { - bool other = _stricmp(loc.filename, gErrorFile) != 0; - while (header && std.ascii.isWhite(*header)) - header++; - bool supplemental = !header && !*header; - - __gshared char[4096] buf; - int len = 0; - if (other) - { - len = snprintf(buf.ptr, buf.length, "%s(%d):", loc.filename, loc.linnum); - } - else - { - int llen = snprintf(buf.ptr, buf.length, "%d,%d,%d,%d:", loc.linnum, loc.charnum - 1, loc.linnum, loc.charnum); - gErrorMessages ~= buf[0..llen]; - if (supplemental) - gErrorMessages ~= gOtherErrorMessages; - gOtherErrorMessages = null; - } - if (p1 && len < buf.length) - len += snprintf(buf.ptr + len, buf.length - len, "%s ", p1); - if (p2 && len < buf.length) - len += snprintf(buf.ptr + len, buf.length - len, "%s ", p2); - if (len < buf.length) - len += vsnprintf(buf.ptr + len, buf.length - len, format, ap); - char nl = other ? '\a' : '\n'; - if (len < buf.length) - buf[len++] = nl; - else - buf[$-1] = nl; - - version(DebugServer) dbglog(buf[0..len]); - - if (other) - { - if (gErrorWasSupplemental) - { - if (gErrorMessages.length && gErrorMessages[$-1] == '\n') - gErrorMessages[$-1] = '\a'; - gErrorMessages ~= buf[0..len]; - gErrorMessages ~= '\n'; - } - else if (supplemental) - gOtherErrorMessages ~= buf[0..len]; - else - { - gErrorWasSupplemental = false; - gOtherErrorMessages = buf[0..len].dup; - } - } - else - { - gErrorMessages ~= buf[0..len]; - gErrorWasSupplemental = supplemental; - } - } - catch(Exception e) - { - - } -} - -void initErrorFile(string fname) -{ - synchronized(gErrorSync) - { - gErrorFile = fname; - gErrorMessages = null; - gOtherErrorMessages = null; - gErrorWasSupplemental = false; - - import std.functional; - diagnosticHandler = toDelegate(&errorPrint); - } -} - -int _stricmp(const(char)*str1, string s2) nothrow -{ - const(char)[] s1 = str1[0..strlen(str1)]; - return icmp(s1, s2); -} - -int _stricmp(const(wchar)*str1, wstring s2) nothrow -{ - const(wchar)[] s1 = str1[0..wcslen(str1)]; - return icmp(s1, s2); -} - //////////////////////////////////////////////////////////////// extern(C) int _CrtDumpMemoryLeaks(); diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index e7d2854d..5dcecdac 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -1604,7 +1604,7 @@ - + diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 6d7ae870..e8291a49 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -739,7 +739,7 @@ extern(C++) class FindTipVisitor : FindASTVisitor } // append doc if (doc) - tip = tip ~ "\n" ~ cast(string)doc[0..strlen(doc)]; + tip = tip ~ "\n\n" ~ strip(cast(string)doc[0..strlen(doc)]); stop = true; } return stop; @@ -1191,3 +1191,19 @@ Module cloneModule(Module mo) m.accept(v); return m; } + +Module createModuleFromText(string filename, string text) +{ + import std.path; + + string name = stripExtension(baseName(filename)); + auto id = Identifier.idPool(name); + auto mod = new Module(filename, id, true, false); + mod.srcBuffer = new FileBuffer(cast(ubyte[])text); + mod.read(Loc.initial); + mod.parse(); + return mod; +} + +//////////////////////////////////////////////////////////////////////////////// + From 6502a5ed502c417dfbebcb05325d8d1cb8d8c65c Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 16 Aug 2019 16:21:50 +0200 Subject: [PATCH 26/73] adapt to recent compiler move generating findReferences text anser to server refactor dmd-init --- tools/tracegc.d | 116 +++++++++++++-- vdc/dmdserver/dmdinit.d | 223 +++++++++++++++++++++++----- vdc/dmdserver/dmdserver.d | 39 +++-- vdc/dmdserver/dmdserver.visualdproj | 8 +- vdc/dmdserver/semvisitor.d | 44 +++--- visuald/colorizer.d | 15 +- visuald/dlangsvc.d | 30 ---- 7 files changed, 343 insertions(+), 132 deletions(-) diff --git a/tools/tracegc.d b/tools/tracegc.d index b44b107c..b5bd4c4a 100644 --- a/tools/tracegc.d +++ b/tools/tracegc.d @@ -411,10 +411,16 @@ class GCTraceProxy : GC return gc.rangeIter(); } - void runFinalizers(in void[] segment) nothrow - { - return gc.runFinalizers(segment); - } + //static if (__VERSION__ >= 2087) + void runFinalizers(scope const void[] segment) nothrow + { + return gc.runFinalizers(segment); + } + //else + void runFinalizers(in void[] segment) nothrow + { + return gc.runFinalizers(segment); + } bool inFinalizer() nothrow { @@ -745,9 +751,14 @@ void dumpAddrInfoStat() trace_printf("\n"); } +HashTab!(void*, void*)**pp_references; + /////////////////////////////////////////////////////////////// import rt.util.container.hashtab; +alias ScanRange = Gcx.ScanRange!false; +Gcx.ToScanStack!ScanRange toscan; // dmd BUG: alignment causes bad capture! + void collectReferences(ConservativeGC cgc, ref HashTab!(void*, void*) references, ref HashTab!(void*, size_t) objects) { auto gcx = cgc.gcx; @@ -755,10 +766,6 @@ void collectReferences(ConservativeGC cgc, ref HashTab!(void*, void*) references cgc.gcLock.lock(); auto pooltable = gcx.pooltable; - alias ScanRange = Gcx.ScanRange!false; - - Gcx.ToScanStack!ScanRange toscan; - /** * Search a range of memory values and mark any pointers into the GC pool. */ @@ -772,6 +779,10 @@ void collectReferences(ConservativeGC cgc, ref HashTab!(void*, void*) references size_t stackPos; ScanRange[FANOUT_LIMIT] stack = void; + import core.stdc.stdlib; + if (&references != *pp_references) + exit(1); + Lagain: size_t pcache = 0; @@ -1096,8 +1107,71 @@ void dumpGC(GC _gc) findRoot(null); } +shared static this() +{ + import dmd.identifier; + Identifier.anonymous(); +} + +const(char)[] dmdident(ConservativeGC cgc, void* p) +{ + import dmd.dsymbol; + import dmd.identifier; + + BlkInfo inf = cgc.queryNoSync(p); + if (inf.base is null || inf.size < Dsymbol.sizeof) + return null; + + auto dummyIdent = Identifier.anonymous(); + auto sym = cast(Dsymbol)p; + auto ident = sym.ident; + BlkInfo syminf = cgc.queryNoSync(cast(void*)ident); + if (syminf.base is null || syminf.size < Identifier.sizeof) + return null; + if (*cast(void**)dummyIdent !is *cast(void**)ident) + return null; // not an Identifier + + __gshared char[256] buf; + int len = sprintf(buf.ptr, "sym %.*s", ident.toString().length, ident.toString().ptr); + return buf[0..len]; +} + +bool isInImage(void* p) +{ + import core.internal.traits : externDFunc; + alias findImageSection = externDFunc!("rt.sections_win64.findImageSection", void[] function(string) nothrow @nogc); + void[] dataSection = findImageSection(".data"); + + if (p - dataSection.ptr < dataSection.length) + return true; + return false; +} + +const(char)[] dmdtype(ConservativeGC cgc, void* p) +{ + import dmd.mtype; + import dmd.identifier; + + BlkInfo inf = cgc.queryNoSync(p); + if (inf.base is null || inf.size < Type.sizeof) + return null; + + auto vtbl = *cast(void***)p; + if (!isInImage(vtbl)) + return null; + auto func = vtbl[5]; + Type type = cast(Type)p; + if (func != (&type.dyncast).funcptr) + return null; + + __gshared char[256] buf; + int len = sprintf(buf.ptr, "type %s %s", type.kind(), type.deco); + return buf[0..len]; +} + void findRoot(void* sobj) { + //sobj = cast(void*)1; if (!sobj) return; @@ -1106,6 +1180,10 @@ void findRoot(void* sobj) HashTab!(void*, void*) references; HashTab!(void*, size_t) objects; + + HashTab!(void*, void*)* preferences = &references; + pp_references = &preferences; + collectReferences(cgc, references, objects); const(void*) minAddr = cgc.gcx.pooltable.minAddr; @@ -1124,10 +1202,13 @@ nextLoc: if (te && (ai = te.resolve()) !is null) { const(char)* filename = stringBuffer.ptr + ai.filenameOff; - trace_printf("%s(%d): %p\n", filename, ai.line, sobj); + auto id = dmdident(cgc, sobj); + if (!id) + id = dmdtype(cgc, sobj); + xtrace_printf("%s(%d): %p %.*s\n", filename, ai.line, sobj, id.length, id.ptr); } else - trace_printf("no location: %p\n", sobj); + xtrace_printf("no location: %p\n", sobj); ulong src; if (auto psrc = sobj in references) @@ -1155,7 +1236,7 @@ nextLoc: else base -= 0x1000; } - trace_printf("%p not a heap object\n", *psrc); + xtrace_printf("%p not a heap object\n", *psrc); DWORD64 disp; char[300] symbuf; @@ -1164,7 +1245,7 @@ nextLoc: sym.MaxNameLength = 300 - IMAGEHLP_SYMBOLA64.sizeof; if (dbghelp.SymGetSymFromAddr64(hProcess, cast(size_t)*psrc, &disp, sym)) - trace_printf(" sym %s + %lld\n", sym.Name.ptr, disp); + xtrace_printf(" sym %s + %lld\n", sym.Name.ptr, disp); } break; } @@ -1202,5 +1283,12 @@ private int trace_printf(ARGS...)(const char* fmt, ARGS args) nothrow return len; } -//sprintf(buf.ptr, "%s(%d): %p %llx\n", filename, line, addr, cast(long) size); -//OutputDebugStringA(buf.ptr); +private int xtrace_printf(ARGS...)(const char* fmt, ARGS args) nothrow +{ + char[1024] buf; + sprintf(buf.ptr, fmt, args); + OutputDebugStringA(buf.ptr); + + return trace_printf(fmt, args); +} + diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d index 31631bf3..a420284c 100644 --- a/vdc/dmdserver/dmdinit.d +++ b/vdc/dmdserver/dmdinit.d @@ -23,6 +23,9 @@ import dmd.target; import dmd.root.outbuffer; +import std.string; +import core.stdc.string; + //////////////////////////////////////////////////////////////// alias countersType = uint[uint]; // actually uint[Key] @@ -48,15 +51,19 @@ enum string[2][] dmdStatics = ["_D3dmd10expression10IntegerExp__T7literalVii1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], ["_D3dmd10expression10IntegerExp__T7literalViN1ZQnRZ11theConstantCQCkQCjQCa", "IntegerExp"], ["_D3dmd10identifier10Identifier17generateIdWithLocFNbAyaKxSQCe7globals3LocZ8countersHSQDfQDeQCvQCmFNbQBwKxQBwZ3Keyk", "countersType"], - ["_D3dmd10identifier10Identifier10generateIdRNbPxaZ1im", "int"], + ["_D3dmd10identifier10Identifier10generateIdRNbPxaZ1ik", "size_t"], ["_D3dmd5lexer5Lexer4scanMFNbPSQBb6tokens5TokenZ8initdoneb", "bool"], ]; string cmangled(string s) { version (Win64) + { + if (s == "_D3dmd10identifier10Identifier10generateIdRNbPxaZ1ik") + return "_D3dmd10identifier10Identifier10generateIdRNbPxaZ1im"; // size_t if (s == "_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBufferkPkAxaZ4nesti") return "_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBuffermPmAxaZ4nesti"; + } return s; } @@ -150,50 +157,186 @@ void dmdInit() target._init(global.params); // needed by Type._init Type._init(); - - dmdReinit(true); } -// initialization that are necessary before restarting an analysis (which might run -// for another platform/architecture) -void dmdReinit(bool configChanged) +struct Options { - if (configChanged) + string[] importDirs; + string[] stringImportDirs; + + bool unittestOn; + bool x64; + bool msvcrt; + bool debugOn; + bool coverage; + bool doDoc; + bool noBoundsCheck; + bool gdcCompiler; + bool ldcCompiler; + bool noDeprecated; + bool mixinAnalysis; + bool UFCSExpansions; + + bool predefineDefaultVersions; + int versionLevel; + string[] versionIds; + int debugLevel; + string[] debugIds; + + void opAssign(const ref Options opts) + { + import std.traits; + + static foreach(i, F; typeof(this).tupleof) + static if(isDynamicArray!(typeof(F))) + this.tupleof[i] = opts.tupleof[i].dup; + else + this.tupleof[i] = opts.tupleof[i]; + } + + bool setImportDirs(string[] dirs) + { + if(dirs == importDirs) + return false; + importDirs = dirs; + return true; + } + bool setStringImportDirs(string[] dirs) { - target._init(global.params); // needed by Type._init - Type._reinit(); - - // assume object.d unmodified otherwis - Module.moduleinfo = null; - - ClassDeclaration.object = null; - ClassDeclaration.throwable = null; - ClassDeclaration.exception = null; - ClassDeclaration.errorException = null; - ClassDeclaration.cpp_type_info_ptr = null; - - StructDeclaration.xerreq = null; - StructDeclaration.xerrcmp = null; - - Type.dtypeinfo = null; - Type.typeinfoclass = null; - Type.typeinfointerface = null; - Type.typeinfostruct = null; - Type.typeinfopointer = null; - Type.typeinfoarray = null; - Type.typeinfostaticarray = null; - Type.typeinfoassociativearray = null; - Type.typeinfovector = null; - Type.typeinfoenum = null; - Type.typeinfofunction = null; - Type.typeinfodelegate = null; - Type.typeinfotypelist = null; - Type.typeinfoconst = null; - Type.typeinfoinvariant = null; - Type.typeinfoshared = null; - Type.typeinfowild = null; - Type.rtinfo = null; + if(dirs == stringImportDirs) + return false; + stringImportDirs = dirs; + return true; } + bool setVersionIds(int level, string[] ids) + { + if(versionLevel == level && versionIds == ids) + return false; + versionLevel = level; + versionIds == ids; + return true; + } + bool setDebugIds(int level, string[] ids) + { + if(debugLevel == level && debugIds == ids) + return false; + debugLevel = level; + debugIds == ids; + return true; + } +} + +void dmdSetupParams(const ref Options opts) +{ + global = global.init; + + global._init(); + global.params.isWindows = true; + global.params.errorLimit = 0; + global.params.color = false; + global.params.link = true; + global.params.useAssert = opts.debugOn ? CHECKENABLE.on : CHECKENABLE.off; + global.params.useInvariants = opts.debugOn ? CHECKENABLE.on : CHECKENABLE.off; + global.params.useIn = opts.debugOn ? CHECKENABLE.on : CHECKENABLE.off; + global.params.useOut = opts.debugOn ? CHECKENABLE.on : CHECKENABLE.off; + global.params.useArrayBounds = opts.noBoundsCheck ? CHECKENABLE.on : CHECKENABLE.off; // set correct value later + global.params.doDocComments = opts.doDoc; + global.params.useSwitchError = CHECKENABLE.on; + global.params.useInline = false; + global.params.obj = false; + global.params.useDeprecated = opts.noDeprecated ? DiagnosticReporting.error : DiagnosticReporting.off; + global.params.linkswitches = Strings(); + global.params.libfiles = Strings(); + global.params.dllfiles = Strings(); + global.params.objfiles = Strings(); + global.params.ddocfiles = Strings(); + // Default to -m32 for 32 bit dmd, -m64 for 64 bit dmd + global.params.is64bit = opts.x64; + global.params.mscoff = opts.msvcrt; + global.params.cpu = CPU.baseline; + global.params.isLP64 = global.params.is64bit; + + global.params.versionlevel = opts.versionLevel; + global.params.versionids = new Strings(); + foreach(v; opts.versionIds) + global.params.versionids.push(toStringz(v)); + + global.versionids = new Identifiers(); + + // Add in command line versions + if (global.params.versionids) + foreach (charz; *global.params.versionids) + { + auto ident = charz[0 .. strlen(charz)]; + if (VersionCondition.isReserved(ident)) + VersionCondition.addPredefinedGlobalIdent(ident); + else + VersionCondition.addGlobalIdent(ident); + } + + if (opts.predefineDefaultVersions) + addDefaultVersionIdentifiers(global.params); + + // always enable for tooltips + global.params.doDocComments = true; + + global.params.debugids = new Strings(); + global.params.debuglevel = opts.debugLevel; + foreach(d; opts.debugIds) + global.params.debugids.push(toStringz(d)); + + global.debugids = new Identifiers(); + if (global.params.debugids) + foreach (charz; *global.params.debugids) + DebugCondition.addGlobalIdent(charz[0 .. strlen(charz)]); + + global.path = new Strings(); + foreach(i; opts.importDirs) + global.path.push(toStringz(i)); + + global.filePath = new Strings(); + foreach(i; opts.stringImportDirs) + global.filePath.push(toStringz(i)); +} + +// initialization that are necessary before restarting an analysis (which might run +// for another platform/architecture, different versions) +void dmdReinit() +{ + target._init(global.params); // needed by Type._init + Type._reinit(); + + // assume object.d unmodified otherwis + Module.moduleinfo = null; + + ClassDeclaration.object = null; + ClassDeclaration.throwable = null; + ClassDeclaration.exception = null; + ClassDeclaration.errorException = null; + ClassDeclaration.cpp_type_info_ptr = null; + + StructDeclaration.xerreq = null; + StructDeclaration.xerrcmp = null; + + Type.dtypeinfo = null; + Type.typeinfoclass = null; + Type.typeinfointerface = null; + Type.typeinfostruct = null; + Type.typeinfopointer = null; + Type.typeinfoarray = null; + Type.typeinfostaticarray = null; + Type.typeinfoassociativearray = null; + Type.typeinfovector = null; + Type.typeinfoenum = null; + Type.typeinfofunction = null; + Type.typeinfodelegate = null; + Type.typeinfotypelist = null; + Type.typeinfoconst = null; + Type.typeinfoinvariant = null; + Type.typeinfoshared = null; + Type.typeinfowild = null; + Type.rtinfo = null; + Objc._init(); Module._init(); diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index fcf55076..8520c7ca 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -7,15 +7,15 @@ // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt module vdc.dmdserver.dmdserver; -import vdc.dmdserver.semvisitor; import vdc.dmdserver.dmdinit; import vdc.dmdserver.dmderrors; +import vdc.dmdserver.semvisitor; +import vdc.dmdserver.semanalysis; version(MAIN) {} else version = noServer; version(noServer): import vdc.ivdserver; -import vdc.semanticopt; import dmd.arraytypes; import dmd.cond; @@ -71,8 +71,9 @@ import core.time; import core.stdc.stdio; import core.stdc.stdlib; import core.stdc.string; +import core.stdc.wchar_; -// version = traceGC; +//version = traceGC; version (traceGC) import tracegc; version = DebugServer; @@ -82,7 +83,7 @@ shared(Object) gDMDSync = new Object; // no multi-instances/multi-threading with shared(Object) gOptSync = new Object; // no multi-instances/multi-threading with DMD version (traceGC) - extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise", "gcopt=gc:trace" ]; + extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise", "gcopt=gc:trace disable:1" ]; else // precise GC doesn't help much because dmd erases most type info extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise", "gcopt=gc:precise" ]; @@ -156,7 +157,6 @@ class DMDServer : ComObject, IVDServer { version(unittest) {} else version(SingleThread) mTid = spawn(&taskLoop, thisTid); - mOptions = new Options; dmdInit(); } @@ -237,7 +237,7 @@ class DMDServer : ComObject, IVDServer synchronized(gOptSync) { - auto opts = mOptions; + auto opts = &mOptions; string imports = to_string(imp); string strImports = to_string(stringImp); @@ -675,7 +675,18 @@ class DMDServer : ComObject, IVDServer try { if (auto m = md.analyzedModule) - references = findReferences(m, line, idx + 1); + { + auto reflocs = findReferencesInModule(m, line, idx + 1); + + char[128] buf; + foreach (ref r; reflocs) + { + int llen = snprintf(buf.ptr, buf.length, "%d,%d,%d,%d:\n", + r.loc.linnum, r.loc.charnum - 1, + r.loc.linnum, r.loc.charnum - 1 + r.ident.toString().length); + references ~= buf[0..llen]; + } + } else references = "analyzing..."; } @@ -869,10 +880,10 @@ class DMDServer : ComObject, IVDServer global.params.cpu = CPU.baseline; global.params.isLP64 = global.params.is64bit; - global.params.versionlevel = mOptions.versionIds.level; + global.params.versionlevel = mOptions.versionLevel; global.params.versionids = new Strings(); - foreach(id, v; mOptions.versionIds.identifiers) - global.params.versionids.push(toStringz(id)); + foreach(v; mOptions.versionIds) + global.params.versionids.push(toStringz(v)); global.versionids = new Identifiers(); @@ -894,9 +905,9 @@ class DMDServer : ComObject, IVDServer global.params.doDocComments = true; global.params.debugids = new Strings(); - global.params.debuglevel = mOptions.debugIds.level; - foreach(id, v; mOptions.debugIds.identifiers) - global.params.debugids.push(toStringz(id)); + global.params.debuglevel = mOptions.debugLevel; + foreach(d; mOptions.debugIds) + global.params.debugids.push(toStringz(d)); global.debugids = new Identifiers(); if (global.params.debugids) @@ -912,7 +923,7 @@ class DMDServer : ComObject, IVDServer global.filePath.push(toStringz(i)); } - dmdReinit(true); + dmdReinit(); for (size_t i = 0; i < mModules.length; i++) { diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index 5dcecdac..6118f2b7 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -1306,7 +1306,7 @@ 0 - 0 + 2 $(VisualDInstallDir)cv2pdb\cv2pdb.exe 0 0 @@ -1398,7 +1398,7 @@ 1 1 c:\l\d\dmd2\windows\bin\dmd.exe - dmd\src ..\.. $(DMDInstallDir)\src\druntime\src + dmd\src ..\.. $(DMDInstallDir)\src\druntime\src $(DMDInstallDir)\druntime\src dmd dmd\res ..\..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -1604,8 +1604,8 @@ - + - + diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index e8291a49..bfea7f79 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -55,12 +55,13 @@ import dmd.root.rootobject; import std.string; import std.conv; +import core.stdc.string; // walk the complete AST (declarations, statement and expressions) // assumes being started on module/declaration level extern(C++) class ASTVisitor : StoppableVisitor { - alias visit = super.visit; + alias visit = StoppableVisitor.visit; void visitExpression(Expression expr) { @@ -362,7 +363,7 @@ extern(C++) class FindASTVisitor : ASTVisitor int endLine; int endIndex; - alias visit = super.visit; + alias visit = ASTVisitor.visit; RootObject found; ScopeDsymbol foundScope; @@ -620,7 +621,7 @@ extern(C++) class FindTipVisitor : FindASTVisitor { string tip; - alias visit = super.visit; + alias visit = FindASTVisitor.visit; this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) { @@ -760,7 +761,7 @@ extern(C++) class FindDefinitionVisitor : FindASTVisitor { Loc loc; - alias visit = super.visit; + alias visit = FindASTVisitor.visit; this(const(char*) filename, int startLine, int startIndex, int endLine, int endIndex) { @@ -827,7 +828,7 @@ int[] findBinaryIsInLocations(Module mod) int[] locdata; const(char)* filename; - alias visit = super.visit; + alias visit = ASTVisitor.visit; final void addLocation(const ref Loc loc) { @@ -871,7 +872,7 @@ string findIdentifierTypes(Module mod) IdTypePos[][const(char)[]] idTypes; const(char)* filename; - alias visit = super.visit; + alias visit = ASTVisitor.visit; extern(D) final void addTypePos(const(char)[] ident, int type, int line, int col) @@ -971,7 +972,13 @@ string findIdentifierTypes(Module mod) } //////////////////////////////////////////////////////////////////////////////// -string findReferences(Module mod, int line, int index) +struct Reference +{ + Loc loc; + Identifier ident; +} + +Reference[] findReferencesInModule(Module mod, int line, int index) { auto filename = mod.srcfile.toChars(); scope FindDefinitionVisitor fdv = new FindDefinitionVisitor(filename, line, index, line, index + 1); @@ -983,23 +990,15 @@ string findReferences(Module mod, int line, int index) extern(C++) class FindReferencesVisitor : ASTVisitor { RootObject search; - string references; + Reference[] references; - alias visit = super.visit; + alias visit = ASTVisitor.visit; extern(D) void addReference(ref const Loc loc, Identifier ident) { if (loc.filename && ident) - { - import core.stdc.stdio; - char[128] buf; - int llen = snprintf(buf.ptr, buf.length, "%d,%d,%d,%d:\n", - loc.linnum, loc.charnum - 1, - loc.linnum, loc.charnum + ident.toString().length - 1); - references ~= buf[0..llen]; - } - + references ~= Reference(loc, ident); } override void visit(Dsymbol sym) @@ -1091,12 +1090,13 @@ string[] findExpansions(Module mod, int line, int index, string tok) if (!ds) continue; - foreach (pair; sd.symtab.tab.asRange) + //foreach (pair; sd.symtab.tab.asRange) + foreach (key, s; sd.symtab.tab.aa) { - Dsymbol s = pair.value; + //Dsymbol s = pair.value; if (!symbolIsVisible(mod, s)) continue; - auto ident = pair.key.toString(); + auto ident = /*pair.*/(cast(Dsymbol)key).toString(); if (ident.startsWith(tok)) idmap[cast(void*)s] = ident.idup; } @@ -1167,7 +1167,7 @@ Module cloneModule(Module mo) this.m = m; } - alias visit = super.visit; + alias visit = ASTVisitor.visit; override void visit(ConditionalStatement cond) { diff --git a/visuald/colorizer.d b/visuald/colorizer.d index 02251d97..c40dce78 100644 --- a/visuald/colorizer.d +++ b/visuald/colorizer.d @@ -379,14 +379,13 @@ class Colorizer : DisposingComObject, IVsColorizer, ConfigModifiedListener else span = ParserSpan(prevpos, iLine, pos, iLine); - if(tok[0] == 'i') - if(tok == "in" || tok == "is") - { - if(langsvc.isBinaryOperator(mSource, iLine + 1, prevpos, iLine + 1, pos)) - type = userColorType(tok, TokenColor.Operator); - else - type = TokenColor.Keyword; - } + if(tok.length == 2 && tok[0] == 'i' && (tok[1] == 'n' || tok[1] == 's')) // in/is + { + if(langsvc.isBinaryOperator(mSource, iLine + 1, prevpos, iLine + 1, pos)) + type = userColorType(tok, TokenColor.Operator); + else + type = TokenColor.Keyword; + } if(cov >= 0) { diff --git a/visuald/dlangsvc.d b/visuald/dlangsvc.d index 01316539..e708d9e0 100644 --- a/visuald/dlangsvc.d +++ b/visuald/dlangsvc.d @@ -4252,36 +4252,6 @@ else return changed; } - // from D_Parser - enum TypeReferenceKind : uint - { - Unknown, - - Interface, - Enum, - EnumValue, - Template, - Class, - Struct, - Union, - TemplateTypeParameter, - - Constant, - LocalVariable, - ParameterVariable, - TLSVariable, - SharedVariable, - GSharedVariable, - MemberVariable, - Variable, - - Alias, - Module, - Function, - Method, - BasicType, - } - int convertTypeRefToColor(uint kind) { switch (kind) From 1fca42c51cdd3343a3181471d6c669a077d68ba8 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 23 Aug 2019 19:08:28 +0200 Subject: [PATCH 27/73] more dmdserver fixes/tweaks add missing semanalysis.d --- tools/tracegc.d | 2 +- vdc/dmdserver/dmdinit.d | 4 +- vdc/dmdserver/dmdserver.d | 17 +- vdc/dmdserver/dmdserver.visualdproj | 2 +- vdc/dmdserver/semanalysis.d | 413 +++++++++++++++++++++++++ vdc/dmdserver/semvisitor.d | 462 ++++++++++++++++++++-------- vdc/ivdserver.d | 1 + vdc/vdserverfactory.d | 5 +- 8 files changed, 759 insertions(+), 147 deletions(-) create mode 100644 vdc/dmdserver/semanalysis.d diff --git a/tools/tracegc.d b/tools/tracegc.d index b5bd4c4a..ab4165f3 100644 --- a/tools/tracegc.d +++ b/tools/tracegc.d @@ -2,7 +2,7 @@ module tracegc; import core.stdc.string; -version = traceGC; +//version = traceGC; // tiny helper to clear a page of the stack below the current stack pointer to avoid false pointers there void wipeStack() diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d index a420284c..5882fe87 100644 --- a/vdc/dmdserver/dmdinit.d +++ b/vdc/dmdserver/dmdinit.d @@ -213,7 +213,7 @@ struct Options if(versionLevel == level && versionIds == ids) return false; versionLevel = level; - versionIds == ids; + versionIds = ids; return true; } bool setDebugIds(int level, string[] ids) @@ -221,7 +221,7 @@ struct Options if(debugLevel == level && debugIds == ids) return false; debugLevel = level; - debugIds == ids; + debugIds = ids; return true; } } diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index 8520c7ca..e1a2eee5 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -626,14 +626,21 @@ class DMDServer : ComObject, IVDServer return S_FALSE; } - int[] locData = findBinaryIsInLocations(md.parsedModule); + Loc[] locData = findBinaryIsInLocations(md.parsedModule); - SAFEARRAY *sa = SafeArrayCreateVector(VT_INT, 0, cast(ULONG) locData.length); + SAFEARRAY *sa = SafeArrayCreateVector(VT_INT, 0, 2 * cast(ULONG) locData.length); if(!sa) return E_OUTOFMEMORY; for(LONG index = 0; index < locData.length; index++) - SafeArrayPutElement(sa, &index, &locData[index]); + { + LONG idx = index * 2; + LONG value = locData[index].linnum; + SafeArrayPutElement(sa, &idx, &value); + idx++; + value = locData[index].charnum - 1; + SafeArrayPutElement(sa, &idx, &value); + } locs.vt = VT_ARRAY | VT_INT; locs.parray = sa; @@ -935,7 +942,7 @@ class DMDServer : ComObject, IVDServer Module.modules.insert(m); } Module.rootModule = rootModule.analyzedModule; - Module.loadModuleHandler = (const ref Loc location, Identifiers* packages, Identifier ident) + Module.loadModuleHandler = (const ref Loc location, IdentifiersAtLoc* packages, Identifier ident) { return Module.loadFromFile(location, packages, ident); }; @@ -1186,7 +1193,7 @@ unittest } checkTip(5, 9, "(local variable) int xyz"); - checkTip(6, 9, "void std.stdio.writeln!(int, int, int).writeln(int _param_0, int _param_1, int _param_2) @safe"); + checkTip(6, 9, "void std.stdio.writeln!(int, int, int)(int _param_0, int _param_1, int _param_2) @safe"); checkTip(7, 12, "(local variable) int xyz"); version(traceGC) diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index 6118f2b7..f8770706 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -1417,7 +1417,7 @@ 0 0 - MARS NoBackend GC + MARS NoBackend GC TEST 0 3 0 diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d new file mode 100644 index 00000000..e3f0f839 --- /dev/null +++ b/vdc/dmdserver/semanalysis.d @@ -0,0 +1,413 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2012 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +module vdc.dmdserver.semanalysis; + +import vdc.dmdserver.dmdinit; +import vdc.dmdserver.dmderrors; +import vdc.dmdserver.semvisitor; + +import dmd.arraytypes; +import dmd.cond; +import dmd.dmodule; +import dmd.dsymbolsem; +import dmd.errors; +import dmd.globals; +import dmd.identifier; +import dmd.semantic2; +import dmd.semantic3; + +__gshared AnalysisContext lastContext; + +struct ModuleInfo +{ + Module parsedModule; + Module semanticModule; + + Module createSemanticModule() + { + Module m = cloneModule(parsedModule); + m.importedFrom = m; + m.resolvePackage(); // adds module to Module.amodules (ignore return which could be module with same name) + semanticModule = m; + Module.modules.insert(m); + return m; + } +} + +// context is kept as long as the options don't change +class AnalysisContext +{ + Options options; + + ModuleInfo[] modules; + + int findModuleInfo(Module parsedMod) + { + foreach (ref i, inf; modules) + if (parsedMod is inf.parsedModule) + return cast(int) i; + return -1; + } + int findModuleInfo(const(char)[] filename) + { + foreach (ref i, inf; modules) + if (filename == inf.parsedModule.srcfile.toString()) + return cast(int)i; + return -1; + } +} + +// is the module already added implicitly during semantic analysis? +Module findInAllModules(const(char)[] filename) +{ + foreach(m; Module.amodules) + { + if (m.srcfile.toString() == filename) + return m; + } + return null; +} + +// +Module analyzeModule(Module parsedModule, const ref Options opts) +{ + int rootModuleIndex = -1; + bool needsReinit = true; + + if (!lastContext) + lastContext = new AnalysisContext; + AnalysisContext ctxt = lastContext; + + auto filename = parsedModule.srcfile.toString(); + int idx = ctxt.findModuleInfo(filename); + if (ctxt.options == opts) + { + if (idx >= 0) + { + if (parsedModule !is ctxt.modules[idx].parsedModule) + { + // module updated, replace it + ctxt.modules[idx].parsedModule = parsedModule; + + // TODO: only update dependent modules + } + else + { + if (!ctxt.modules[idx].semanticModule) + { + auto m = ctxt.modules[rootModuleIndex].createSemanticModule(); + m.importAll(null); + } + needsReinit = false; + } + rootModuleIndex = idx; + } + else + { + ctxt.modules ~= ModuleInfo(parsedModule); + rootModuleIndex = cast(int)(ctxt.modules.length - 1); + + // is the module already added implicitly during semantic analysis? + auto ma = findInAllModules(filename); + if (ma is null) + { + // if not, no other module depends on it, so just append + auto m = ctxt.modules[rootModuleIndex].createSemanticModule(); + m.importAll(null); + needsReinit = false; + } + else + { + // TODO: check if the same as m + auto m = ctxt.modules[rootModuleIndex].createSemanticModule(); + m.importAll(null); + // TODO: only update dependent modules + } + } + } + else + { + ctxt.options = opts; + dmdSetupParams(opts); + + if (idx >= 0) + { + ctxt.modules[idx].parsedModule = parsedModule; + rootModuleIndex = idx; + } + else + { + ctxt.modules ~= ModuleInfo(parsedModule); + rootModuleIndex = cast(int)(ctxt.modules.length - 1); + } + } + + Module.loadModuleHandler = (const ref Loc location, IdentifiersAtLoc* packages, Identifier ident) + { + // only called if module not found in Module.amodules + return Module.loadFromFile(location, packages, ident); + }; + + if (needsReinit) + { + dmdReinit(); + + foreach(ref mi; ctxt.modules) + { + mi.createSemanticModule(); + } + + foreach(ref mi; ctxt.modules) + { + mi.semanticModule.importAll(null); + } + } + + Module.rootModule = ctxt.modules[rootModuleIndex].semanticModule; + Module.rootModule.dsymbolSemantic(null); + Module.dprogress = 1; + Module.runDeferredSemantic(); + Module.rootModule.semantic2(null); + Module.runDeferredSemantic2(); + Module.rootModule.semantic3(null); + Module.runDeferredSemantic3(); + + return Module.rootModule; +} + +//////////////////////////////////////////////////////////////// +//version = traceGC; +version (traceGC) import tracegc; + +unittest +{ + import core.memory; + + dmdInit(); + + Options opts; + opts.predefineDefaultVersions = true; + opts.x64 = true; + opts.msvcrt = true; + opts.importDirs = [ r"c:\s\d\rainers\druntime\import", r"c:\s\d\rainers\phobos" ]; + + auto filename = "source.d"; + + void assert_equal(S, T)(S s, T t) + { + if (s == t) + return; + assert(false); + } + + Module checkErrors(string src, string expected_err) + { + initErrorFile(filename); + Module parsedModule = createModuleFromText(filename, src); + assert(parsedModule); + Module m = analyzeModule(parsedModule, opts); + auto err = cast(string) gErrorMessages; + assert_equal(err, expected_err); + return m; + } + + void checkTip(Module analyzedModule, int line, int col, string expected_tip) + { + string tip = findTip(analyzedModule, line, col, line, col + 1); + assert_equal(tip, expected_tip); + } + + void checkDefinition(Module analyzedModule, int line, int col, string expected_fname, int expected_line, int expected_col) + { + string file = findDefinition(analyzedModule, line, col); + assert_equal(file, expected_fname); + assert_equal(line, expected_line); + assert_equal(col, expected_col); + } + + void checkBinaryIsInLocations(string src, Loc[] locs) + { + initErrorFile(filename); + Module parsedModule = createModuleFromText(filename, src); + auto err = cast(string) gErrorMessages; + assert(err == null); + assert(parsedModule); + Loc[] locdata = findBinaryIsInLocations(parsedModule); + assert(locdata.length == locs.length); + L_nextLoc: + foreach(i; 0 .. locdata.length) + { + // not listed twice + foreach(ref loc; locdata[i+1 .. $]) + assert(locdata[i].linnum != loc.linnum || locdata[i].charnum != loc.charnum); + // found in results + foreach(ref loc; locs) + if(locdata[i].linnum == loc.linnum && locdata[i].charnum == loc.charnum) + continue L_nextLoc; + assert(false); + } + } + + string source; + source = q{ + int main() + { + return abc; + } + }; + Module m = checkErrors(source, "4,10,4,11:undefined identifier `abc`\n"); + + version(traceGC) + { + wipeStack(); + GC.collect(); + } + + //_CrtDumpMemoryLeaks(); + version(traceGC) + dumpGC(); + + source = q{ + import std.stdio; + int main(string[] args) + { + int xyz = 7; + writeln(1, 2, 3); + return xyz; + } + }; + + for (int i = 0; i < 1; i++) // loop for testing GC leaks + { + m = checkErrors(source, ""); + + version(traceGC) + { + wipeStack(); + GC.collect(); + + //_CrtDumpMemoryLeaks(); + dumpGC(); + } + } + + checkTip(m, 5, 8, "(local variable) int xyz"); + checkTip(m, 5, 10, "(local variable) int xyz"); + checkTip(m, 5, 11, ""); + checkTip(m, 6, 8, "void std.stdio.writeln!(int, int, int)(int _param_0, int _param_1, int _param_2) @safe"); + checkTip(m, 7, 11, "(local variable) int xyz"); + + version(traceGC) + { + wipeStack(); + GC.collect(); + } + + checkDefinition(m, 7, 11, "source.d", 5, 8); // xyz + + //checkTypeIdentifiers(source); + + source = + q{ module pkg.source; // Line 1 + int main(in string[] args) + in(args.length > 1) in{ assert(args.length > 1); } + do { + static if(is(typeof(args[0]) : string)) // Line 5 + if (args[0] is args[1]) {} + else if (args[1] !is args[0]) {} + + int[string] aa; + if (auto p = args[0] in aa) // Line 10 + if (auto q = args[1] !in aa) {} + return 0; + } + static if(is(bool)) + bool t = null is null; // Line 15 + else + bool f = 0 in [1:1]; + + enum EE { E1 = 3, E2 } + void foo() // Line 20 + { + auto ee = EE.E1; + } + import core.cpuid : cpu_vendor = vendor, processor; + import cpuid = core.cpuid; // Line 25 + string cpu_info() + { + return cpu_vendor ~ " " ~ processor; + } + }; + checkBinaryIsInLocations(source, [Loc(null, 6, 17), Loc(null, 7, 23), + Loc(null, 10, 25), Loc(null, 11, 26), + Loc(null, 15, 18), Loc(null, 17, 15)]); + + m = checkErrors(source, ""); + + checkTip(m, 2, 24, "(parameter) const(string[]) args"); // function arg + checkTip(m, 3, 6, "(parameter) const(string[]) args"); // in contract + checkTip(m, 3, 34, "(parameter) const(string[]) args"); // in contract + checkTip(m, 5, 24, "(parameter) const(string[]) args"); // static if is typeof expression + checkTip(m, 6, 10, "(parameter) const(string[]) args"); // if expression + checkTip(m, 11, 21, "(parameter) const(string[]) args"); // !in expression + + checkTip(m, 19, 9, "(enum) pkg.source.EE"); // enum EE + checkTip(m, 19, 13, "(enum value) pkg.source.EE.E1 = 3"); // enum E1 + checkTip(m, 19, 21, "(enum value) pkg.source.EE.E2 = 4"); // enum E2 + checkTip(m, 22, 14, "(enum) pkg.source.EE"); // enum EE + checkTip(m, 22, 17, "(enum value) pkg.source.EE.E1 = 3"); // enum E1 + + checkTip(m, 1, 9, "(package) pkg"); + checkTip(m, 1, 13, "(module) pkg.source"); + checkTip(m, 24, 10, "(package) core"); + checkTip(m, 24, 15, "(module) core.cpuid"); + checkTip(m, 24, 23, "(alias) pkg.source.cpu_vendor = string core.cpuid.vendor() pure nothrow @nogc @property @trusted"); + checkTip(m, 24, 36, "(alias) pkg.source.cpu_vendor = string core.cpuid.vendor() pure nothrow @nogc @property @trusted"); + checkTip(m, 24, 44, "(alias) pkg.source.processor = string core.cpuid.processor() pure nothrow @nogc @property @trusted"); + checkTip(m, 28, 11, "string core.cpuid.vendor() pure nothrow @nogc @property @trusted"); + + source = + q{ // Line 1 + struct S + { + int field1 = 3; + int fun(int par) { return field1 + par; } + } + void foo() + { + S anS; + int x = anS.fun(1); // Line 10 + } + }; + m = checkErrors(source, ""); + + checkTip(m, 2, 10, "(struct) source.S"); + checkTip(m, 4, 8, "(field) int source.S.field1"); + checkTip(m, 5, 8, "int source.S.fun(int par)"); + checkTip(m, 5, 16, "(parameter) int par"); + checkTip(m, 5, 30, "(field) int source.S.field1"); + checkTip(m, 5, 39, "(parameter) int par"); + + checkTip(m, 9, 4, "(struct) source.S"); + checkTip(m, 9, 6, "(local variable) source.S anS"); + checkTip(m, 10, 12, "(local variable) source.S anS"); + checkTip(m, 10, 16, "int source.S.fun(int par)"); + + source = + q{ // Line 1 + struct ST(T) + { + T f; + } + }; + m = checkErrors(source, ""); + + checkTip(m, 2, 10, "(struct) source.ST(T)"); + checkTip(m, 4, 4, "(struct) source.ST(T)"); +} diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index bfea7f79..7f56f4ce 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -55,21 +55,35 @@ import dmd.root.rootobject; import std.string; import std.conv; +import stdext.array; import core.stdc.string; // walk the complete AST (declarations, statement and expressions) // assumes being started on module/declaration level extern(C++) class ASTVisitor : StoppableVisitor { + bool unconditional; // take both branches in conditional declarations/statements + alias visit = StoppableVisitor.visit; + Expression[] visiting; + size_t currentVisiting; + void visitExpression(Expression expr) { if (stop || !expr) return; + if (currentVisiting >= visiting.length) + visiting ~= expr; + else + visiting[currentVisiting] = expr; + currentVisiting++; + if (walkPostorder(expr, this)) stop = true; + + visiting[--currentVisiting] = null; } void visitStatement(Statement stmt) @@ -90,14 +104,51 @@ extern(C++) class ASTVisitor : StoppableVisitor } // default to being permissive - override void visit(Dsymbol) {} - override void visit(Expression) {} override void visit(Parameter) {} - override void visit(Statement) {} - override void visit(Type) {} override void visit(TemplateParameter) {} - override void visit(Condition) {} - override void visit(Initializer) {} + + // expressions + override void visit(Expression expr) + { + if (expr.original && expr.original != expr) + if (!visiting.contains(expr.original)) + visitExpression(expr.original); + } + + override void visit(IsExp ie) + { + // TODO: has ident + if (ie.targ) + ie.targ.accept(this); + if (ie.originaltarg && ie.originaltarg !is ie.targ) + ie.originaltarg.accept(this); + + visit(cast(Expression)ie); + } + + override void visit(DeclarationExp expr) + { + visitDeclaration(expr.declaration); + visit(cast(Expression)expr); + } + + override void visit(TypeExp expr) + { + if (expr.type) + expr.type.accept(this); + visit(cast(Expression)expr); + } + + // types + override void visit(Type) {} + + override void visit(TypeTypeof t) + { + visitExpression(t.exp); + } + + // symbols + override void visit(Dsymbol) {} override void visit(ScopeDsymbol scopesym) { @@ -110,6 +161,7 @@ extern(C++) class ASTVisitor : StoppableVisitor } } + // declarations override void visit(VarDeclaration decl) { visit(cast(Declaration)decl); @@ -123,7 +175,14 @@ extern(C++) class ASTVisitor : StoppableVisitor visit(cast(Declaration)decl); if (!stop) - if (auto inc = decl.include(null)) + if (unconditional) + { + if (decl.decl) + foreach(d; *decl.decl) + if (!stop) + d.accept(this); + } + else if (auto inc = decl.include(null)) foreach(d; *inc) if (!stop) d.accept(this); @@ -135,8 +194,46 @@ extern(C++) class ASTVisitor : StoppableVisitor decl.condition.accept(this); visit(cast(AttribDeclaration)decl); + + if (!stop && unconditional && decl.elsedecl) + foreach(d; *decl.elsedecl) + if (!stop) + d.accept(this); } + override void visit(FuncDeclaration decl) + { + visit(cast(Declaration)decl); + + if (decl.parameters) + foreach(p; *decl.parameters) + if (!stop) + p.accept(this); + + if (decl.frequires) + foreach(s; *decl.frequires) + visitStatement(s); + if (decl.fensures) + foreach(e; *decl.fensures) + visitStatement(e.ensure); // TODO: check result ident + + visitStatement(decl.frequire); + visitStatement(decl.fensure); + visitStatement(decl.fbody); + } + + // condition + override void visit(Condition) {} + + override void visit(StaticIfCondition cond) + { + visitExpression(cond.exp); + visit(cast(Condition)cond); + } + + // initializer + override void visit(Initializer) {} + override void visit(ExpInitializer einit) { visitExpression(einit.exp); @@ -168,19 +265,8 @@ extern(C++) class ASTVisitor : StoppableVisitor } } - override void visit(FuncDeclaration decl) - { - visit(cast(Declaration)decl); - - if (decl.parameters) - foreach(p; *decl.parameters) - if (!stop) - p.accept(this); - - visitStatement(decl.frequire); - visitStatement(decl.fensure); - visitStatement(decl.fbody); - } + // statements + override void visit(Statement) {} override void visit(ErrorStatement stmt) { @@ -196,6 +282,24 @@ extern(C++) class ASTVisitor : StoppableVisitor visit(cast(Statement)stmt); } + override void visit(ConditionalStatement stmt) + { + if (!stop && stmt.condition) + { + stmt.condition.accept(this); + + if (unconditional) + { + visitStatement(stmt.ifbody); + visitStatement(stmt.elsebody); + } + else if (stmt.condition.include(null)) + visitStatement(stmt.ifbody); + else + visitStatement(stmt.elsebody); + } + } + override void visit(CompileStatement stmt) { if (stmt.exps) @@ -340,19 +444,6 @@ extern(C++) class ASTVisitor : StoppableVisitor visitDeclaration(i); visit(cast(Statement)stmt); } - - override void visit(DeclarationExp expr) - { - visitDeclaration(expr.declaration); - } - - override void visit(ErrorExp expr) - { - visitExpression(expr.errExp); - if (!stop) - visit(cast(Expression)expr); - } - } extern(C++) class FindASTVisitor : ASTVisitor @@ -396,6 +487,24 @@ extern(C++) class FindASTVisitor : ASTVisitor return false; } + bool visitPackages(IdentifiersAtLoc* packages) + { + if (packages) + for (size_t p; p < packages.dim; p++) + if (!found && matchIdentifier((*packages)[p].loc, (*packages)[p].ident)) + { + Package pkg; + auto pkgs = new IdentifiersAtLoc(); + for (size_t q = 0; q <= p; q++) + pkgs.push((*packages)[p]); + Package.resolve(pkgs, null, &pkg); + if (pkg) + foundNode(pkg); + return true; + } + return false; + } + bool matchLoc(ref Loc loc) { if (loc.filename is filename) @@ -413,16 +522,50 @@ extern(C++) class FindASTVisitor : ASTVisitor override void visit(Parameter sym) { - if (!found && matchIdentifier(sym.identloc, sym.ident)) + if (!found && matchIdentifier(sym.ident.loc, sym.ident)) foundNode(sym); } + override void visit(Module mod) + { + if (mod.md) + { + visitPackages(mod.md.packages); + + if (!found && matchIdentifier(mod.md.loc, mod.md.id)) + foundNode(mod); + } + visit(cast(Package)mod); + } + + override void visit(Import imp) + { + visitPackages(imp.packages); + + if (!found && matchIdentifier(imp.loc, imp.id)) + foundNode(imp.mod); + + for (int n = 0; !found && n < imp.names.dim; n++) + if (matchIdentifier(imp.names[n].loc, imp.names[n].ident) || + matchIdentifier(imp.aliases[n].loc, imp.aliases[n].ident)) + if (n < imp.aliasdecls.dim) + foundNode(imp.aliasdecls[n]); + + visit(cast(Dsymbol)imp); + } + override void visit(DVCondition cond) { if (!found && matchIdentifier(cond.loc, cond.ident)) foundNode(cond); } + override void visit(TypeIdentifier t) + { + visitTypeIdentifier(t, t); + visit(cast(TypeQualified)t); + } + override void visit(CompoundStatement cs) { // optimize to only visit members in approriate source range @@ -501,6 +644,7 @@ extern(C++) class FindASTVisitor : ASTVisitor if (!found && expr.var) if (matchIdentifier(expr.loc, expr.var.ident)) foundNode(expr); + super.visit(expr); } override void visit(NewExp ne) { @@ -511,6 +655,14 @@ extern(C++) class FindASTVisitor : ASTVisitor foundNode(ne.newtype); } + override void visit(IdentifierExp expr) + { + if (!found && expr.ident && expr.type) + if (matchIdentifier(expr.loc, expr.ident)) + foundNode(expr.type); + visit(cast(Expression)expr); + } + override void visit(DotIdExp de) { if (!found && de.ident) @@ -646,105 +798,123 @@ extern(C++) class FindTipVisitor : FindASTVisitor found = obj; if (obj) { - string tipForDeclaration(Declaration decl) - { - if (auto func = decl.isFuncDeclaration()) - { - OutBuffer buf; - if (decl.type) - functionToBufferWithIdent(decl.type.toTypeFunction(), &buf, decl.toPrettyChars()); - else - buf.writestring(decl.toPrettyChars()); - auto res = buf.peekSlice(); - buf.extractSlice(); // take ownership - return cast(string)res; - } + tip = tipForObject(obj); + stop = true; + } + return stop; + } +} - string txt; - if (decl.isParameter()) - txt = "(parameter) "; - else if (decl.isEnumMember()) - txt = "(enum member) "; - else if (decl.storage_class & STC.manifest) - txt = "(constant) "; - else if (decl.isAliasDeclaration()) - txt = "(alias) "; - else if (decl.isField()) - txt = "(field) "; - else if (!decl.isDataseg() && !decl.isCodeseg()) - txt = "(local variable) "; - else if (decl.isThreadlocal()) - txt = "(thread local variable) "; - else if (decl.type && decl.type.isShared()) - txt = "(shared variable) "; - else - txt = "(__gshared variable) "; - bool fqn = txt.empty; - - if (decl.type) - txt ~= to!string(decl.type.toPrettyChars()) ~ " "; - txt ~= to!string(fqn ? decl.toPrettyChars(fqn) : decl.toChars()); - if (decl.storage_class & STC.manifest) - if (auto var = decl.isVarDeclaration()) - if (var._init) - txt ~= " = " ~ var._init.toString(); - if (auto em = decl.isEnumMember()) - if (em.origValue) - txt ~= " = " ~ em.origValue.toString(); - return txt; - } +string tipForObject(RootObject obj) +{ + string tipForDeclaration(Declaration decl) + { + if (auto func = decl.isFuncDeclaration()) + { + OutBuffer buf; + if (decl.type) + functionToBufferWithIdent(decl.type.toTypeFunction(), &buf, decl.toPrettyChars()); + else + buf.writestring(decl.toPrettyChars()); + auto res = buf.peekSlice(); + buf.extractSlice(); // take ownership + return cast(string)res; + } - string toc; - const(char)* doc; - if (auto t = obj.isType()) - { - toc = "(" ~ t.kind().to!string ~ ") " ~ t.toPrettyChars(true).to!string; - if (auto sym = typeSymbol(t)) - if (sym.comment) - doc = sym.comment; - } - else if (auto e = obj.isExpression()) - { - switch(e.op) - { - case TOK.variable: - case TOK.symbolOffset: - tip = tipForDeclaration((cast(SymbolExp)e).var); - doc = (cast(SymbolExp)e).var.comment; - break; - case TOK.dotVariable: - tip = tipForDeclaration((cast(DotVarExp)e).var); - doc = (cast(DotVarExp)e).var.comment; - break; - default: - if (e.type) - toc = e.type.toPrettyChars(true).to!string; - break; - } - } - else if (auto s = obj.isDsymbol()) - { - if (auto decl = s.isDeclaration) - tip = tipForDeclaration(decl); - else - toc = s.toPrettyChars(true).to!string; + bool fqn = true; + string txt; + if (decl.isParameter()) + { + txt = "(parameter) "; + fqn = false; + } + else if (auto em = decl.isEnumMember()) + { + txt = "(enum value) " ~ decl.toPrettyChars(fqn).to!string; + if (em.origValue) + txt ~= " = " ~ cast(string)em.origValue.toString(); + return txt; + } + else if (decl.storage_class & STC.manifest) + txt = "(constant) "; + else if (decl.isAliasDeclaration()) + txt = "(alias) "; + else if (decl.isField()) + txt = "(field) "; + else if (!decl.isDataseg() && !decl.isCodeseg()) + { + txt = "(local variable) "; + fqn = false; + } + else if (decl.isThreadlocal()) + txt = "(thread local variable) "; + else if (decl.type && decl.type.isShared()) + txt = "(shared variable) "; + else + txt = "(__gshared variable) "; + + if (decl.type) + txt ~= to!string(decl.type.toPrettyChars(true)) ~ " "; + txt ~= to!string(fqn ? decl.toPrettyChars(fqn) : decl.toChars()); + if (decl.storage_class & STC.manifest) + if (auto var = decl.isVarDeclaration()) + if (var._init) + txt ~= " = " ~ var._init.toString(); + if (auto ad = decl.isAliasDeclaration()) + if (ad.aliassym) + txt ~= " = " ~ tipForObject(ad.aliassym); + return txt; + } - if (s.comment) - doc = s.comment; - } - if (!tip.length) - { - if (!toc) - toc = obj.toString().dup; - tip = toc; - } - // append doc - if (doc) - tip = tip ~ "\n\n" ~ strip(cast(string)doc[0..strlen(doc)]); - stop = true; + string tip; + string toc; + const(char)* doc; + if (auto t = obj.isType()) + { + toc = "(" ~ t.kind().to!string ~ ") " ~ t.toPrettyChars(true).to!string; + if (auto sym = typeSymbol(t)) + if (sym.comment) + doc = sym.comment; + } + else if (auto e = obj.isExpression()) + { + switch(e.op) + { + case TOK.variable: + case TOK.symbolOffset: + tip = tipForDeclaration((cast(SymbolExp)e).var); + doc = (cast(SymbolExp)e).var.comment; + break; + case TOK.dotVariable: + tip = tipForDeclaration((cast(DotVarExp)e).var); + doc = (cast(DotVarExp)e).var.comment; + break; + default: + if (e.type) + toc = e.type.toPrettyChars(true).to!string; + break; } - return stop; } + else if (auto s = obj.isDsymbol()) + { + if (auto decl = s.isDeclaration()) + tip = tipForDeclaration(decl); + else + toc = "(" ~ s.kind().to!string ~ ") " ~ s.toPrettyChars(true).to!string; + + if (s.comment) + doc = s.comment; + } + if (!tip.length) + { + if (!toc) + toc = obj.toString().dup; + tip = toc; + } + // append doc + if (doc) + tip = tip ~ "\n\n" ~ strip(cast(string)doc[0..strlen(doc)]); + return tip; } string findTip(Module mod, int startLine, int startIndex, int endLine, int endIndex) @@ -821,11 +991,11 @@ string findDefinition(Module mod, ref int line, ref int index) //////////////////////////////////////////////////////////////////////////////// -int[] findBinaryIsInLocations(Module mod) +Loc[] findBinaryIsInLocations(Module mod) { extern(C++) class BinaryIsInVisitor : ASTVisitor { - int[] locdata; + Loc[] locdata; const(char)* filename; alias visit = ASTVisitor.visit; @@ -833,10 +1003,7 @@ int[] findBinaryIsInLocations(Module mod) final void addLocation(const ref Loc loc) { if (loc.filename is filename) - { - locdata ~= loc.linnum; - locdata ~= loc.charnum - 1; - } + locdata ~= loc; } override void visit(InExp e) @@ -853,6 +1020,7 @@ int[] findBinaryIsInLocations(Module mod) scope BinaryIsInVisitor biiv = new BinaryIsInVisitor; biiv.filename = mod.srcfile.toChars(); + biiv.unconditional = true; mod.accept(biiv); return biiv.locdata; @@ -892,6 +1060,13 @@ string findIdentifierTypes(Module mod) addTypePos(ident.toString(), type, loc.linnum, loc.charnum); } + void addPackages(IdentifiersAtLoc* packages) + { + if (packages) + for (size_t p; p < packages.dim; p++) + addIdent((*packages)[p].loc, (*packages)[p].ident, TypeReferenceKind.Package); + } + void addDeclaration(ref const Loc loc, Declaration decl) { auto ident = decl.ident; @@ -931,9 +1106,25 @@ string findIdentifierTypes(Module mod) addIdent(sym.loc, sym.ident, TypeReferenceKind.Variable); } + override void visit(Import imp) + { + addPackages(imp.packages); + + addIdent(imp.loc, imp.ident, TypeReferenceKind.Module); + + for (int n = 0; n < imp.names.dim; n++) + { + addIdent(imp.names[n].loc, imp.names[n].ident, TypeReferenceKind.Alias); + if (imp.aliases[n].ident && n < imp.aliasdecls.dim) + addDeclaration(imp.aliases[n].loc, imp.aliasdecls[n]); + } + + visit(cast(Dsymbol)imp); + } + override void visit(Parameter sym) { - addIdent(sym.identloc, sym.ident, TypeReferenceKind.ParameterVariable); + addIdent(sym.ident.loc, sym.ident, TypeReferenceKind.ParameterVariable); } override void visit(EnumDeclaration ed) @@ -1156,6 +1347,7 @@ Module cloneModule(Module mo) Module m = new Module(mo.srcfile.toString(), mo.ident, mo.isDocFile, mo.isHdrFile); *cast(FileName*)&(m.srcfile) = mo.srcfile; // keep identical source file name pointer m.isPackageFile = mo.isPackageFile; + m.md = mo.md; mo.syntaxCopy(m); extern(C++) class AdjustModuleVisitor : ASTVisitor diff --git a/vdc/ivdserver.d b/vdc/ivdserver.d index a5849e5b..24a5f193 100644 --- a/vdc/ivdserver.d +++ b/vdc/ivdserver.d @@ -264,6 +264,7 @@ enum TypeReferenceKind : uint Alias, Module, + Package = Module, // todo Function, Method, BasicType, diff --git a/vdc/vdserverfactory.d b/vdc/vdserverfactory.d index 8f8ef1ad..ed1be124 100644 --- a/vdc/vdserverfactory.d +++ b/vdc/vdserverfactory.d @@ -147,12 +147,11 @@ void ShowErrorMessage(LPCTSTR header, HRESULT hr) import std.compiler; import std.conv; -static if(version_minor < 64) +version(TEST) { - // dmd 2.064 implicitely adds C main with D main int main(char[][] argv) { - return vdserver_main(); + return 0; //vdserver_main(); } } else From de0e80cca37f3bd6993323fc398917964dacec91 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 1 Sep 2019 14:12:59 +0200 Subject: [PATCH 28/73] some code completion --- vdc/dmdserver/semanalysis.d | 72 ++++++++++++++++++++++++++++++- vdc/dmdserver/semvisitor.d | 85 +++++++++++++++++++++++++++++-------- 2 files changed, 138 insertions(+), 19 deletions(-) diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index e3f0f839..985e655d 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -184,6 +184,7 @@ Module analyzeModule(Module parsedModule, const ref Options opts) //////////////////////////////////////////////////////////////// //version = traceGC; version (traceGC) import tracegc; +extern(Windows) void OutputDebugStringA(const(char)* lpOutputString); unittest { @@ -254,6 +255,28 @@ unittest } } + void checkExpansions(Module analyzedModule, int line, int col, string[] expected) + { + import std.algorithm, std.array; + string[] expansions = findExpansions(analyzedModule, line, col, ""); + expansions.sort(); + expected.sort(); + assert_equal(expansions.length, expected.length); + for (size_t i = 0; i < expansions.length; i++) + assert_equal(expansions[i].split(':')[0], expected[i]); + } + + void dumpAST(Module mod) + { + import dmd.root.outbuffer; + import dmd.hdrgen; + auto buf = OutBuffer(); + buf.doindent = 1; + moduleToBuffer(&buf, mod); + + OutputDebugStringA(buf.peekChars); + } + string source; source = q{ int main() @@ -409,5 +432,52 @@ unittest m = checkErrors(source, ""); checkTip(m, 2, 10, "(struct) source.ST(T)"); - checkTip(m, 4, 4, "(struct) source.ST(T)"); + checkTip(m, 4, 4, "(unresolved type) T"); + checkTip(m, 4, 6, "T f"); + + source = + q{ // Line 1 + void foo() + { + int x = 1; + try + { + x++; + } + catch(Exception e) + { // Line 10 + Exception* pe = &e; + throw new Error("unexpected"); + } + finally + { + x = 0; + } + } + }; + m = checkErrors(source, ""); + + checkTip(m, 9, 20, "(local variable) object.Exception e"); + checkTip(m, 9, 10, "(class) object.Exception"); + + source = + q{ // Line 1 + struct S + { + int field1 = 1; + int field2 = 2; // Line 5 + int fun(int par) { return field1 + par; } + int more = 3; + } + void foo() + { // Line 10 + S anS; + int x = anS.f(1); + a + } + }; + m = checkErrors(source, "12,14,12,15:no property `f` for type `S`\n"); + dumpAST(m); + checkExpansions(m, 12, 16, [ "field1", "field2", "fun", "more" ]); + checkExpansions(m, 13, 5, [ "field1", "field2", "fun", "more" ]); } diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 7f56f4ce..b5859e89 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -115,6 +115,11 @@ extern(C++) class ASTVisitor : StoppableVisitor visitExpression(expr.original); } + override void visit(ErrorExp errexp) + { + visit(cast(Expression)errexp); + } + override void visit(IsExp ie) { // TODO: has ident @@ -245,6 +250,8 @@ extern(C++) class ASTVisitor : StoppableVisitor override void visit(ErrorInitializer einit) { + if (einit.original) + einit.original.accept(this); } override void visit(StructInitializer sinit) @@ -551,7 +558,7 @@ extern(C++) class FindASTVisitor : ASTVisitor if (n < imp.aliasdecls.dim) foundNode(imp.aliasdecls[n]); - visit(cast(Dsymbol)imp); + // symbol has ident of first package, so don't forward } override void visit(DVCondition cond) @@ -695,7 +702,8 @@ extern(C++) class FindASTVisitor : ASTVisitor { if (decl.originalType && decl.originalType.ty == Tident) visitTypeIdentifier(cast(TypeIdentifier) decl.originalType, decl.type); - + else if (decl.type && decl.type.ty == Tident) // not yet semantically analyzed (or a template declaration) + visitTypeIdentifier(cast(TypeIdentifier) decl.type, decl.type); super.visit(decl); } @@ -841,17 +849,20 @@ string tipForObject(RootObject obj) txt = "(alias) "; else if (decl.isField()) txt = "(field) "; - else if (!decl.isDataseg() && !decl.isCodeseg()) + else if (decl.semanticRun >= PASS.semanticdone) // avoid lazy semantic analysis { - txt = "(local variable) "; - fqn = false; + if (!decl.isDataseg() && !decl.isCodeseg()) + { + txt = "(local variable) "; + fqn = false; + } + else if (decl.isThreadlocal()) + txt = "(thread local variable) "; + else if (decl.type && decl.type.isShared()) + txt = "(shared variable) "; + else if (decl.type && decl.type.ty != Terror) + txt = "(__gshared variable) "; } - else if (decl.isThreadlocal()) - txt = "(thread local variable) "; - else if (decl.type && decl.type.isShared()) - txt = "(shared variable) "; - else - txt = "(__gshared variable) "; if (decl.type) txt ~= to!string(decl.type.toPrettyChars(true)) ~ " "; @@ -871,7 +882,12 @@ string tipForObject(RootObject obj) const(char)* doc; if (auto t = obj.isType()) { - toc = "(" ~ t.kind().to!string ~ ") " ~ t.toPrettyChars(true).to!string; + string kind; + if (t.isTypeIdentifier()) + kind = "unresolved type"; + else + kind = t.kind().to!string; + toc = "(" ~ kind ~ ") " ~ t.toPrettyChars(true).to!string; if (auto sym = typeSymbol(t)) if (sym.comment) doc = sym.comment; @@ -1098,6 +1114,25 @@ string findIdentifierTypes(Module mod) addIdent(loc, ident, TypeReferenceKind.GSharedVariable); } + void addType(ref const Loc loc, Type type, Type originalType) + { + static TypeReferenceKind refkind(Type t) + { + switch (t.ty) + { + case Tident: return TypeReferenceKind.TemplateTypeParameter; + case Tclass: return TypeReferenceKind.Class; + case Tstruct: return TypeReferenceKind.Struct; + case Tenum: return TypeReferenceKind.Enum; + default: return TypeReferenceKind.BasicType; + } + } + if (originalType && originalType.ty == Tident) + addIdent(loc, (cast(TypeIdentifier) originalType).ident, refkind(type)); + else if (type && type.ty == Tident) // not yet semantically analyzed (or a template declaration) + addIdent(loc, (cast(TypeIdentifier) type).ident, TypeReferenceKind.TemplateTypeParameter); + } + override void visit(Dsymbol sym) { if (auto decl = sym.isDeclaration) @@ -1106,11 +1141,17 @@ string findIdentifierTypes(Module mod) addIdent(sym.loc, sym.ident, TypeReferenceKind.Variable); } + override void visit(VarDeclaration decl) + { + addType(decl.loc, decl.type, decl.originalType); + visit(cast(Declaration)decl); + } + override void visit(Import imp) { addPackages(imp.packages); - addIdent(imp.loc, imp.ident, TypeReferenceKind.Module); + addIdent(imp.loc, imp.id, TypeReferenceKind.Module); for (int n = 0; n < imp.names.dim; n++) { @@ -1118,8 +1159,7 @@ string findIdentifierTypes(Module mod) if (imp.aliases[n].ident && n < imp.aliasdecls.dim) addDeclaration(imp.aliases[n].loc, imp.aliasdecls[n]); } - - visit(cast(Dsymbol)imp); + // symbol has ident of first package, so don't forward } override void visit(Parameter sym) @@ -1247,6 +1287,7 @@ string[] findExpansions(Module mod, int line, int index, string tok) if (!fdv.found) return null; + int flags = 0; Type type = fdv.found.isType(); if (auto e = fdv.found.isExpression()) { @@ -1257,7 +1298,9 @@ string[] findExpansions(Module mod, int line, int index, string tok) type = (cast(SymbolExp)e).var.type; break; case TOK.dotVariable: - type = (cast(DotVarExp)e).e1.type; + case TOK.dotIdentifier: + type = (cast(UnaExp)e).e1.type; + flags |= SearchLocalsOnly; break; default: break; @@ -1272,10 +1315,16 @@ string[] findExpansions(Module mod, int line, int index, string tok) string[void*] idmap; // doesn't work with extern(C++) classes void searchScope(ScopeDsymbol sds, int flags) { + static Dsymbol uplevel(Dsymbol s) + { + if (auto ad = s.isAggregateDeclaration()) + return ad.enclosing; + return s.toParent; + } // TODO: properties // TODO: base classes // TODO: struct/class not going to parent if accessed from elsewhere (but does if nested) - for (Dsymbol ds = sds; ds; ds = ds.toParent) + for (Dsymbol ds = sds; ds; ds = uplevel(ds)) { ScopeDsymbol sd = ds.isScopeDsymbol(); if (!ds) @@ -1321,7 +1370,7 @@ string[] findExpansions(Module mod, int line, int index, string tok) } } } - searchScope(sds, 0); + searchScope(sds, flags); string[] idlist; foreach(sym, id; idmap) From 7c9d7cc78fe1bc76e3b64d43705c8ed2069f9248 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 1 Sep 2019 21:18:11 +0200 Subject: [PATCH 29/73] more expansions --- vdc/dmdserver/dmdserver.d | 2 +- vdc/dmdserver/semanalysis.d | 16 +++++---- vdc/dmdserver/semvisitor.d | 68 ++++++++++++++++++++++++++----------- 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index e1a2eee5..fcd6ca9a 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -554,7 +554,7 @@ class DMDServer : ComObject, IVDServer try { if (auto m = md.analyzedModule) - symbols = findExpansions(m, line, idx + 1, stok); + symbols = findExpansions(m, line, idx + 1 - cast(int) stok.length, stok); } catch(OutOfMemoryError e) { diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index 985e655d..652c676c 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -255,10 +255,10 @@ unittest } } - void checkExpansions(Module analyzedModule, int line, int col, string[] expected) + void checkExpansions(Module analyzedModule, int line, int col, string tok, string[] expected) { import std.algorithm, std.array; - string[] expansions = findExpansions(analyzedModule, line, col, ""); + string[] expansions = findExpansions(analyzedModule, line, col, tok); expansions.sort(); expected.sort(); assert_equal(expansions.length, expected.length); @@ -473,11 +473,15 @@ unittest { // Line 10 S anS; int x = anS.f(1); - a + int y = anS. } }; - m = checkErrors(source, "12,14,12,15:no property `f` for type `S`\n"); + m = checkErrors(source, + "14,2,14,3:identifier or `new` expected following `.`, not `}`\n" ~ + "14,2,14,3:semicolon expected, not `}`\n" ~ + "12,14,12,15:no property `f` for type `S`\n"); dumpAST(m); - checkExpansions(m, 12, 16, [ "field1", "field2", "fun", "more" ]); - checkExpansions(m, 13, 5, [ "field1", "field2", "fun", "more" ]); + checkExpansions(m, 12, 16, "f", [ "field1", "field2", "fun" ]); + checkExpansions(m, 13, 16, "", [ "field1", "field2", "fun", "more" ]); + checkExpansions(m, 13, 13, "an", [ "anS" ]); } diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index b5859e89..a12a0f58 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -512,11 +512,11 @@ extern(C++) class FindASTVisitor : ASTVisitor return false; } - bool matchLoc(ref Loc loc) + bool matchLoc(ref const(Loc) loc, int len) { if (loc.filename is filename) if (loc.linnum == startLine && loc.linnum == endLine) - if (loc.charnum <= startIndex /*&& loc.charnum + ident.toString().length >= endIndex*/) + if (loc.charnum <= startIndex && loc.charnum + len >= endIndex) return true; return false; } @@ -636,6 +636,13 @@ extern(C++) class FindASTVisitor : ASTVisitor foundScope = scopesym; } + override void visit(ScopeStatement ss) + { + visit(cast(Statement)ss); + if (found && !foundScope) + foundScope = ss.scopesym; + } + override void visit(TemplateInstance) { // skip members added by semantic @@ -655,7 +662,7 @@ extern(C++) class FindASTVisitor : ASTVisitor } override void visit(NewExp ne) { - if (!found && matchLoc(ne.loc)) + if (!found && matchLoc(ne.loc, 99)) if (ne.member) foundNode(ne.member); else @@ -672,9 +679,20 @@ extern(C++) class FindASTVisitor : ASTVisitor override void visit(DotIdExp de) { - if (!found && de.ident) - if (matchIdentifier(de.identloc, de.ident)) + if (!found) + if (de.ident) + if (matchIdentifier(de.identloc, de.ident)) + foundNode(de); + } + + override void visit(DotExp de) + { + if (!found) + { + // '.' of erroneous DotIdExp + if (matchLoc(de.loc, 2)) foundNode(de); + } } override void visit(DotTemplateExp dte) @@ -740,6 +758,13 @@ extern(C++) class FindASTVisitor : ASTVisitor visit(cast(AggregateDeclaration)cd); } + override void visit(FuncDeclaration decl) + { + super.visit(decl); + if (found && !foundScope) + foundScope = decl.scopesym; + } + void visitTypeIdentifier(TypeIdentifier originalType, Type resolvedType) { Loc loc = originalType.loc; @@ -961,10 +986,8 @@ extern(C++) class FindDefinitionVisitor : FindASTVisitor { if (auto t = obj.isType()) { - if (t.ty == Tstruct) - loc = (cast(TypeStruct)t).sym.loc; - else if (t.ty == Tstruct) - loc = (cast(TypeClass)t).sym.loc; + if (auto sym = typeSymbol(t)) + loc = sym.loc; } else if (auto e = obj.isExpression()) { @@ -1281,7 +1304,7 @@ Reference[] findReferencesInModule(Module mod, int line, int index) string[] findExpansions(Module mod, int line, int index, string tok) { auto filename = mod.srcfile.toChars(); - scope FindDefinitionVisitor fdv = new FindDefinitionVisitor(filename, line, index - cast(int) tok.length, line, index + 1); + scope FindDefinitionVisitor fdv = new FindDefinitionVisitor(filename, line, index, line, index + 1); mod.accept(fdv); if (!fdv.found) @@ -1295,13 +1318,17 @@ string[] findExpansions(Module mod, int line, int index, string tok) { case TOK.variable: case TOK.symbolOffset: - type = (cast(SymbolExp)e).var.type; + //type = (cast(SymbolExp)e).var.type; break; case TOK.dotVariable: case TOK.dotIdentifier: type = (cast(UnaExp)e).e1.type; flags |= SearchLocalsOnly; break; + case TOK.dot: + type = (cast(DotExp)e).e1.type; + flags |= SearchLocalsOnly; + break; default: break; } @@ -1327,18 +1354,21 @@ string[] findExpansions(Module mod, int line, int index, string tok) for (Dsymbol ds = sds; ds; ds = uplevel(ds)) { ScopeDsymbol sd = ds.isScopeDsymbol(); - if (!ds) + if (!sd) continue; //foreach (pair; sd.symtab.tab.asRange) - foreach (key, s; sd.symtab.tab.aa) + if (sd.symtab) { - //Dsymbol s = pair.value; - if (!symbolIsVisible(mod, s)) - continue; - auto ident = /*pair.*/(cast(Dsymbol)key).toString(); - if (ident.startsWith(tok)) - idmap[cast(void*)s] = ident.idup; + foreach (key, s; sd.symtab.tab.aa) + { + //Dsymbol s = pair.value; + if (!symbolIsVisible(mod, s)) + continue; + auto ident = /*pair.*/(cast(Dsymbol)key).toString(); + if (ident.startsWith(tok)) + idmap[cast(void*)s] = ident.idup; + } } // TODO: alias this From 3431ea2a88748072aace6a438bc55b7ece222d16 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 6 Sep 2019 15:57:24 +0200 Subject: [PATCH 30/73] dmdserver: use one process per client --- vdc/vdserverfactory.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vdc/vdserverfactory.d b/vdc/vdserverfactory.d index ed1be124..7d089643 100644 --- a/vdc/vdserverfactory.d +++ b/vdc/vdserverfactory.d @@ -107,7 +107,7 @@ extern(C) int vdserver_main() // Register the Factory. DWORD regID = 0; - hr = CoRegisterClassObject(*cast(GUID*)&VDServerClassFactory.iid, cf, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, ®ID); + hr = CoRegisterClassObject(*cast(GUID*)&VDServerClassFactory.iid, cf, CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, ®ID); if(FAILED(hr)) { ShowErrorMessage("CoRegisterClassObject()", hr); From ace02fb97972e094f1794994b8d1cf6e77daa5e0 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 8 Sep 2019 13:00:06 +0200 Subject: [PATCH 31/73] x64 builds should go into other directory --- c2d/c2d.visualdproj | 2 +- c2d/cpp2d.visualdproj | 2 +- c2d/vsi2d.visualdproj | 2 +- sdk/vsi.visualdproj | 256 ++++++++++++++++++++------------------ stdext/stdext.visualdproj | 2 +- 5 files changed, 141 insertions(+), 123 deletions(-) diff --git a/c2d/c2d.visualdproj b/c2d/c2d.visualdproj index 26b8b618..3091b25f 100644 --- a/c2d/c2d.visualdproj +++ b/c2d/c2d.visualdproj @@ -1884,7 +1884,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) diff --git a/c2d/cpp2d.visualdproj b/c2d/cpp2d.visualdproj index f52707d3..1754366a 100644 --- a/c2d/cpp2d.visualdproj +++ b/c2d/cpp2d.visualdproj @@ -1884,7 +1884,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) diff --git a/c2d/vsi2d.visualdproj b/c2d/vsi2d.visualdproj index ddeb0ae6..e19bd5c6 100644 --- a/c2d/vsi2d.visualdproj +++ b/c2d/vsi2d.visualdproj @@ -1642,7 +1642,7 @@ .. .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) diff --git a/sdk/vsi.visualdproj b/sdk/vsi.visualdproj index f076eb3f..4aaac8e6 100644 --- a/sdk/vsi.visualdproj +++ b/sdk/vsi.visualdproj @@ -1884,7 +1884,7 @@ .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -1986,9 +1986,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -1997,16 +2091,12 @@ - - - - @@ -2014,7 +2104,6 @@ - @@ -2046,13 +2135,18 @@ - + + + + + + @@ -2062,14 +2156,8 @@ - - - - - - @@ -2081,17 +2169,12 @@ - - - - - @@ -2099,137 +2182,72 @@ + + + - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stdext/stdext.visualdproj b/stdext/stdext.visualdproj index fad21f77..c66704a8 100644 --- a/stdext/stdext.visualdproj +++ b/stdext/stdext.visualdproj @@ -1884,7 +1884,7 @@ .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) From 0671acfcad90a8d5e961a379c954bd64d5522e5a Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 8 Sep 2019 13:06:14 +0200 Subject: [PATCH 32/73] fix dmdserver compilation add option to enable dmd server, register it as COM server fix finding definition for DotVarExp fix crawling lowered foreach --- .gitmodules | 3 + Makefile | 3 + nsis/visuald.nsi | 53 ++++++++++--- vdc/abothe/Parser | 2 +- vdc/dmdserver/ddmdrmem.d | 6 ++ vdc/dmdserver/dmd | 1 + vdc/dmdserver/dmdserver.d | 56 ++++++++------ vdc/dmdserver/dmdserver.visualdproj | 6 +- vdc/dmdserver/semanalysis.d | 114 +++++++++++++++++++++++++++- vdc/dmdserver/semvisitor.d | 79 +++++++++++++------ visuald/propertypage.d | 12 +-- visuald/vdserverclient.d | 11 ++- 12 files changed, 278 insertions(+), 68 deletions(-) create mode 160000 vdc/dmdserver/dmd diff --git a/.gitmodules b/.gitmodules index 73521abf..8f0419da 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "vdc/abothe/Parser"] path = vdc/abothe/Parser url = https://github.com/rainers/D_Parser.git +[submodule "vdc/dmdserver/dmd"] + path = vdc/dmdserver/dmd + url = https://github.com/rainers/dmd.git diff --git a/Makefile b/Makefile index c35dd220..82fe8535 100644 --- a/Makefile +++ b/Makefile @@ -64,6 +64,9 @@ visuald_test: vdserver: devenv /Project "vdserver" /Build "$(CONFIG)|Win32" visuald_vs10.sln +dmdserver: + devenv /Project "dmdserver" /Build "$(CONFIG)|x64" visuald_vs10.sln + dparser: cd vdc\abothe && $(MSBUILD15) vdserver.sln /p:Configuration=Release;Platform="Any CPU" /p:TargetFrameworkVersion=4.5.2 /p:DefineConstants=NET40 /t:Rebuild editbin /STACK:0x800000 bin\Release\DParserCOMServer\DParserCOMServer.exe diff --git a/nsis/visuald.nsi b/nsis/visuald.nsi index 43768476..b194dc82 100644 --- a/nsis/visuald.nsi +++ b/nsis/visuald.nsi @@ -15,6 +15,9 @@ ; define VDSERVER to include vdserver COM server installation ; !define VDSERVER +; define DMDSERVER to include dmdserver COM server installation +!define DMDSERVER + ; define VDEXTENSIONS to include C# extensions (expected at ../bin/Release/vdextensions) !define VDEXTENSIONS @@ -255,6 +258,10 @@ Section "Visual Studio package" SecPackage ${File} "..\bin\${CONFIG}\" vdserver.exe !endif +!ifdef DMDSERVER + ${File} "..\bin\${CONFIG}\x64\" dmdserver.exe +!endif + !ifdef VDEXTENSIONS ${File} ..\bin\Release\vdextensions\ vdextensions.dll ${File} ..\bin\Release\vdext15\ vdext15.dll @@ -281,6 +288,10 @@ Section "Visual Studio package" SecPackage Call RegisterVDServer !endif +!ifdef DMDSERVER + Call RegisterDMDServer +!endif + !ifdef DPARSER Call RegisterDParser !endif @@ -1124,6 +1135,7 @@ Section "Uninstall" Call un.RegisterIVDServer Call un.RegisterVDServer + Call un.RegisterDMDServer Call un.RegisterDParser Call un.installedFiles @@ -1545,24 +1557,46 @@ Function un.RegisterVDServer FunctionEnd +;--------------------------------------- +!define DMDSERVER_REG_ROOT HKCR +!define DMDSERVER_FACTORY_NAME visuald.dmdserver.factory +!define DMDSERVER_FACTORY_CLSID {002a2de9-8bb6-484d-9906-7e4ad4084715} +; typelib and IVDServer interface inherited from vdserver.exe + +Function RegisterDMDServer + + WriteRegStr ${DMDSERVER_REG_ROOT} "${DMDSERVER_FACTORY_NAME}\CLSID" "" ${DMDSERVER_FACTORY_CLSID} + WriteRegStr ${DMDSERVER_REG_ROOT} "CLSID\${DMDSERVER_FACTORY_CLSID}\LocalServer32" "" $INSTDIR\dmdserver.exe + WriteRegStr ${DMDSERVER_REG_ROOT} "CLSID\${DMDSERVER_FACTORY_CLSID}\ProgId" "" DMDServer.VDServer + WriteRegStr ${DMDSERVER_REG_ROOT} "CLSID\${DMDSERVER_FACTORY_CLSID}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" "" "" + +FunctionEnd + +Function un.RegisterDMDServer + + DeleteRegKey ${DMDSERVER_REG_ROOT} "${DMDSERVER_FACTORY_NAME}" + DeleteRegKey ${DMDSERVER_REG_ROOT} "CLSID\${DMDSERVER_FACTORY_CLSID}" + +FunctionEnd + ;--------------------------------------- !define DPARSER_REG_ROOT HKCR !define DPARSER_FACTORY_NAME DParserCOMServer.VDServerClassFactory -!define DPARSER_FACTORY_CLSID {002a2de9-8bb6-484d-aa02-7e4ad4084715} +!define DPARSER_FACTORY_CLSID {002a2de9-8bb6-484d-aa05-7e4ad4084715} !define DPARSER_VDSERVER_CLSID {002a2de9-8bb6-484d-aa05-7e4ad4084715} ; typelib and IVDServer interface inherited from vdserver.exe Function RegisterDParser -; WriteRegStr ${DPARSER_REG_ROOT} "${DPARSER_FACTORY_NAME}\CLSID" "" ${DPARSER_FACTORY_CLSID} -; WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_FACTORY_CLSID}\LocalServer32" "" $INSTDIR\DParser\DParserCOMServer.exe -; WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_FACTORY_CLSID}\ProgId" "" DParserCOMServer.VDServer -; WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_FACTORY_CLSID}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" "" "" + WriteRegStr ${DPARSER_REG_ROOT} "${DPARSER_FACTORY_NAME}\CLSID" "" ${DPARSER_FACTORY_CLSID} + WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_FACTORY_CLSID}\LocalServer32" "" $INSTDIR\DParser\DParserCOMServer.exe + WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_FACTORY_CLSID}\ProgId" "" DParserCOMServer.VDServer + WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_FACTORY_CLSID}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" "" "" - WriteRegStr ${DPARSER_REG_ROOT} "${DPARSER_FACTORY_NAME}\CLSID" "" ${DPARSER_VDSERVER_CLSID} - WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_VDSERVER_CLSID}\LocalServer32" "" $INSTDIR\DParser\DParserCOMServer.exe - WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_VDSERVER_CLSID}\ProgId" "" DParserCOMServer.VDServer - WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_VDSERVER_CLSID}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" "" "" +; WriteRegStr ${DPARSER_REG_ROOT} "${DPARSER_FACTORY_NAME}\CLSID" "" ${DPARSER_VDSERVER_CLSID} +; WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_VDSERVER_CLSID}\LocalServer32" "" $INSTDIR\DParser\DParserCOMServer.exe +; WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_VDSERVER_CLSID}\ProgId" "" DParserCOMServer.VDServer +; WriteRegStr ${DPARSER_REG_ROOT} "CLSID\${DPARSER_VDSERVER_CLSID}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" "" "" FunctionEnd @@ -1573,6 +1607,7 @@ Function un.RegisterDParser FunctionEnd +;--------------------------------------- Function VSConfigurationChanged Exch $1 ; argument "${VS2017_INSTALL_KEY}Common7\IDE" diff --git a/vdc/abothe/Parser b/vdc/abothe/Parser index 74f7f224..0e6499b7 160000 --- a/vdc/abothe/Parser +++ b/vdc/abothe/Parser @@ -1 +1 @@ -Subproject commit 74f7f224f394cdf865b8405bdd54e0159a56e5a4 +Subproject commit 0e6499b7735bfcb7f10227f145cc5fb4df2965c1 diff --git a/vdc/dmdserver/ddmdrmem.d b/vdc/dmdserver/ddmdrmem.d index c10595a7..8c1aaa12 100644 --- a/vdc/dmdserver/ddmdrmem.d +++ b/vdc/dmdserver/ddmdrmem.d @@ -36,6 +36,12 @@ extern (C++) struct Mem __gshared static oom = new Error("out of memory"); throw oom; } + static void* check(void* p) nothrow + { + if (!p) + error(); + return p; + } extern(D) __gshared immutable cancelError = new Error("cancel malloc"); extern(D) __gshared bool cancel; diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd new file mode 160000 index 00000000..772865de --- /dev/null +++ b/vdc/dmdserver/dmd @@ -0,0 +1 @@ +Subproject commit 772865de420577b0e4575f7ced4333b28f7dbd42 diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index fcd6ca9a..45ef5d1c 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -475,7 +475,7 @@ class DMDServer : ComObject, IVDServer mDefSpan.start.line = startLine; mDefSpan.start.index = startIndex + 1; mDefSpan.end.line = endLine; - mDefSpan.end.index = endIndex + 1; + mDefSpan.end.index = endIndex; // last character preferred position for evaluation ModuleData* md; synchronized(gErrorSync) @@ -493,7 +493,7 @@ class DMDServer : ComObject, IVDServer try { if (auto m = md.analyzedModule) - deffilename = findDefinition(m, mDefSpan.start.line, mDefSpan.start.index); + deffilename = findDefinition(m, mDefSpan.end.line, mDefSpan.end.index); else deffilename = "analyzing..."; } @@ -526,10 +526,10 @@ class DMDServer : ComObject, IVDServer version(DebugServer) dbglog("GetDefinitionResult: " ~ mLastDefFile); writeReadyMessage(); - startLine = mDefSpan.start.line; - startIndex = mDefSpan.start.index - 1; - endLine = mDefSpan.start.line; - endIndex = mDefSpan.start.index; + startLine = mDefSpan.end.line; + startIndex = mDefSpan.end.index - 1; + endLine = mDefSpan.end.line; + endIndex = mDefSpan.end.index; *answer = allocBSTR(mLastDefFile); return S_OK; } @@ -817,6 +817,11 @@ class DMDServer : ComObject, IVDServer void analyzeModules(ModuleData* rootModule) { + if (rootModule.parsedModule) + rootModule.analyzedModule = analyzeModule(rootModule.parsedModule, mOptions); + + version(none) { + version(none) { clearDmdStatics(); @@ -935,11 +940,13 @@ class DMDServer : ComObject, IVDServer for (size_t i = 0; i < mModules.length; i++) { ModuleData* md = mModules[i]; - Module m = cloneModule(md.parsedModule); - m.importedFrom = m; - m = m.resolvePackage(); - md.analyzedModule = m; - Module.modules.insert(m); + if (Module m = cloneModule(md.parsedModule)) + { + m.importedFrom = m; + m = m.resolvePackage(); + md.analyzedModule = m; + Module.modules.insert(m); + } } Module.rootModule = rootModule.analyzedModule; Module.loadModuleHandler = (const ref Loc location, IdentifiersAtLoc* packages, Identifier ident) @@ -949,19 +956,22 @@ class DMDServer : ComObject, IVDServer for (size_t i = 0; i < mModules.length; i++) { - Module m = mModules[i].analyzedModule; - m.importAll(null); + if (Module m = mModules[i].analyzedModule) + m.importAll(null); } version(all) { - Module.rootModule.dsymbolSemantic(null); - Module.dprogress = 1; - Module.runDeferredSemantic(); - Module.rootModule.semantic2(null); - Module.runDeferredSemantic2(); - Module.rootModule.semantic3(null); - Module.runDeferredSemantic3(); + if (Module.rootModule) + { + Module.rootModule.dsymbolSemantic(null); + Module.dprogress = 1; + Module.runDeferredSemantic(); + Module.rootModule.semantic2(null); + Module.runDeferredSemantic2(); + Module.rootModule.semantic3(null); + Module.runDeferredSemantic3(); + } } else { @@ -990,6 +1000,7 @@ else m.semantic3(null); } Module.runDeferredSemantic3(); +} } } @@ -1065,12 +1076,13 @@ unittest DMDServer srv = newCom!DMDServer; srv.mPredefineVersions = true; + srv.mOptions.predefineDefaultVersions = true; addref(srv); scope(exit) release(srv); auto filename = allocBSTR("source.d"); - auto imp = allocBSTR(r"c:\s\d\rainers\druntime\import" ~ "\n" ~ - r"c:\s\d\rainers\phobos"); + auto imp = allocBSTR(r"c:\s\d\dlang\druntime\import" ~ "\n" ~ + r"c:\s\d\dlang\phobos"); auto empty = allocBSTR(""); uint flags = ConfigureFlags!()(false, //bool unittestOn false, //bool debugOn, diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index f8770706..fd3764da 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -1151,11 +1151,11 @@ 0 0 0 - 0 + 1 $(CC) -c -nologo -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 1 0 - c:\l\d\dmd2\windows\bin\dmd.exe + c:\s\d\dlang\dmd\generated\Windows\Release\x64\dmd.exe dmd\src ..\.. $(DMDInstallDir)\src\druntime\src dmd dmd\res ..\..\bin\$(ConfigurationName)\$(PlatformName) @@ -1506,7 +1506,7 @@ - + diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index 652c676c..a821c7d5 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -11,6 +11,7 @@ module vdc.dmdserver.semanalysis; import vdc.dmdserver.dmdinit; import vdc.dmdserver.dmderrors; import vdc.dmdserver.semvisitor; +import vdc.ivdserver; import dmd.arraytypes; import dmd.cond; @@ -196,7 +197,7 @@ unittest opts.predefineDefaultVersions = true; opts.x64 = true; opts.msvcrt = true; - opts.importDirs = [ r"c:\s\d\rainers\druntime\import", r"c:\s\d\rainers\phobos" ]; + opts.importDirs = [ r"c:\s\d\dlang\druntime\import", r"c:\s\d\dlang\phobos" ]; auto filename = "source.d"; @@ -266,6 +267,42 @@ unittest assert_equal(expansions[i].split(':')[0], expected[i]); } + void checkIdentifierTypes(Module analyzedModule, IdTypePos[][string] expectedPos) + { + string[] expected; + foreach(id, pos; expectedPos) + { + string ids = id.idup ~ ":" ~ idPositionsToString(pos); + expected ~= ids; + } + + import std.algorithm, std.array, std.string; + string stridtypes = findIdentifierTypes(analyzedModule); + string[] idtypes = splitLines(stridtypes); + idtypes.sort(); + expected.sort(); + assert_equal(idtypes.length, expected.length); + for (size_t i = 0; i < idtypes.length; i++) + assert_equal(idtypes[i], expected[i]); + } + + static struct TextPos + { + int line; + int column; + } + void checkReferences(Module analyzedModule, int line, int col, TextPos[] expected) + { + import std.algorithm, std.array, std.string; + auto refs = findReferencesInModule(analyzedModule, line, col); + assert_equal(refs.length, expected.length); + for (size_t i = 0; i < refs.length; i++) + { + assert_equal(refs[i].loc.linnum, expected[i].line); + assert_equal(refs[i].loc.charnum, expected[i].column); + } + } + void dumpAST(Module mod) { import dmd.root.outbuffer; @@ -407,6 +444,11 @@ unittest S anS; int x = anS.fun(1); // Line 10 } + int fun(S s) + { + auto p = new S(1); + return s.field1; // Line 15 + } }; m = checkErrors(source, ""); @@ -422,6 +464,11 @@ unittest checkTip(m, 10, 12, "(local variable) source.S anS"); checkTip(m, 10, 16, "int source.S.fun(int par)"); + checkTip(m, 12, 11, "(struct) source.S"); + + checkDefinition(m, 10, 16, "source.d", 5, 8); // fun + checkDefinition(m, 14, 17, "source.d", 2, 10); // S + source = q{ // Line 1 struct ST(T) @@ -484,4 +531,69 @@ unittest checkExpansions(m, 12, 16, "f", [ "field1", "field2", "fun" ]); checkExpansions(m, 13, 16, "", [ "field1", "field2", "fun", "more" ]); checkExpansions(m, 13, 13, "an", [ "anS" ]); + + source = + q{ // Line 1 + struct S + { + int fun(int par) { return par; } + } // Line 5 + void fun(int rec) + { + S anS; + int x = anS.fun(1); + if (rec) // Line 10 + fun(false); + } + }; + m = checkErrors(source, ""); + + IdTypePos[][string] exp = [ + "S": [ IdTypePos(TypeReferenceKind.Struct) ], + "x": [ IdTypePos(TypeReferenceKind.LocalVariable) ], + "anS": [ IdTypePos(TypeReferenceKind.LocalVariable) ], + "rec": [ IdTypePos(TypeReferenceKind.ParameterVariable) ], + "par": [ IdTypePos(TypeReferenceKind.ParameterVariable) ], + "fun": [ IdTypePos(TypeReferenceKind.Method), + IdTypePos(TypeReferenceKind.Function, 6, 8), + IdTypePos(TypeReferenceKind.Method, 9, 16), + IdTypePos(TypeReferenceKind.Function, 11, 5)], + ]; + checkIdentifierTypes(m, exp); + + source = + q{ // Line 1 + struct S + { + int fun(int par) { return par; } + int foo() { return fun(1); } // Line 5 + } + void fun(int rec) + { + S anS; + int x = anS.fun(1); // Line 10 + if (rec) fun(false); + } + }; + m = checkErrors(source, ""); + + checkReferences(m, 4, 8, [TextPos(4,8), TextPos(5, 23), TextPos(10, 16)]); + + // foreach lowered to for + source = q{ // Line 1 + import std.range; + int fun(int rec) + { + int sum = 0; // Line 5 + foreach(i; iota(0, rec)) + sum += i; + return sum; + } + }; + m = checkErrors(source, ""); + dumpAST(m); + + checkTip(m, 6, 12, "(local variable) int i"); + checkTip(m, 7, 5, "(local variable) int sum"); + checkTip(m, 7, 12, "(local variable) int i"); } diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index a12a0f58..f74c5a22 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -337,6 +337,9 @@ extern(C++) class ASTVisitor : StoppableVisitor visitExpression(stmt.increment); if (!stop) visit(cast(Statement)stmt); + + if (!stop && stmt.loweredFrom) + stmt.loweredFrom.accept(this); } override void visit(ForeachStatement stmt) @@ -718,10 +721,11 @@ extern(C++) class FindASTVisitor : ASTVisitor override void visit(VarDeclaration decl) { - if (decl.originalType && decl.originalType.ty == Tident) - visitTypeIdentifier(cast(TypeIdentifier) decl.originalType, decl.type); - else if (decl.type && decl.type.ty == Tident) // not yet semantically analyzed (or a template declaration) - visitTypeIdentifier(cast(TypeIdentifier) decl.type, decl.type); + visitTypeIdentifier(decl.parsedType, decl.type); + if (!found && decl.originalType != decl.parsedType) + visitTypeIdentifier(decl.originalType, decl.type); + if (!found && decl.type != decl.originalType && decl.type != decl.parsedType) + visitTypeIdentifier(decl.type, decl.type); // not yet semantically analyzed (or a template declaration) super.visit(decl); } @@ -749,10 +753,7 @@ extern(C++) class FindASTVisitor : ASTVisitor { foreach (bc; *(cd.baseclasses)) { - if (bc.originalType && bc.originalType.ty == Tident) - { - visitTypeIdentifier(cast(TypeIdentifier) bc.originalType, bc.type); - } + visitTypeIdentifier(bc.parsedType, bc.type); } } visit(cast(AggregateDeclaration)cd); @@ -765,15 +766,18 @@ extern(C++) class FindASTVisitor : ASTVisitor foundScope = decl.scopesym; } - void visitTypeIdentifier(TypeIdentifier originalType, Type resolvedType) + void visitTypeIdentifier(Type originalType, Type resolvedType) { - Loc loc = originalType.loc; - if (matchIdentifier(loc, originalType.ident)) + if (found || !originalType || originalType.ty != Tident) + return; + auto otype = cast(TypeIdentifier) originalType; + Loc loc = otype.loc; + if (matchIdentifier(loc, otype.ident)) foundNode(resolvedType); // guess qualified name to be without spaces - loc.charnum += originalType.ident.toString().length + 1; - foreach (id; originalType.idents) + loc.charnum += otype.ident.toString().length + 1; + foreach (id; otype.idents) { if (id.dyncast() == DYNCAST.identifier) { @@ -1066,14 +1070,23 @@ Loc[] findBinaryIsInLocations(Module mod) } //////////////////////////////////////////////////////////////////////////////// +struct IdTypePos +{ + int type; + int line; + int col; +} + +string idPositionsToString(IdTypePos[] pos) +{ + string ids = pos[0].type.to!string(); + foreach (ref p; pos[1..$]) + ids ~= ";" ~ p.type.to!string() ~ "," ~ p.line.to!string() ~ "," ~ p.col.to!string(); + return ids; +} + string findIdentifierTypes(Module mod) { - static struct IdTypePos - { - int type; - int line; - int col; - } extern(C++) class IdentifierTypesVisitor : ASTVisitor { IdTypePos[][const(char)[]] idTypes; @@ -1113,9 +1126,9 @@ string findIdentifierTypes(Module mod) { auto p = decl.toParent2; if (p && p.isAggregateDeclaration) - addIdent(loc, ident, TypeReferenceKind.Function); - else addIdent(loc, ident, TypeReferenceKind.Method); + else + addIdent(loc, ident, TypeReferenceKind.Function); } else if (decl.isParameter()) addIdent(loc, ident, TypeReferenceKind.ParameterVariable); @@ -1167,7 +1180,23 @@ string findIdentifierTypes(Module mod) override void visit(VarDeclaration decl) { addType(decl.loc, decl.type, decl.originalType); - visit(cast(Declaration)decl); + if (decl.parsedType != decl.originalType) + addType(decl.loc, decl.type, decl.parsedType); + super.visit(decl); + } + + override void visit(SymbolExp expr) + { + if (expr.var && expr.var.ident) + addDeclaration(expr.loc, expr.var); + super.visit(expr); + } + + override void visit(DotVarExp dve) + { + if (dve.var && dve.var.ident) + addDeclaration(dve.varloc.filename ? dve.varloc : dve.loc, dve.var); + super.visit(dve); } override void visit(Import imp) @@ -1217,9 +1246,7 @@ string findIdentifierTypes(Module mod) string s; foreach(id, pos; itv.idTypes) { - string ids = id.idup ~ ":" ~ pos[0].type.to!string(); - foreach (ref p; pos[1..$]) - ids ~= ";" ~ p.type.to!string() ~ "," ~ p.line.to!string() ~ "," ~ p.col.to!string(); + string ids = id.idup ~ ":" ~ idPositionsToString(pos); s ~= ids ~ "\n"; } return s; @@ -1423,6 +1450,8 @@ ScopeDsymbol typeSymbol(Type type) Module cloneModule(Module mo) { + if (!mo) + return null; Module m = new Module(mo.srcfile.toString(), mo.ident, mo.isDocFile, mo.isHdrFile); *cast(FileName*)&(m.srcfile) = mo.srcfile; // keep identical source file name pointer m.isPackageFile = mo.isPackageFile; diff --git a/visuald/propertypage.d b/visuald/propertypage.d index 6237b2c7..b549798b 100644 --- a/visuald/propertypage.d +++ b/visuald/propertypage.d @@ -37,7 +37,7 @@ import std.path; import std.process : environment; import std.string; -debug version = DParserOption; +version = DParserOption; enum hasDubSupport = false; class PropertyWindow : Window @@ -2939,6 +2939,7 @@ class IntellisensePropertyPage : GlobalPropertyPage override void CreateControls() { AddTitleLine("Semantic analysis"); + version(DParserOption) AddControl("", mUseDmdParser = new CheckBox(mCanvas, "Experimental: use DMD parsing engine for semantic analysis")); AddControl("", mMixinAnalysis = new CheckBox(mCanvas, "Enable mixin analysis")); AddControl("", mUFCSExpansions = new CheckBox(mCanvas, "Enable UFCS expansions")); //AddControl("", mSemanticGotoDef = new CheckBox(mCanvas, "Use semantic analysis for \"Goto Definition\" (before trying JSON info)")); @@ -2947,7 +2948,6 @@ class IntellisensePropertyPage : GlobalPropertyPage //AddControl("", mExpandFromBuffer = new CheckBox(mCanvas, "Expansions from text buffer")); AddControl("", mExpandFromJSON = new CheckBox(mCanvas, "Expansions from JSON browse information")); AddControl("Show expansion when", mExpandTrigger = new ComboBox(mCanvas, [ "pressing Ctrl+Space", "+ writing '.'", "+ writing an identifier" ], false)); - version(DParserOption) AddControl("", mUseDParser = new CheckBox(mCanvas, "Use Alexander Bothe's D parsing engine for semantic analysis")); AddControl("", mExactExpMatch = new CheckBox(mCanvas, "Expansions match exact start instead of case insensitive sub string")); AddControl("Sort expansions", mSortExpMode = new ComboBox(mCanvas, [ "alphabetically", "by type", "by declaration and scope" ], false)); AddTitleLine("Tooltips"); @@ -2963,7 +2963,7 @@ class IntellisensePropertyPage : GlobalPropertyPage void EnableControls() { - version(DParserOption) bool useDParser = mUseDParser.isChecked(); + version(DParserOption) bool useDParser = !mUseDmdParser.isChecked(); else bool useDParser = true; mMixinAnalysis.setEnabled(useDParser); mUFCSExpansions.setEnabled(useDParser); @@ -2980,7 +2980,7 @@ class IntellisensePropertyPage : GlobalPropertyPage mShowTypeInTooltip.setChecked(opts.showTypeInTooltip); mShowValueInTooltip.setChecked(opts.showValueInTooltip); //mSemanticGotoDef.setChecked(opts.semanticGotoDef); - version(DParserOption) mUseDParser.setChecked(opts.useDParser); + version(DParserOption) mUseDmdParser.setChecked(!opts.useDParser); mMixinAnalysis.setChecked(opts.mixinAnalysis); mUFCSExpansions.setChecked(opts.UFCSExpansions); mSortExpMode.setSelection(opts.sortExpMode); @@ -2999,7 +2999,7 @@ class IntellisensePropertyPage : GlobalPropertyPage changes += changeOption(mShowTypeInTooltip.isChecked(), opts.showTypeInTooltip, refopts.showTypeInTooltip); changes += changeOption(mShowValueInTooltip.isChecked(), opts.showValueInTooltip, refopts.showValueInTooltip); //changes += changeOption(mSemanticGotoDef.isChecked(), opts.semanticGotoDef, refopts.semanticGotoDef); - version(DParserOption) changes += changeOption(mUseDParser.isChecked(), opts.useDParser, refopts.useDParser); + 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(cast(ubyte) mSortExpMode.getSelection(), opts.sortExpMode, refopts.sortExpMode); @@ -3014,7 +3014,7 @@ class IntellisensePropertyPage : GlobalPropertyPage CheckBox mShowTypeInTooltip; CheckBox mShowValueInTooltip; //CheckBox mSemanticGotoDef; - version(DParserOption) CheckBox mUseDParser; + version(DParserOption) CheckBox mUseDmdParser; CheckBox mUFCSExpansions; ComboBox mSortExpMode; CheckBox mExactExpMatch; diff --git a/visuald/vdserverclient.d b/visuald/vdserverclient.d index a54534ca..13bd569c 100644 --- a/visuald/vdserverclient.d +++ b/visuald/vdserverclient.d @@ -62,7 +62,16 @@ private void dbglog(string s) else { if(!dbgfh) - dbgfh = fopen("c:/tmp/vdclient.log", "w"); + { + import std.file; + string fname = tempDir(); + char[20] name = "/vdclient0.log"; + for (char i = '0'; !dbgfh && i <= '9'; i++) + { + name[9] = i; + dbgfh = fopen((fname ~ name).ptr, "w"); + } + } SysTime now = Clock.currTime(); uint tid = sdk.win32.winbase.GetCurrentThreadId(); auto len = fprintf(dbgfh, "%02d:%02d:%02d - %04x - ", From 36e59fed0bcbbed8bdd42f2dba2f775200564562 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 8 Sep 2019 15:37:09 +0200 Subject: [PATCH 33/73] fix column of findIdentifierTypes resolve type in CastExp resolve TypeIdentifier in some complex types --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/dmdserver.d | 26 ++++++++++- vdc/dmdserver/semanalysis.d | 28 ++++++------ vdc/dmdserver/semvisitor.d | 89 ++++++++++++++++++++++++++----------- 4 files changed, 103 insertions(+), 42 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index 772865de..dec8f6de 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit 772865de420577b0e4575f7ced4333b28f7dbd42 +Subproject commit dec8f6de4a09d84e71abc9824ba65b6b8452cff7 diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index 45ef5d1c..11b44a6f 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -752,7 +752,10 @@ class DMDServer : ComObject, IVDServer try { if (auto m = md.analyzedModule) - identiferTypes = findIdentifierTypes(m); + { + auto res = findIdentifierTypes(m); + identiferTypes = findIdentifierTypesResultToString(res); + } else identiferTypes = "identifying..."; } @@ -1064,6 +1067,27 @@ private: //////////////////////////////////////////////////////////////// +string idPositionsToString(IdTypePos[] pos) +{ + string ids = pos[0].type.to!string(); + foreach (ref p; pos[1..$]) + ids ~= ";" ~ p.type.to!string() ~ "," ~ p.line.to!string() ~ "," ~ (p.col - 1).to!string(); + return ids; +} + +string findIdentifierTypesResultToString(FindIdentifierTypesResult res) +{ + string s; + foreach(id, pos; res) + { + string ids = id.idup ~ ":" ~ idPositionsToString(pos); + s ~= ids ~ "\n"; + } + return s; +} + +//////////////////////////////////////////////////////////////// + extern(C) int _CrtDumpMemoryLeaks(); extern(C) void dumpGC(); diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index a821c7d5..074c2a3a 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -201,7 +201,7 @@ unittest auto filename = "source.d"; - void assert_equal(S, T)(S s, T t) + static void assert_equal(S, T)(S s, T t) { if (s == t) return; @@ -267,23 +267,22 @@ unittest assert_equal(expansions[i].split(':')[0], expected[i]); } - void checkIdentifierTypes(Module analyzedModule, IdTypePos[][string] expectedPos) + void checkIdentifierTypes(Module analyzedModule, IdTypePos[][string] expected) { - string[] expected; - foreach(id, pos; expectedPos) + static void assert_equalPositions(IdTypePos[] s, IdTypePos[] t) { - string ids = id.idup ~ ":" ~ idPositionsToString(pos); - expected ~= ids; + assert_equal(s.length, t.length); + assert_equal(s[0].type, t[0].type); + foreach (i; 1.. s.length) + assert_equal(s[i], t[i]); } - import std.algorithm, std.array, std.string; - string stridtypes = findIdentifierTypes(analyzedModule); - string[] idtypes = splitLines(stridtypes); - idtypes.sort(); - expected.sort(); + auto idtypes = findIdentifierTypes(analyzedModule); assert_equal(idtypes.length, expected.length); - for (size_t i = 0; i < idtypes.length; i++) - assert_equal(idtypes[i], expected[i]); + auto ids = idtypes.keys(); + ids.sort(); + foreach (i, id; ids) + assert_equalPositions(idtypes[id], expected[id]); } static struct TextPos @@ -493,6 +492,7 @@ unittest } catch(Exception e) { // Line 10 + auto err = cast(Error) e; Exception* pe = &e; throw new Error("unexpected"); } @@ -506,6 +506,8 @@ unittest checkTip(m, 9, 20, "(local variable) object.Exception e"); checkTip(m, 9, 10, "(class) object.Exception"); + checkTip(m, 11, 21, "(class) object.Error"); + checkTip(m, 12, 5, "(class) object.Exception"); source = q{ // Line 1 diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index f74c5a22..5ee85d56 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -576,6 +576,14 @@ extern(C++) class FindASTVisitor : ASTVisitor visit(cast(TypeQualified)t); } + override void visit(CastExp expr) + { + visitTypeIdentifier(expr.parsedTo, expr.to); + if (expr.parsedTo != expr.to) + visitTypeIdentifier(expr.to, expr.to); + super.visit(expr); + } + override void visit(CompoundStatement cs) { // optimize to only visit members in approriate source range @@ -768,23 +776,45 @@ extern(C++) class FindASTVisitor : ASTVisitor void visitTypeIdentifier(Type originalType, Type resolvedType) { - if (found || !originalType || originalType.ty != Tident) + if (found || !originalType || !resolvedType) return; + while (originalType.ty != Tident) + { + if (originalType.ty != resolvedType.ty) + return; + switch (originalType.ty) + { + case Tarray: + case Tpointer: + case Treference: + case Tsarray: + case Tvector: + originalType = (cast(TypeNext) originalType).next; + resolvedType = (cast(TypeNext) resolvedType).next; + break; + default: + return; + } + } auto otype = cast(TypeIdentifier) originalType; Loc loc = otype.loc; if (matchIdentifier(loc, otype.ident)) + { foundNode(resolvedType); - - // guess qualified name to be without spaces - loc.charnum += otype.ident.toString().length + 1; - foreach (id; otype.idents) + } + else { - if (id.dyncast() == DYNCAST.identifier) + // guess qualified name to be without spaces + loc.charnum += otype.ident.toString().length + 1; + foreach (id; otype.idents) { - auto ident = cast(Identifier)id; - if (matchIdentifier(loc, ident)) - foundNode(resolvedType); - loc.charnum += ident.toString().length + 1; + if (id.dyncast() == DYNCAST.identifier) + { + auto ident = cast(Identifier)id; + if (matchIdentifier(loc, ident)) + foundNode(resolvedType); + loc.charnum += ident.toString().length + 1; + } } } } @@ -1077,19 +1107,13 @@ struct IdTypePos int col; } -string idPositionsToString(IdTypePos[] pos) -{ - string ids = pos[0].type.to!string(); - foreach (ref p; pos[1..$]) - ids ~= ";" ~ p.type.to!string() ~ "," ~ p.line.to!string() ~ "," ~ p.col.to!string(); - return ids; -} +alias FindIdentifierTypesResult = IdTypePos[][const(char)[]]; -string findIdentifierTypes(Module mod) +FindIdentifierTypesResult findIdentifierTypes(Module mod) { extern(C++) class IdentifierTypesVisitor : ASTVisitor { - IdTypePos[][const(char)[]] idTypes; + FindIdentifierTypesResult idTypes; const(char)* filename; alias visit = ASTVisitor.visit; @@ -1152,6 +1176,23 @@ string findIdentifierTypes(Module mod) void addType(ref const Loc loc, Type type, Type originalType) { + while (type && originalType && type.ty == originalType.ty) + { + switch (originalType.ty) + { + case Tarray: + case Tpointer: + case Treference: + case Tsarray: + case Tvector: + originalType = (cast(TypeNext) originalType).next; + type = (cast(TypeNext) type ).next; + continue; + default: + break; + } + break; + } static TypeReferenceKind refkind(Type t) { switch (t.ty) @@ -1163,7 +1204,7 @@ string findIdentifierTypes(Module mod) default: return TypeReferenceKind.BasicType; } } - if (originalType && originalType.ty == Tident) + if (originalType && originalType.ty == Tident && type) addIdent(loc, (cast(TypeIdentifier) originalType).ident, refkind(type)); else if (type && type.ty == Tident) // not yet semantically analyzed (or a template declaration) addIdent(loc, (cast(TypeIdentifier) type).ident, TypeReferenceKind.TemplateTypeParameter); @@ -1243,13 +1284,7 @@ string findIdentifierTypes(Module mod) itv.filename = mod.srcfile.toChars(); mod.accept(itv); - string s; - foreach(id, pos; itv.idTypes) - { - string ids = id.idup ~ ":" ~ idPositionsToString(pos); - s ~= ids ~ "\n"; - } - return s; + return itv.idTypes; } //////////////////////////////////////////////////////////////////////////////// From 447b5a1166c4d689d0cef4e90bc6b43869fde01e Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 8 Sep 2019 16:47:26 +0200 Subject: [PATCH 34/73] rebase dmd to master --- vdc/dmdserver/ddmdrmem.d | 2 ++ vdc/dmdserver/dmd | 2 +- vdc/dmdserver/dmdinit.d | 7 +------ vdc/dmdserver/dmdserver.visualdproj | 1 + 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/vdc/dmdserver/ddmdrmem.d b/vdc/dmdserver/ddmdrmem.d index 8c1aaa12..53a24d8b 100644 --- a/vdc/dmdserver/ddmdrmem.d +++ b/vdc/dmdserver/ddmdrmem.d @@ -5,6 +5,8 @@ import core.stdc.string : strlen; extern (C++) struct Mem { + enum isGCEnabled = true; + static char* xstrdup(const(char)* p) nothrow { return p[0 .. strlen(p) + 1].dup.ptr; diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index dec8f6de..7d63208d 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit dec8f6de4a09d84e71abc9824ba65b6b8452cff7 +Subproject commit 7d63208dae982b30fb63e03208a23d439bb3bdc5 diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d index 5882fe87..79d01627 100644 --- a/vdc/dmdserver/dmdinit.d +++ b/vdc/dmdserver/dmdinit.d @@ -112,14 +112,9 @@ void clearSemanticStatics() TemplateTypeParameter.tdummy = null; TemplateAliasParameter.sdummy = null; - CtfeStatus.callDepth = 0; - CtfeStatus.stackTraceCallsToSuppress = 0; - CtfeStatus.maxCallDepth = 0; - CtfeStatus.numAssignments = 0; - VarDeclaration.nextSequenceNumber = 0; - entrypoint = cast(Module)&entrypoint; // disable generation of C main + //entrypoint = cast(Module)&entrypoint; // disable generation of C main // Package.this.packageTag? // funcDeclarationSemantic.printedMain? diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index fd3764da..58b154c0 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -1569,6 +1569,7 @@ + From 2bcf15dd82e2edb6c2645a601307d607f70dfa72 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 8 Sep 2019 18:49:54 +0200 Subject: [PATCH 35/73] fix coloring of NewExp --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/semvisitor.d | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index 7d63208d..a6805528 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit 7d63208dae982b30fb63e03208a23d439bb3bdc5 +Subproject commit a6805528dd95c92253a0c393016d42ef37feef98 diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 5ee85d56..df5ac8a3 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -1233,6 +1233,18 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) super.visit(expr); } + override void visit(NewExp ne) + { + if (ne.member) + ne.member.accept(this); + + addType(ne.loc, ne.newtype, ne.parsedType); + if (ne.newtype != ne.parsedType) + addType(ne.loc, ne.newtype, ne.newtype); + + super.visit(ne); + } + override void visit(DotVarExp dve) { if (dve.var && dve.var.ident) From dc359bb1cb831b2f47ef855ffad53d101f14f131 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 8 Sep 2019 19:09:50 +0200 Subject: [PATCH 36/73] file name cleanup --- vdc/dmdserver/ddmderrors.d | 253 ------------------------ vdc/dmdserver/dmderrors.d | 7 + vdc/dmdserver/dmdinit.d | 15 +- vdc/dmdserver/{ddmdlib.d => dmdlib.d} | 0 vdc/dmdserver/{ddmdrmem.d => dmdrmem.d} | 0 vdc/dmdserver/dmdserver.visualdproj | 5 +- 6 files changed, 17 insertions(+), 263 deletions(-) delete mode 100644 vdc/dmdserver/ddmderrors.d rename vdc/dmdserver/{ddmdlib.d => dmdlib.d} (100%) rename vdc/dmdserver/{ddmdrmem.d => dmdrmem.d} (100%) diff --git a/vdc/dmdserver/ddmderrors.d b/vdc/dmdserver/ddmderrors.d deleted file mode 100644 index 6e5790a0..00000000 --- a/vdc/dmdserver/ddmderrors.d +++ /dev/null @@ -1,253 +0,0 @@ -/** - * Compiler implementation of the - * $(LINK2 http://www.dlang.org, D programming language). - * - * Copyright: Copyright (c) 1999-2017 by Digital Mars, All Rights Reserved - * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) - * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/ddmd/errors.d, _errors.d) - */ - -module dmderrors; - -// Online documentation: https://dlang.org/phobos/ddmd_errors.html - -import core.stdc.stdarg; -import core.stdc.stdio; -import core.stdc.stdlib; -import core.stdc.string; -import dmd.globals; -import dmd.root.outbuffer; -import dmd.root.rmem; -import dmd.console; - -/********************** - * Color highlighting to classify messages - */ -enum Classification -{ - error = Color.brightRed, /// for errors - gagged = Color.brightBlue, /// for gagged errors - warning = Color.brightYellow, /// for warnings - deprecation = Color.brightCyan, /// for deprecations - supplemental = Color.brightMagenta, /// for supplemental info (e.g. instantiation trace) -} - -/************************************** - * Print error message - */ -extern (C++) void error(const ref Loc loc, const(char)* format, ...) -{ - va_list ap; - va_start(ap, format); - verror(loc, format, ap); - va_end(ap); -} - -extern (C++) void error(Loc loc, const(char)* format, ...) -{ - va_list ap; - va_start(ap, format); - verror(loc, format, ap); - va_end(ap); -} - -extern (C++) void error(const(char)* filename, uint linnum, uint charnum, const(char)* format, ...) -{ - Loc loc; - loc.filename = filename; - loc.linnum = linnum; - loc.charnum = charnum; - va_list ap; - va_start(ap, format); - verror(loc, format, ap); - va_end(ap); -} - -extern (C++) void errorSupplemental(const ref Loc loc, const(char)* format, ...) -{ - va_list ap; - va_start(ap, format); - verrorSupplemental(loc, format, ap); - va_end(ap); -} - -extern (C++) void warning(const ref Loc loc, const(char)* format, ...) -{ - va_list ap; - va_start(ap, format); - vwarning(loc, format, ap); - va_end(ap); -} - -extern (C++) void warningSupplemental(const ref Loc loc, const(char)* format, ...) -{ - va_list ap; - va_start(ap, format); - vwarningSupplemental(loc, format, ap); - va_end(ap); -} - -extern (C++) void deprecation(const ref Loc loc, const(char)* format, ...) -{ - va_list ap; - va_start(ap, format); - vdeprecation(loc, format, ap); - va_end(ap); -} - -extern (C++) void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) -{ - va_list ap; - va_start(ap, format); - vdeprecation(loc, format, ap); - va_end(ap); -} - -extern(C++) -void verrorPrint(const ref Loc loc, Color headerColor, const(char)* header, - const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null); - -// header is "Error: " by default (see errors.h) -extern (C++) void verror(const ref Loc loc, const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null, const(char)* header = "Error: ") -{ - global.errors++; - if (!global.gag) - { - verrorPrint(loc, Classification.error, header, format, ap, p1, p2); - if (global.params.errorLimit && global.errors >= global.params.errorLimit) - fatal(); // moderate blizzard of cascading messages - } - else - { - if (global.params.showGaggedErrors) - { - fprintf(stderr, "(spec:%d) ", global.gag); - verrorPrint(loc, Classification.gagged, header, format, ap, p1, p2); - } - global.gaggedErrors++; - } -} - -// Doesn't increase error count, doesn't print "Error:". -extern (C++) void verrorSupplemental(const ref Loc loc, const(char)* format, va_list ap) -{ - Color color; - if (global.gag) - { - if (!global.params.showGaggedErrors) - return; - color = Classification.gagged; - } - else - color = Classification.supplemental; - verrorPrint(loc, color, " ", format, ap); -} - -extern (C++) void vwarning(const ref Loc loc, const(char)* format, va_list ap) -{ - if (global.params.warnings && !global.gag) - { - verrorPrint(loc, Classification.warning, "Warning: ", format, ap); - //halt(); - if (global.params.warnings == 1) - global.warnings++; // warnings don't count if gagged - } -} - -extern (C++) void vwarningSupplemental(const ref Loc loc, const(char)* format, va_list ap) -{ - if (global.params.warnings && !global.gag) - verrorPrint(loc, Classification.warning, " ", format, ap); -} - -extern (C++) void vdeprecation(const ref Loc loc, const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) -{ - static __gshared const(char)* header = "Deprecation: "; - if (global.params.useDeprecated == 0) - verror(loc, format, ap, p1, p2, header); - else if (global.params.useDeprecated == 2 && !global.gag) - verrorPrint(loc, Classification.deprecation, header, format, ap, p1, p2); -} - -extern (C++) void vdeprecationSupplemental(const ref Loc loc, const(char)* format, va_list ap) -{ - if (global.params.useDeprecated == 0) - verrorSupplemental(loc, format, ap); - else if (global.params.useDeprecated == 2 && !global.gag) - verrorPrint(loc, Classification.deprecation, " ", format, ap); -} - -/*************************************** - * Call this after printing out fatal error messages to clean up and exit - * the compiler. - */ -extern (C++) void fatal() -{ - throw new Exception("fatal"); -} - -/************************************** - * Try to stop forgetting to remove the breakpoints from - * release builds. - */ -extern (C++) void halt() -{ - throw new Exception("halt"); -} - -/** -* Print a verbose message. -* Doesn't prefix or highlight messages. -* Params: -* loc = location of message -* format = printf-style format specification -* ... = printf-style variadic arguments -*/ -extern (C++) void message(const ref Loc loc, const(char)* format, ...) -{ - va_list ap; - va_start(ap, format); - vmessage(loc, format, ap); - va_end(ap); -} - -/** -* Same as above, but doesn't take a location argument. -* Params: -* format = printf-style format specification -* ... = printf-style variadic arguments -*/ -extern (C++) void message(const(char)* format, ...) -{ - va_list ap; - va_start(ap, format); - vmessage(Loc.initial, format, ap); - va_end(ap); -} - -/** -* Same as $(D message), but takes a va_list parameter. -* Params: -* loc = location of message -* format = printf-style format specification -* ap = printf-style variadic arguments -*/ -extern (C++) void vmessage(const ref Loc loc, const(char)* format, va_list ap) -{ - version(none) - { - const p = loc.toChars(); - if (*p) - { - fprintf(stdout, "%s: ", p); - mem.xfree(cast(void*)p); - } - OutBuffer tmp; - tmp.vprintf(format, ap); - fputs(tmp.peekString(), stdout); - fputc('\n', stdout); - fflush(stdout); // ensure it gets written out in case of compiler aborts - } -} - diff --git a/vdc/dmdserver/dmderrors.d b/vdc/dmdserver/dmderrors.d index 18fb45d7..68f04875 100644 --- a/vdc/dmdserver/dmderrors.d +++ b/vdc/dmdserver/dmderrors.d @@ -1,3 +1,10 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2019 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt module vdc.dmdserver.dmderrors; diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d index 79d01627..ff693366 100644 --- a/vdc/dmdserver/dmdinit.d +++ b/vdc/dmdserver/dmdinit.d @@ -1,3 +1,11 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2019 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + module vdc.dmdserver.dmdinit; import dmd.arraytypes; @@ -120,13 +128,6 @@ void clearSemanticStatics() // funcDeclarationSemantic.printedMain? /+ Type.stringtable.reset(); - - dinterpret_init(); - - Scope.freelist = null; - //Token.freelist = null; - - Identifier.initTable(); +/ } diff --git a/vdc/dmdserver/ddmdlib.d b/vdc/dmdserver/dmdlib.d similarity index 100% rename from vdc/dmdserver/ddmdlib.d rename to vdc/dmdserver/dmdlib.d diff --git a/vdc/dmdserver/ddmdrmem.d b/vdc/dmdserver/dmdrmem.d similarity index 100% rename from vdc/dmdserver/ddmdrmem.d rename to vdc/dmdserver/dmdrmem.d diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index 58b154c0..0abd6fa6 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -1603,9 +1603,8 @@ - - - + + From 5c723186c2240233ea58014ec799283f9359c7a6 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 14 Sep 2019 18:29:57 +0200 Subject: [PATCH 37/73] debug GC leaks --- c2d/c2d.visualdproj | 2 +- tools/tracegc.d | 15 ++++++++++----- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/dmdserver.d | 5 ++--- vdc/dmdserver/dmdserver.visualdproj | 8 ++++---- vdc/dmdserver/semanalysis.d | 24 +++++++++++++++++++++--- 6 files changed, 39 insertions(+), 17 deletions(-) diff --git a/c2d/c2d.visualdproj b/c2d/c2d.visualdproj index 3091b25f..bbaeeacf 100644 --- a/c2d/c2d.visualdproj +++ b/c2d/c2d.visualdproj @@ -795,7 +795,7 @@ m:\s\d\rainers\windows\bin\dmd.exe .. .. - ..\bin\$(ConfigurationName)64 + ..\bin\$(ConfigurationName)\$(PLATFORMNAME) $(OutDir)\$(ProjectName) diff --git a/tools/tracegc.d b/tools/tracegc.d index ab4165f3..07d8908f 100644 --- a/tools/tracegc.d +++ b/tools/tracegc.d @@ -1,6 +1,8 @@ module tracegc; import core.stdc.string; +import core.time; +import core.stdc.stdio; //version = traceGC; @@ -11,9 +13,8 @@ void wipeStack() memset (data.ptr, 0xff, 4096); } -version(traceGC): +version(traceGC) { import core.sys.windows.windows; -import core.stdc.stdio; import gc.impl.conservative.gc; import core.thread; @@ -927,7 +928,7 @@ void collectReferences(ConservativeGC cgc, ref HashTab!(void*, void*) references foreach(range; cgc.rangeIter) mark(range.pbot, range.ptop); - thread_scanAll(&mark); + //thread_scanAll(&mark); thread_resumeAll(); cgc.gcLock.unlock(); @@ -1125,6 +1126,8 @@ const(char)[] dmdident(ConservativeGC cgc, void* p) auto dummyIdent = Identifier.anonymous(); auto sym = cast(Dsymbol)p; auto ident = sym.ident; + if (!ident) + return null; BlkInfo syminf = cgc.queryNoSync(cast(void*)ident); if (syminf.base is null || syminf.size < Identifier.sizeof) return null; @@ -1251,12 +1254,14 @@ nextLoc: } } +} // version(traceGC) + //////////////////////////////////////////////////////////////// private __gshared MonoTime gcStartTick; private __gshared FILE* gcx_fh; private __gshared bool hadNewline = false; -private int trace_printf(ARGS...)(const char* fmt, ARGS args) nothrow +int trace_printf(ARGS...)(const char* fmt, ARGS args) nothrow { if (!gcx_fh) gcx_fh = fopen("tracegc.log", "w"); @@ -1283,7 +1288,7 @@ private int trace_printf(ARGS...)(const char* fmt, ARGS args) nothrow return len; } -private int xtrace_printf(ARGS...)(const char* fmt, ARGS args) nothrow +int xtrace_printf(ARGS...)(const char* fmt, ARGS args) nothrow { char[1024] buf; sprintf(buf.ptr, fmt, args); diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index a6805528..21fc7469 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit a6805528dd95c92253a0c393016d42ef37feef98 +Subproject commit 21fc7469eae4a31021e89c647fb9dcd373c873b9 diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index 11b44a6f..85fd150c 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -83,7 +83,7 @@ shared(Object) gDMDSync = new Object; // no multi-instances/multi-threading with shared(Object) gOptSync = new Object; // no multi-instances/multi-threading with DMD version (traceGC) - extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise", "gcopt=gc:trace disable:1" ]; + extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise", "gcopt=gc:trace disable:0" ]; else // precise GC doesn't help much because dmd erases most type info extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise", "gcopt=gc:precise" ]; @@ -1105,8 +1105,7 @@ unittest scope(exit) release(srv); auto filename = allocBSTR("source.d"); - auto imp = allocBSTR(r"c:\s\d\dlang\druntime\import" ~ "\n" ~ - r"c:\s\d\dlang\phobos"); + auto imp = allocBSTR(guessImportPaths().join("\n")); auto empty = allocBSTR(""); uint flags = ConfigureFlags!()(false, //bool unittestOn false, //bool debugOn, diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index 0abd6fa6..ef55a676 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -1394,10 +1394,10 @@ 0 0 0 - $(CC) -nologo -c -TP -Idmd\src -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\vcbuild -DTARGET_WINDOS=1 -FIwarnings.h + $(CC) -nologo -c -Idmd\src -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\vcbuild -DTARGET_WINDOS=1 -FIwarnings.h 1 1 - c:\l\d\dmd2\windows\bin\dmd.exe + c:\s\d\rainers\dmd\generated\Windows\Release\x64\dmd.exe dmd\src ..\.. $(DMDInstallDir)\src\druntime\src $(DMDInstallDir)\druntime\src dmd dmd\res ..\..\bin\$(ConfigurationName)\$(PlatformName) @@ -1603,10 +1603,10 @@ - - + + > 20, cast(long)stats.freeSize >> 20); + + version(traceGC) + if (stats.usedSize > (200 << 20)) + dumpGC(); } checkTip(m, 5, 8, "(local variable) int xyz"); From 57148e02d6bf73c3e452115f80eaaa0e80fbb3ce Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 15 Sep 2019 09:16:46 +0200 Subject: [PATCH 38/73] experimental: add colorful QuickInfo tooltips --- vdextensions/gotodef.cs | 4 +- vdextensions/quickinfo.cs | 275 ++++++++++++++++++++++++++++++++++++ vdextensions/vdext15.csproj | 31 +++- visuald/dlangsvc.d | 111 ++++++++++++++- visuald/dllmain.d | 23 ++- visuald/dpackage.d | 2 +- visuald/viewfilter.d | 2 +- visuald/visuald.def | 2 + 8 files changed, 439 insertions(+), 11 deletions(-) create mode 100644 vdextensions/quickinfo.cs diff --git a/vdextensions/gotodef.cs b/vdextensions/gotodef.cs index f3c9a96e..22c51ff1 100644 --- a/vdextensions/gotodef.cs +++ b/vdextensions/gotodef.cs @@ -165,7 +165,9 @@ public override void PreviewKeyUp(KeyEventArgs args) [Name("GotoDefVisualD")] [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; diff --git a/vdextensions/quickinfo.cs b/vdextensions/quickinfo.cs new file mode 100644 index 00000000..3407dfd0 --- /dev/null +++ b/vdextensions/quickinfo.cs @@ -0,0 +1,275 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2016 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Utilities; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Language.StandardClassification; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Text.Adornments; + +using System; +using System.ComponentModel.Composition; +using System.Collections.Generic; +using System.Windows.Controls; +using System.Windows; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Documents; +using System.Runtime.InteropServices; // DllImport + +namespace vdext15 +{ + class ClassifiedTextBlock : TextBlock + { + public ClassifiedTextBlock(string text) + : base(new Run(text)) + { + } + + public void setForeground(System.Windows.Media.Brush brush) + { + Foreground = brush; + foreach (var inl in Inlines) + inl.Foreground = brush; + } + + public void enableLink() + { + MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler( + delegate (object sender, System.Windows.Input.MouseButtonEventArgs args) + { + // Text = "clicked!"; + }); + MouseEnter += new System.Windows.Input.MouseEventHandler( + delegate (object sender, System.Windows.Input.MouseEventArgs args) + { + TextDecorations.Add(System.Windows.TextDecorations.Underline); + }); + MouseLeave += new System.Windows.Input.MouseEventHandler( + delegate (object sender, System.Windows.Input.MouseEventArgs args) + { + foreach (var td in System.Windows.TextDecorations.Underline) + TextDecorations.Remove(td); + }); + } + } + + internal sealed class VsiualDQuickInfoSource : IAsyncQuickInfoSource + { + private ITextBuffer _textBuffer; + private string _filename; + + VsiualDQuickInfoSourceProvider _provider; + + public VsiualDQuickInfoSource(VsiualDQuickInfoSourceProvider provider, ITextBuffer textBuffer) + { + _provider = provider; + _textBuffer = textBuffer; + _filename = GetFileName(_textBuffer); + } + + [DllImport("visuald.dll")] + public static extern int GetTooltip([MarshalAs(UnmanagedType.BStr)] string fname, int line, int col); + [DllImport("visuald.dll")] + public static extern bool GetTooltipResult(int request, + [MarshalAs(UnmanagedType.BStr)] out string tip, + [MarshalAs(UnmanagedType.BStr)] out string fmt); + + static bool GetQuickInfo(string fname, int line, int col, out string info, out string fmt, + CancellationToken cancellationToken) + { + try + { + int req = GetTooltip(fname, line, col); + if (req != 0) + { + while (!GetTooltipResult(req, out info, out fmt)) + { + if (cancellationToken.IsCancellationRequested) + return false; + Thread.Sleep(100); + } + return true; + } + } + catch + { + } + info = ""; + fmt = ""; + return false; + } + + public static string GetFileName(ITextBuffer buffer) + { + Microsoft.VisualStudio.TextManager.Interop.IVsTextBuffer bufferAdapter; + buffer.Properties.TryGetProperty(typeof(Microsoft.VisualStudio.TextManager.Interop.IVsTextBuffer), out bufferAdapter); + if (bufferAdapter != null) + { + var persistFileFormat = bufferAdapter as IPersistFileFormat; + if (persistFileFormat != null) + { + string ppzsFilename = null; + persistFileFormat.GetCurFile(out ppzsFilename, out _); + return ppzsFilename; + } + } + return null; + } + + public System.Windows.Media.Brush GetBrush(ITextView view, string type) + { + if (_provider.typeRegistry != null && _provider.formatMap != null) + { + var ctype = _provider.typeRegistry.GetClassificationType(type); + var cmap = _provider.formatMap.GetClassificationFormatMap(view); + if (ctype != null && cmap != null) + { + var tprop = cmap.GetTextProperties(ctype); + if (tprop != null) + return tprop.ForegroundBrush; + } + } + return null; + } + + public ClassifiedTextBlock createClassifiedTextBlock(ITextView view, string text, string type) + { + var tb = new ClassifiedTextBlock(text); + if (String.IsNullOrEmpty(text) || String.IsNullOrEmpty(text.Trim())) + return tb; + + if (type == "Identifier") + tb.enableLink(); + + // Foreground cannot be set from the constructor?! + tb.setForeground(GetBrush(view, type)); + return tb; + } + + // This is called on a background thread. + public Task GetQuickInfoItemAsync(IAsyncQuickInfoSession session, CancellationToken cancellationToken) + { + var triggerPoint = session.GetTriggerPoint(_textBuffer.CurrentSnapshot); + + if (triggerPoint != null) + { + var line = triggerPoint.Value.GetContainingLine(); + var lineNumber = triggerPoint.Value.GetContainingLine().LineNumber; + var lineSpan = _textBuffer.CurrentSnapshot.CreateTrackingSpan(line.Extent, SpanTrackingMode.EdgeInclusive); + + var column = triggerPoint.Value.Position - line.Start.Position; + string info, fmt; + if (!GetQuickInfo(_filename, lineNumber, column, out info, out fmt, cancellationToken)) + return System.Threading.Tasks.Task.FromResult(null); + + ContainerElement infoElm = null; + Application.Current.Dispatcher.Invoke(delegate + { + // back in the UI thread to allow creation of UIElements + var rows = new List(); + var secs = new List(); + + string[] ops = fmt.Split(';'); + int prevpos = 0; + string prevtype = null; + foreach (var op in ops) + { + if (prevtype == null) + prevtype = op; + else + { + string[] colname = op.Split(':'); + if (colname.Length == 2) + { + int pos; + if (Int32.TryParse(colname[0], out pos) && pos > prevpos) + { + string sec = info.Substring(prevpos, pos - prevpos); + var nls = sec.Split('\n'); + for (int n = 0; n < nls.Length - 1; n++) + { + secs.Add(createClassifiedTextBlock(session.TextView, nls[n], prevtype)); + rows.Add(new ContainerElement(ContainerElementStyle.Wrapped, secs)); + secs = new List(); + } + secs.Add(createClassifiedTextBlock(session.TextView, nls[nls.Length-1], prevtype)); + + prevtype = colname[1]; + prevpos = pos; + } + } + } + } + if (prevtype != null && prevpos < info.Length) + { + string sec = info.Substring(prevpos, info.Length - prevpos); + secs.Add(createClassifiedTextBlock(session.TextView, sec, prevtype)); + } + else + { + secs.Add(createClassifiedTextBlock(session.TextView, info, PredefinedClassificationTypeNames.SymbolDefinition)); + } + if (secs.Count > 0) + rows.Add(new ContainerElement(ContainerElementStyle.Wrapped, secs)); + + // var tb = createClassifiedTextBlock(session.TextView, " Hello again", PredefinedClassificationTypeNames.Keyword); + +/* + var lineNumberElm = new ContainerElement( + ContainerElementStyle.Wrapped, + new ClassifiedTextElement( + new ClassifiedTextRun(PredefinedClassificationTypeNames.Identifier, _filename), + new ClassifiedTextRun(PredefinedClassificationTypeNames.Keyword, " Line number: "), + new ClassifiedTextRun(PredefinedClassificationTypeNames.Identifier, $"{lineNumber + 1}"), + new ClassifiedTextRun(PredefinedClassificationTypeNames.Keyword, " Column: "), + new ClassifiedTextRun(PredefinedClassificationTypeNames.Identifier, $"{column}"))); + + rows.Add(lineNumberElm); +*/ + + infoElm = new ContainerElement(ContainerElementStyle.Stacked, rows); + }); + return System.Threading.Tasks.Task.FromResult(new QuickInfoItem(lineSpan, infoElm)); + } + + return System.Threading.Tasks.Task.FromResult(null); + } + + public void Dispose() + { + // This provider does not perform any cleanup. + } + } + + [Export(typeof(IAsyncQuickInfoSourceProvider))] + [Name("Vsiual D Quick Info Provider")] + [ContentType("d")] + [Order] + internal sealed class VsiualDQuickInfoSourceProvider : IAsyncQuickInfoSourceProvider + { + // these imports don't work in VsiualDQuickInfoSource, maybe because created in another thread? + [Import] + public IClassificationFormatMapService formatMap = null; + [Import] + public IClassificationTypeRegistryService typeRegistry = null; + + public IAsyncQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer) + { + //if (!textBuffer.ContentType.IsOfType("d")) + // return null; + + // This ensures only one instance per textbuffer is created + return textBuffer.Properties.GetOrCreateSingletonProperty(() + => new VsiualDQuickInfoSource(this, textBuffer)); + } + } +} diff --git a/vdextensions/vdext15.csproj b/vdextensions/vdext15.csproj index a5e85fac..6996da58 100644 --- a/vdextensions/vdext15.csproj +++ b/vdextensions/vdext15.csproj @@ -81,22 +81,34 @@ False $(GAC_HintPath)\Microsoft.VisualStudio.Text.Data\vs15\Microsoft.VisualStudio.Text.Data.dll - + False - $(GAC_HintPath)\Microsoft.VisualStudio.Text.Logic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Text.Logic.dll + $(GAC_HintPath)\Microsoft.VisualStudio.Text.Logic\vs15\Microsoft.VisualStudio.Text.Logic.dll - + False - $(GAC_HintPath)\Microsoft.VisualStudio.Text.UI\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Text.UI.dll + $(GAC_HintPath)\Microsoft.VisualStudio.Text.UI\vs15\Microsoft.VisualStudio.Text.UI.dll False $(GAC_HintPath)\Microsoft.VisualStudio.Text.UI.Wpf\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Text.UI.Wpf.dll - + False $(GAC_HintPath)\Microsoft.VisualStudio.Utilities\vs15\Microsoft.VisualStudio.Utilities.dll + + False + $(GAC_HintPath)\Microsoft.VisualStudio.Language\vs15\Microsoft.VisualStudio.Language.dll + + + False + $(GAC_HintPath)\Microsoft.VisualStudio.Language.Intellisense\vs15\Microsoft.VisualStudio.Language.Intellisense.dll + + + False + $(GAC_HintPath)\Microsoft.VisualStudio.Language.StandardClassification\vs15\Microsoft.VisualStudio.Language.StandardClassification.dll + @@ -117,11 +129,18 @@ C:\Windows\assembly\GAC\Microsoft.VisualStudio.OLE.Interop\7.1.40304.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.OLE.Interop.dll - C:\Windows\assembly\GAC\Microsoft.VisualStudio.Shell.Interop\7.1.40304.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Shell.Interop.dll + $(GAC_HintPath)\Microsoft.VisualStudio.Shell.Interop\vs15\Microsoft.VisualStudio.Shell.Interop.dll + + + $(GAC_HintPath)\Microsoft.VisualStudio.Shell.Interop\vs15\Microsoft.VisualStudio.Shell.Interop.dll + + + $(GAC_HintPath)\Microsoft.VisualStudio.Shell.Interop.8.0\vs15\Microsoft.VisualStudio.Shell.Interop.8.0.dll + diff --git a/visuald/dlangsvc.d b/visuald/dlangsvc.d index 01316539..264535d1 100644 --- a/visuald/dlangsvc.d +++ b/visuald/dlangsvc.d @@ -46,6 +46,7 @@ import vdc.ivdserver; static import vdc.util; import stdext.array; +import stdext.ddocmacros; import stdext.string; import stdext.path; @@ -697,8 +698,31 @@ class LanguageService : DisposingComObject, } ////////////////////////////////////////////////////////////// + extern(D) alias IdleTask = void delegate(); + IdleTask[] runInIdle; + __gshared Object syncRunInIdle = new Object; + + void addIdleTask(IdleTask task) + { + synchronized(syncRunInIdle) + runInIdle ~= task; + } + void execIdleTasks() + { + void delegate()[] toRun; + synchronized(syncRunInIdle) + { + toRun = runInIdle; + runInIdle = null; + } + foreach(r; toRun) + r(); + } + bool OnIdle() { + execIdleTasks(); + if(mVDServerClient) mVDServerClient.onIdle(); @@ -844,6 +868,91 @@ class LanguageService : DisposingComObject, return true; } + // QuickInfo callback from C# /////////////////////////////////// + + private uint mLastTipIdleTaskScheduled; + private uint mLastTipIdleTaskHandled; + + private uint mLastTipRequest; + private uint mLastTipReceived; + private wstring mLastTip; + private wstring mLastTipFmt; + + extern(D) + void tipCallback(uint request, string fname, string text, TextSpan span) + { + mLastTipReceived = request; + text = text.strip(); + text = text.replace("\r", ""); + text = replace(text, "\a", "\n\n"); + text = phobosDdocExpand(text); + + mLastTip = toUTF16(text); + + string fmt; + int state = 0; + uint pos = 0; + int prevcol = -1; + while (pos < mLastTip.length) + { + uint prevpos = pos; + int tok; + int col = dLex.scan(state, mLastTip, pos, tok); + if (col != prevcol) + { + if (prevpos > 0) + { + fmt ~= ";"; + fmt ~= to!string(prevpos); + fmt ~= ":"; + } + fmt ~= defaultColors[col == 0 ? 5 : col-1].name; + prevcol = col; + } + } + mLastTipFmt = toUTF16(fmt); + } + + uint RequestTooltip(string filename, int line, int col) + { + if (!Package.GetGlobalOptions().usesQuickInfoTooltips()) + return 0; + + if (++mLastTipIdleTaskScheduled == 0) // skip 0 as an error value + ++mLastTipIdleTaskScheduled; + uint task = mLastTipIdleTaskScheduled; + + addIdleTask(() { + if (task != mLastTipIdleTaskScheduled) + return; // ignore old requests + auto src = GetSource(filename); + if (!src) + return; + + TextSpan span = TextSpan(col, line, col + 1, line); + ConfigureSemanticProject(src); + int flags = Package.GetGlobalOptions().showValueInTooltip ? 1 : 0; + + mLastTipRequest = vdServerClient.GetTip(src.GetFileName(), &span, flags, &tipCallback); + mLastTipIdleTaskHandled = mLastTipIdleTaskScheduled; + }); + return mLastTipIdleTaskScheduled; + } + + bool GetTooltipResult(uint task, out wstring tip, out wstring fmtdesc) + { + if (task != mLastTipIdleTaskScheduled) + return true; // return empty tip for wrong request + if (task != mLastTipIdleTaskHandled) + return false; // wait some more + if (mLastTipRequest != mLastTipReceived) + return false; // wait some more + + tip = mLastTip; + fmtdesc = mLastTipFmt; + return true; + } + // semantic completion /////////////////////////////////// uint GetTip(Source src, TextSpan* pSpan, GetTipCallBack cb) @@ -1640,7 +1749,7 @@ class Source : DisposingComObject, IVsUserDataEvents, IVsTextLinesEvents, IVsTex } - // Commands -- see MarkerCommandValues for meaning of iItem param + // Commands -- see MarkerCommandValues for meaning of iItem param override HRESULT GetMarkerCommandInfo(/+[in]+/ IVsTextMarker pMarker, in int iItem, /+[out, custom(uuid_IVsTextMarkerClient, "optional")]+/ BSTR * pbstrText, /+[out]+/ DWORD* pcmdf) diff --git a/visuald/dllmain.d b/visuald/dllmain.d index 1cae8bc0..bae9dc60 100644 --- a/visuald/dllmain.d +++ b/visuald/dllmain.d @@ -188,7 +188,7 @@ void GenerateGeneralXMLW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCm } extern(Windows) -bool GetCoverageData(const(char)* fname, uint line, uint* data, uint cnt, float* covPercent) +BOOL GetCoverageData(const(char)* fname, uint line, uint* data, uint cnt, float* covPercent) { if (!Package.s_instance) return false; // not yet loaded as a package @@ -196,3 +196,24 @@ bool GetCoverageData(const(char)* fname, uint line, uint* data, uint cnt, float* return Package.GetLanguageService().GetCoverageData(filename, line, data, cnt, covPercent); } +extern(Windows) +uint GetTooltip(BSTR fname, uint line, uint col) +{ + if (!Package.s_instance) + return false; // not yet loaded as a package + string filename = to!string(fname); + return Package.GetLanguageService().RequestTooltip(filename, line, col); +} + +extern(Windows) +BOOL GetTooltipResult(uint request, BSTR* btip, BSTR* bfmt) +{ + if (!Package.s_instance) + return false; // not yet loaded as a package + + wstring tip, fmt; + bool rc = Package.GetLanguageService().GetTooltipResult(request, tip, fmt); + *btip = allocwBSTR(tip); + *bfmt = allocwBSTR(fmt); + return rc; +} diff --git a/visuald/dpackage.d b/visuald/dpackage.d index 308c03ad..bc0125a8 100644 --- a/visuald/dpackage.d +++ b/visuald/dpackage.d @@ -1573,7 +1573,7 @@ class GlobalOptions int vsVersion; bool isVS2017OrLater() { return vsVersion >= 15; } bool usesUpdateSemanticModule() { return parseSource || expandFromSemantics || showTypeInTooltip || semanticGotoDef; } - + bool usesQuickInfoTooltips() { return isVS2017OrLater() && !useDParser; } this() { diff --git a/visuald/viewfilter.d b/visuald/viewfilter.d index febf72ca..f558005d 100644 --- a/visuald/viewfilter.d +++ b/visuald/viewfilter.d @@ -1823,7 +1823,7 @@ version(none) // quick info tooltips not good enough yet } *pbstrText = allocBSTR(msg); } - if(Package.GetGlobalOptions().showTypeInTooltip) + if(Package.GetGlobalOptions().showTypeInTooltip && !Package.GetGlobalOptions().usesQuickInfoTooltips()) { if(mPendingSpan == span && mTipRequest == mPendingRequest) { diff --git a/visuald/visuald.def b/visuald/visuald.def index 630b4f5b..d6f017e2 100644 --- a/visuald/visuald.def +++ b/visuald/visuald.def @@ -23,3 +23,5 @@ EXPORTS WritePackageDefW = WritePackageDefW PRIVATE GetCoverageData = GetCoverageData PRIVATE GenerateGeneralXMLW = GenerateGeneralXMLW PRIVATE + GetTooltip = GetTooltip PRIVATE + GetTooltipResult = GetTooltipResult PRIVATE From b3333169b8b7d80981bd8e69da1238765b5a6f28 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 15 Sep 2019 09:36:12 +0200 Subject: [PATCH 39/73] avoid deprecation warnings with dmd 2.088 --- c2d/dlist.d | 22 ++++++++++++++++------ stdext/container.d | 2 +- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/c2d/dlist.d b/c2d/dlist.d index 81ba6ab9..75c82bc0 100644 --- a/c2d/dlist.d +++ b/c2d/dlist.d @@ -268,11 +268,21 @@ else } } - ref T opStar() + ref T opUnary(string op)() if(op == "*") { return _pos.data; } + void opUnary(string op)() if(op == "++") + { + advance(); + } + + void opUnary(string op)() if(op == "--") + { + retreat(); + } + ref T opIndex(int idx) { DListIterator!(T) it = this; @@ -280,14 +290,14 @@ else return *it; } - DListIterator!(T) opAdd(int cnt) + DListIterator!(T) opBinary(string op)(int cnt) if(op == "+") { DListIterator!(T) it = this; it += cnt; return it; } - DListIterator!(T) opSub(int cnt) + DListIterator!(T) opBinary(string op)(int cnt) if(op == "-") { DListIterator!(T) it = this; it += -cnt; @@ -314,7 +324,7 @@ else return _pos is _list.root._next; } - void opAddAssign(int cnt) + void opOpAssign(string op)(int cnt) if(op == "+") { while(cnt > 0) { @@ -327,9 +337,9 @@ else cnt++; } } - void opSubAssign(int cnt) + void opOpAssign(string op)(int cnt) if(op == "-") { - opAddAssign(-cnt); + opOpAssign!"+"(-cnt); } void insertAfter(T data) diff --git a/stdext/container.d b/stdext/container.d index e95c766f..42619331 100644 --- a/stdext/container.d +++ b/stdext/container.d @@ -39,7 +39,7 @@ struct Queue(T) return data[idx]; } - ref Queue!T opCatAssign(ref T t) + ref Queue!T opOpAssign(string op)(ref T t) if (op == "~") { append(t); return this; From 84ec5e980a4ec393ec1b3b54f1556a10083b5f52 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 21 Sep 2019 14:52:10 +0200 Subject: [PATCH 40/73] adapt conversion to Win SDK 10.0.18362.0 --- c2d/idl2d.d | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/c2d/idl2d.d b/c2d/idl2d.d index 28f23f18..572362b7 100644 --- a/c2d/idl2d.d +++ b/c2d/idl2d.d @@ -145,6 +145,8 @@ class idl2d "enclaveapi.h", // Win SDK 10.0.14393.0 "dpa_dsa.h", + // Win SDK 10.0.18362.0 + "fileapifromapp.h", ]) win_idl_files ~= f ~ "*"; // make it optional @@ -1292,6 +1294,8 @@ version(all) replaceTokenSequence(tokens, "MEM_EXTENDED_PARAMETER_TYPE, *PMEM_EXTENDED_PARAMETER_TYPE", "*PMEM_EXTENDED_PARAMETER_TYPE", true); // win 10.0.17763.0: typedef enum MEM_SECTION_EXTENDED_PARAMETER_TYPE {} MEM_SECTION_EXTENDED_PARAMETER_TYPE, ... replaceTokenSequence(tokens, "MEM_SECTION_EXTENDED_PARAMETER_TYPE, *PMEM_SECTION_EXTENDED_PARAMETER_TYPE", "*PMEM_SECTION_EXTENDED_PARAMETER_TYPE", true); + // win 10.0.18362.0: typedef struct DECLSPEC_ALIGN(16) DECLSPEC_NOINITALL _CONTEXT ... + replaceTokenSequence(tokens, "DECLSPEC_NOINITALL", "", true); } if(currentModule == "commctrl") @@ -1360,6 +1364,10 @@ version(all) // imports inside extern(C) {} replaceTokenSequence(tokens, "extern \"C\" { $_data }", "$_data", true); } + if(currentModule == "fileapifromapp") + { + replaceTokenSequence(tokens, "WINSTORAGEAPI", "", true); + } if(currentModule == "propidlbase") { replaceTokenSequence(tokens, "_VARIANT_BOOL bool;", "/*_VARIANT_BOOL bool;*/", true); From 15dc1ab6a78f0fa4ecfb1b76fca752c1507d96ec Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 21 Sep 2019 15:13:27 +0200 Subject: [PATCH 41/73] appveyor: remove VS2015 build --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 77779a32..a6bdb233 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,9 +18,9 @@ environment: - os: Visual Studio 2017 VS: 15 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - - os: Visual Studio 2015 - VS: 14 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 +# - os: Visual Studio 2015 +# VS: 14 +# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 # - os: Visual Studio 2013 # VS: 12 # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 From c8c9cf7dad556e4647fb3742716ec97f77151891 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 21 Sep 2019 15:14:11 +0200 Subject: [PATCH 42/73] installer: add build tools sections --- nsis/visuald.nsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nsis/visuald.nsi b/nsis/visuald.nsi index 43768476..ab9c958e 100644 --- a/nsis/visuald.nsi +++ b/nsis/visuald.nsi @@ -913,6 +913,8 @@ SectionEnd LangString DESC_SecVS2015 ${LANG_ENGLISH} "Register for usage in Visual Studio 2015." 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_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." !ifdef EXPRESS LangString DESC_SecVCExpress2008 ${LANG_ENGLISH} "Register for usage in Visual C++ Express 2008 (experimental and unusable)." LangString DESC_SecVCExpress2010 ${LANG_ENGLISH} "Register for usage in Visual C++ Express 2010 (experimental and unusable)." @@ -949,6 +951,8 @@ SectionEnd !insertmacro MUI_DESCRIPTION_TEXT ${SecVS2015} $(DESC_SecVS2015) !insertmacro MUI_DESCRIPTION_TEXT ${SecVS2017} $(DESC_SecVS2017) !insertmacro MUI_DESCRIPTION_TEXT ${SecVS2019} $(DESC_SecVS2019) + !insertmacro MUI_DESCRIPTION_TEXT ${SecVS2017BT} $(DESC_SecVS2017BT) + !insertmacro MUI_DESCRIPTION_TEXT ${SecVS2019BT} $(DESC_SecVS2019BT) !ifdef EXPRESS !insertmacro MUI_DESCRIPTION_TEXT ${SecVCExpress2008} $(DESC_SecVCExpress2008) !insertmacro MUI_DESCRIPTION_TEXT ${SecVCExpress2008} $(DESC_SecVCExpress2010) From 00e57d4da4fb21e87da9b9d922280df15491abd5 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 22 Sep 2019 16:07:39 +0200 Subject: [PATCH 43/73] fix typo --- vdextensions/quickinfo.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vdextensions/quickinfo.cs b/vdextensions/quickinfo.cs index 3407dfd0..7822be83 100644 --- a/vdextensions/quickinfo.cs +++ b/vdextensions/quickinfo.cs @@ -62,14 +62,14 @@ public void enableLink() } } - internal sealed class VsiualDQuickInfoSource : IAsyncQuickInfoSource + internal sealed class VisualDQuickInfoSource : IAsyncQuickInfoSource { private ITextBuffer _textBuffer; private string _filename; - VsiualDQuickInfoSourceProvider _provider; + VisualDQuickInfoSourceProvider _provider; - public VsiualDQuickInfoSource(VsiualDQuickInfoSourceProvider provider, ITextBuffer textBuffer) + public VisualDQuickInfoSource(VisualDQuickInfoSourceProvider provider, ITextBuffer textBuffer) { _provider = provider; _textBuffer = textBuffer; @@ -251,12 +251,12 @@ public void Dispose() } [Export(typeof(IAsyncQuickInfoSourceProvider))] - [Name("Vsiual D Quick Info Provider")] + [Name("Visual D Quick Info Provider")] [ContentType("d")] [Order] - internal sealed class VsiualDQuickInfoSourceProvider : IAsyncQuickInfoSourceProvider + internal sealed class VisualDQuickInfoSourceProvider : IAsyncQuickInfoSourceProvider { - // these imports don't work in VsiualDQuickInfoSource, maybe because created in another thread? + // these imports don't work in VisualDQuickInfoSource, maybe because created in another thread? [Import] public IClassificationFormatMapService formatMap = null; [Import] @@ -269,7 +269,7 @@ public IAsyncQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer) // This ensures only one instance per textbuffer is created return textBuffer.Properties.GetOrCreateSingletonProperty(() - => new VsiualDQuickInfoSource(this, textBuffer)); + => new VisualDQuickInfoSource(this, textBuffer)); } } } From de3067557904b36a66fda8d8995125eb5f17650c Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 20 Sep 2019 14:08:07 +0200 Subject: [PATCH 44/73] allow file wildcards for dependency exclusions --- visuald/build.d | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/visuald/build.d b/visuald/build.d index cc2f3c30..97674779 100644 --- a/visuald/build.d +++ b/visuald/build.d @@ -1426,9 +1426,15 @@ bool getFilesFromTrackerFile(string lnkdeppath, ref string[] files) bool isExcluded(string file) { foreach(ex; exclpaths) + { if (file.length >= ex.length && icmp(file[0..ex.length], ex) == 0) + { if (ex[$-1] == '\\' || file.length == ex.length || file[ex.length] == '\\') return true; + } + else if (ex.indexOf('\\') < 0 && globMatch(baseName(file).toLower, ex.toLower)) + return true; + } return false; } From 27ddbc383a038255837e28e8cadcb4deb1694ba7 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 21 Sep 2019 14:32:49 +0200 Subject: [PATCH 45/73] tweak build --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/dmdserver.visualdproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index 21fc7469..07db7781 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit 21fc7469eae4a31021e89c647fb9dcd373c873b9 +Subproject commit 07db7781f3f1b583a50aaad0be5f5de5bb64dcce diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index ef55a676..8cffddf2 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -720,7 +720,7 @@ $(IntDir)\$(SafeProjectName).map 1 2 - 1 + 0 -L/STACK:8388608 -gf @@ -1151,7 +1151,7 @@ 0 0 0 - 1 + 0 $(CC) -c -nologo -Idmd\src\dmd -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\dmd\vcbuild -DTARGET_WINDOS=1 1 0 From cf04a0e333cd28d01a0027e537b6b989d42185e7 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 22 Sep 2019 20:54:08 +0200 Subject: [PATCH 46/73] add (m|c|re)alloc_noscan, append \0\0 to source --- vdc/dmdserver/dmdrmem.d | 17 +++++++++++++++++ vdc/dmdserver/semvisitor.d | 1 + 2 files changed, 18 insertions(+) diff --git a/vdc/dmdserver/dmdrmem.d b/vdc/dmdserver/dmdrmem.d index 53a24d8b..feaaa199 100644 --- a/vdc/dmdserver/dmdrmem.d +++ b/vdc/dmdserver/dmdrmem.d @@ -23,16 +23,33 @@ extern (C++) struct Mem throw *pcancelError; return GC.malloc(n); } + static void* xmalloc_noscan(size_t n) nothrow pure + { + if (*pcancel) + throw *pcancelError; + return GC.malloc(n, GC.BlkAttr.NO_SCAN); + } static void* xcalloc(size_t size, size_t n) nothrow pure { return GC.calloc(size * n); } + static void* xcalloc_noscan(size_t size, size_t n) nothrow pure + { + return GC.calloc(size * n, GC.BlkAttr.NO_SCAN); + } + static void* xrealloc(void* p, size_t size) nothrow pure { return GC.realloc(p, size); } + + static void* xrealloc_noscan(void* p, size_t size) nothrow pure + { + return GC.realloc(p, size, GC.BlkAttr.NO_SCAN); + } + static void error() nothrow { __gshared static oom = new Error("out of memory"); diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index df5ac8a3..3af24230 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -1543,6 +1543,7 @@ Module createModuleFromText(string filename, string text) { import std.path; + text ~= "\0\0"; // parser needs 2 trailing zeroes string name = stripExtension(baseName(filename)); auto id = Identifier.idPool(name); auto mod = new Module(filename, id, true, false); From 44d34a08571b5874a63862ab722e1f974a9681d5 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Tue, 24 Sep 2019 08:23:42 +0200 Subject: [PATCH 47/73] fix dmd update --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/dmdinit.d | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index 07db7781..b7548733 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit 07db7781f3f1b583a50aaad0be5f5de5bb64dcce +Subproject commit b75487330bcda5fc0009b41e7e4bd5f150377161 diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d index ff693366..56bbeb67 100644 --- a/vdc/dmdserver/dmdinit.d +++ b/vdc/dmdserver/dmdinit.d @@ -48,7 +48,7 @@ enum string[2][] dmdStatics = ["_D3dmd7typesem12typeSemanticRCQBc5mtype4TypeSQBr7globals3LocPSQCi6dscope5ScopeZ11visitAArrayMFCQDpQCn10TypeAArrayZ5fhashCQEp4func15FuncDeclaration", "FuncDeclaration"], ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDdQBc8DotIdExpiZ11visitAArrayMFCQEkQDq10TypeAArrayZ8fd_aaLenCQFn4func15FuncDeclaration", "FuncDeclaration"], ["_D3dmd7typesem6dotExpFCQv5mtype4TypePSQBk6dscope5ScopeCQCb10expression10ExpressionCQDdQBc8DotIdExpiZ8noMemberMFQDlQDaQClCQEp10identifier10IdentifieriZ4nesti", "int"], - ["_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBufferkPkAxaZ4nesti", "int"], // x86 + ["_D3dmd6dmacro10MacroTable6expandMFKSQBi4root9outbuffer9OutBufferkKkAxaZ4nesti", "int"], // x86 ["_D3dmd7dmodule6Module19runDeferredSemanticRZ6nestedi", "int"], ["_D3dmd10dsymbolsem22DsymbolSemanticVisitor5visitMRCQBx9dtemplate13TemplateMixinZ4nesti", "int"], ["_D3dmd9dtemplate16TemplateInstance16tryExpandMembersMFPSQCc6dscope5ScopeZ4nesti", "int"], @@ -69,8 +69,8 @@ string cmangled(string s) { if (s == "_D3dmd10identifier10Identifier10generateIdRNbPxaZ1ik") return "_D3dmd10identifier10Identifier10generateIdRNbPxaZ1im"; // size_t - if (s == "_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBufferkPkAxaZ4nesti") - return "_D3dmd6dmacro5Macro6expandMFPSQBc4root9outbuffer9OutBuffermPmAxaZ4nesti"; + if (s == "_D3dmd6dmacro10MacroTable6expandMFKSQBi4root9outbuffer9OutBufferkKkAxaZ4nesti") + return "_D3dmd6dmacro10MacroTable6expandMFKSQBi4root9outbuffer9OutBuffermKmAxaZ4nesti"; } return s; } From 19c136e2799fa733e4104bde3509af362a62467b Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 30 Sep 2019 09:19:47 +0200 Subject: [PATCH 48/73] more tests, fix static type-dot-ident expressions --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/semanalysis.d | 167 ++++++++++++++++++++++++++++++++---- vdc/dmdserver/semvisitor.d | 18 +++- 3 files changed, 166 insertions(+), 21 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index b7548733..db24474c 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit b75487330bcda5fc0009b41e7e4bd5f150377161 +Subproject commit db24474c844bd02839a9831893226463bdec945c diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index 50f691a6..4b4cb3b5 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -454,37 +454,83 @@ unittest struct S { int field1 = 3; + static long stat1 = 7; // Line 5 int fun(int par) { return field1 + par; } } void foo() { - S anS; - int x = anS.fun(1); // Line 10 + S anS; // Line 10 + int x = anS.fun(1); } int fun(S s) { - auto p = new S(1); - return s.field1; // Line 15 + auto p = new S(1); // Line 15 + auto seven = S.stat1; + return s.field1; } }; m = checkErrors(source, ""); checkTip(m, 2, 10, "(struct) source.S"); checkTip(m, 4, 8, "(field) int source.S.field1"); - checkTip(m, 5, 8, "int source.S.fun(int par)"); - checkTip(m, 5, 16, "(parameter) int par"); - checkTip(m, 5, 30, "(field) int source.S.field1"); - checkTip(m, 5, 39, "(parameter) int par"); + checkTip(m, 6, 8, "int source.S.fun(int par)"); + checkTip(m, 6, 16, "(parameter) int par"); + checkTip(m, 6, 30, "(field) int source.S.field1"); + checkTip(m, 6, 39, "(parameter) int par"); + + checkTip(m, 10, 4, "(struct) source.S"); + checkTip(m, 10, 6, "(local variable) source.S anS"); + checkTip(m, 11, 12, "(local variable) source.S anS"); + checkTip(m, 11, 16, "int source.S.fun(int par)"); + + checkTip(m, 13, 11, "(struct) source.S"); + checkTip(m, 16, 19, "(thread local variable) long source.S.stat1"); + checkTip(m, 16, 17, "(struct) source.S"); + + checkDefinition(m, 11, 16, "source.d", 6, 8); // fun + checkDefinition(m, 15, 17, "source.d", 2, 10); // S + + source = + q{ // Line 1 + class C + { + int field1 = 3; + static long stat1 = 7; // Line 5 + int fun(int par) { return field1 + par; } + } + void foo() + { + C aC = new C; // Line 10 + int x = aC.fun(1); + } + int fun(C c) + { + auto p = new C(); // Line 15 + auto seven = C.stat1; + return c.field1; + } + }; + m = checkErrors(source, ""); + + checkTip(m, 2, 9, "(class) source.C"); + checkTip(m, 4, 8, "(field) int source.C.field1"); + checkTip(m, 6, 8, "int source.C.fun(int par)"); + checkTip(m, 6, 16, "(parameter) int par"); + checkTip(m, 6, 30, "(field) int source.C.field1"); + checkTip(m, 6, 39, "(parameter) int par"); - checkTip(m, 9, 4, "(struct) source.S"); - checkTip(m, 9, 6, "(local variable) source.S anS"); - checkTip(m, 10, 12, "(local variable) source.S anS"); - checkTip(m, 10, 16, "int source.S.fun(int par)"); + checkTip(m, 10, 4, "(class) source.C"); + checkTip(m, 10, 15, "(class) source.C"); + checkTip(m, 10, 6, "(local variable) source.C aC"); + checkTip(m, 11, 12, "(local variable) source.C aC"); + checkTip(m, 11, 16, "int source.C.fun(int par)"); - checkTip(m, 12, 11, "(struct) source.S"); + checkTip(m, 13, 11, "(class) source.C"); + checkTip(m, 16, 19, "(thread local variable) long source.C.stat1"); + checkTip(m, 16, 17, "(class) source.C"); - checkDefinition(m, 10, 16, "source.d", 5, 8); // fun - checkDefinition(m, 14, 17, "source.d", 2, 10); // S + checkDefinition(m, 11, 16, "source.d", 6, 8); // fun + checkDefinition(m, 15, 17, "source.d", 2, 9); // C source = q{ // Line 1 @@ -547,7 +593,7 @@ unittest "14,2,14,3:identifier or `new` expected following `.`, not `}`\n" ~ "14,2,14,3:semicolon expected, not `}`\n" ~ "12,14,12,15:no property `f` for type `S`\n"); - dumpAST(m); + //dumpAST(m); checkExpansions(m, 12, 16, "f", [ "field1", "field2", "fun" ]); checkExpansions(m, 13, 16, "", [ "field1", "field2", "fun", "more" ]); checkExpansions(m, 13, 13, "an", [ "anS" ]); @@ -611,9 +657,96 @@ unittest } }; m = checkErrors(source, ""); - dumpAST(m); + //dumpAST(m); checkTip(m, 6, 12, "(local variable) int i"); checkTip(m, 7, 5, "(local variable) int sum"); checkTip(m, 7, 12, "(local variable) int i"); + + source = q{ // Line 1 + enum TOK : ubyte + { + reserved, + leftParentheses, // Line 5 + rightParentheses, + } + void foo(TOK op) + { + if (op == TOK.leftParentheses) {} // Line 10 + } + class Base + { + this(TOK op, size_t sz) {} + } // Line 15 + class LeftBase : Base + { + this() + { + super(TOK.leftParentheses, LeftBase.sizeof);// Line 20 + } + } + }; + m = checkErrors(source, ""); + dumpAST(m); + + checkTip(m, 10, 8, "(parameter) source.TOK op"); + checkTip(m, 10, 14, "(enum) source.TOK"); + checkTip(m, 10, 18, "(enum value) source.TOK.leftParentheses = 1"); + checkTip(m, 20, 11, "(enum) source.TOK"); + checkTip(m, 20, 15, "(enum value) source.TOK.leftParentheses = 1"); + checkTip(m, 20, 32, "(class) source.LeftBase"); + //checkTip(m, 20, 41, "(constant) source.LeftBase.sizeof = 8"); +} + +unittest +{ + import core.memory; + import std.path; + import std.file; + + dmdInit(); + string srcdir = "dmd/src"; + + Options opts; + opts.predefineDefaultVersions = true; + opts.x64 = true; + opts.msvcrt = true; + opts.importDirs = guessImportPaths() ~ srcdir; + opts.stringImportDirs ~= srcdir ~ "/../res"; + opts.versionIds ~= "MARS"; + //opts.versionIds ~= "NoBackend"; + + auto filename = std.path.buildPath(srcdir, "dmd/expressionsem.d"); + + static void assert_equal(S, T)(S s, T t) + { + if (s == t) + return; + assert(false); + } + + Module checkErrors(string src, string expected_err) + { + try + { + initErrorFile(filename); + Module parsedModule = createModuleFromText(filename, src); + assert(parsedModule); + Module m = analyzeModule(parsedModule, opts); + auto err = cast(string) gErrorMessages; + assert_equal(err, expected_err); + return m; + } + catch(Throwable t) + { + throw t; + } + } + string source = cast(string)std.file.read(filename); + Module m = checkErrors(source, ""); +} + +// https://issues.dlang.org/show_bug.cgi?id=20253 +void dummy() +{ } diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 3af24230..4d801980 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -479,7 +479,7 @@ extern(C++) class FindASTVisitor : ASTVisitor bool foundNode(RootObject obj) { - if (!obj) + if (obj) { found = obj; stop = true; @@ -576,6 +576,11 @@ extern(C++) class FindASTVisitor : ASTVisitor visit(cast(TypeQualified)t); } + override void visit(Expression expr) + { + super.visit(expr); + } + override void visit(CastExp expr) { visitTypeIdentifier(expr.parsedTo, expr.to); @@ -682,9 +687,16 @@ extern(C++) class FindASTVisitor : ASTVisitor override void visit(IdentifierExp expr) { - if (!found && expr.ident && expr.type) + if (!found && expr.ident) + { if (matchIdentifier(expr.loc, expr.ident)) - foundNode(expr.type); + { + if (expr.type) + foundNode(expr.type); + else if (expr.original) + foundNode(expr.original.type); + } + } visit(cast(Expression)expr); } From bd1c61974616a7a3c40dbf871bb4fbfdabaadf05 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Thu, 3 Oct 2019 14:54:52 +0200 Subject: [PATCH 49/73] use version LanguageServer in addition to NoBackend use common field "original" for lowered statement --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/dmdserver.visualdproj | 12 ++++----- vdc/dmdserver/semanalysis.d | 2 +- vdc/dmdserver/semvisitor.d | 39 +++++++++-------------------- 4 files changed, 20 insertions(+), 35 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index db24474c..d2babe31 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit db24474c844bd02839a9831893226463bdec945c +Subproject commit d2babe31f05803aa4aef506187f31735f02b3f62 diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index 8cffddf2..e7883971 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -691,7 +691,7 @@ 0 0 - MARS NoBackend GC + MARS NoBackend GC LanguageServer 0 1 0 @@ -1121,7 +1121,7 @@ 0 0 0 - 0 + 1 0 0 0 @@ -1175,7 +1175,7 @@ 0 0 - MARS NoBackend GC + MARS NoBackend GC LanguageServer 0 0 0 @@ -1205,7 +1205,7 @@ 1 2 0 - -L/STACK:8388608 -gf + -L/STACK:8388608 -gf -check=assert *.obj;*.cmd;*.build;*.json;*.dep @@ -1417,7 +1417,7 @@ 0 0 - MARS NoBackend GC TEST + MARS NoBackend GC TEST LanguageServer 0 3 0 @@ -1447,7 +1447,7 @@ 1 2 0 - -L/STACK:8388608 + -L/STACK:8388608 -verrors=0 *.obj;*.cmd;*.build;*.json;*.dep diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index 4b4cb3b5..691aa6aa 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -687,7 +687,7 @@ unittest } }; m = checkErrors(source, ""); - dumpAST(m); + //dumpAST(m); checkTip(m, 10, 8, "(parameter) source.TOK op"); checkTip(m, 10, 14, "(enum) source.TOK"); diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 4d801980..ea8d4b80 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -273,20 +273,15 @@ extern(C++) class ASTVisitor : StoppableVisitor } // statements - override void visit(Statement) {} - - override void visit(ErrorStatement stmt) + override void visit(Statement stmt) { - visitStatement(stmt.errStmt); - if (!stop) - visit(cast(Statement)stmt); + visitStatement(stmt.original); } override void visit(ExpStatement stmt) { visitExpression(stmt.exp); - if (!stop) - visit(cast(Statement)stmt); + visit(cast(Statement)stmt); } override void visit(ConditionalStatement stmt) @@ -305,6 +300,7 @@ extern(C++) class ASTVisitor : StoppableVisitor else visitStatement(stmt.elsebody); } + visit(cast(Statement)stmt); } override void visit(CompileStatement stmt) @@ -313,33 +309,26 @@ extern(C++) class ASTVisitor : StoppableVisitor foreach(e; *stmt.exps) if (!stop) e.accept(this); - if (!stop) - visit(cast(Statement)stmt); + visit(cast(Statement)stmt); } override void visit(WhileStatement stmt) { visitExpression(stmt.condition); - if (!stop) - visit(cast(Statement)stmt); + visit(cast(Statement)stmt); } override void visit(DoStatement stmt) { visitExpression(stmt.condition); - if (!stop) - visit(cast(Statement)stmt); + visit(cast(Statement)stmt); } override void visit(ForStatement stmt) { visitExpression(stmt.condition); visitExpression(stmt.increment); - if (!stop) - visit(cast(Statement)stmt); - - if (!stop && stmt.loweredFrom) - stmt.loweredFrom.accept(this); + visit(cast(Statement)stmt); } override void visit(ForeachStatement stmt) @@ -349,8 +338,7 @@ extern(C++) class ASTVisitor : StoppableVisitor if (!stop) p.accept(this); visitExpression(stmt.aggr); - if (!stop) - visit(cast(Statement)stmt); + visit(cast(Statement)stmt); } override void visit(ForeachRangeStatement stmt) @@ -359,8 +347,7 @@ extern(C++) class ASTVisitor : StoppableVisitor stmt.prm.accept(this); visitExpression(stmt.lwr); visitExpression(stmt.upr); - if (!stop) - visit(cast(Statement)stmt); + visit(cast(Statement)stmt); } override void visit(IfStatement stmt) @@ -368,8 +355,7 @@ extern(C++) class ASTVisitor : StoppableVisitor if (!stop && stmt.prm) stmt.prm.accept(this); visitExpression(stmt.condition); - if (!stop) - visit(cast(Statement)stmt); + visit(cast(Statement)stmt); } override void visit(PragmaStatement stmt) @@ -378,8 +364,7 @@ extern(C++) class ASTVisitor : StoppableVisitor foreach(a; *stmt.args) if (!stop) a.accept(this); - if (!stop) - visit(cast(Statement)stmt); + visit(cast(Statement)stmt); } override void visit(StaticAssertStatement stmt) From 0229ef3e694019cf32ac2eee8a442ef746d605e5 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 4 Oct 2019 09:32:38 +0200 Subject: [PATCH 50/73] add mago options hideReferencePointers and removeLeadingHexZeroes --- visuald/propertypage.d | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/visuald/propertypage.d b/visuald/propertypage.d index 34cd87da..39401ac1 100644 --- a/visuald/propertypage.d +++ b/visuald/propertypage.d @@ -3029,6 +3029,8 @@ struct MagoOptions bool showVTable; bool flatClassFields; bool expandableStrings; + bool hideReferencePointers; + bool removeLeadingHexZeroes; uint maxArrayElements; void saveToRegistry() @@ -3039,6 +3041,8 @@ struct MagoOptions keyMago.Set("showVTable", showVTable); keyMago.Set("flatClassFields", flatClassFields); keyMago.Set("expandableStrings", expandableStrings); + keyMago.Set("hideReferencePointers", hideReferencePointers); + keyMago.Set("removeLeadingHexZeroes", removeLeadingHexZeroes); keyMago.Set("maxArrayElements", maxArrayElements); } @@ -3051,6 +3055,8 @@ struct MagoOptions showVTable = (keyMago.GetDWORD("showVTable", 1) != 0); flatClassFields = (keyMago.GetDWORD("flatClassFields", 0) != 0); expandableStrings = (keyMago.GetDWORD("expandableStrings", 0) != 0); + hideReferencePointers = (keyMago.GetDWORD("hideReferencePointers", 1) != 0); + removeLeadingHexZeroes = (keyMago.GetDWORD("removeLeadingHexZeroes", 0) != 0); maxArrayElements = keyMago.GetDWORD("maxArrayElements", 1000); } } @@ -3070,6 +3076,8 @@ class MagoPropertyPage : ResizablePropertyPage AddControl("", mShowVTable = new CheckBox(mCanvas, "Show virtual function table as field of classes")); AddControl("", mFlatClassFields = new CheckBox(mCanvas, "Show base class fields as direct fields")); AddControl("", mExpandableStrings = new CheckBox(mCanvas, "Expand strings to show array of characters")); + AddControl("", mHideRefPointers = new CheckBox(mCanvas, "Hide pointers for class references and slices")); + AddControl("", mRemoveHexZeroes = new CheckBox(mCanvas, "Remove leading zeroes from hex values")); auto saveWidth = kLabelWidth; kLabelWidth = kPageWidth * 4 / 5; AddControl("Limit array elements shown in expansions to", mMaxArrayElements = new Text(mCanvas)); @@ -3120,6 +3128,8 @@ class MagoPropertyPage : ResizablePropertyPage mShowVTable.setChecked(mOptions.showVTable); mFlatClassFields.setChecked(mOptions.flatClassFields); mExpandableStrings.setChecked(mOptions.expandableStrings); + mHideRefPointers.setChecked(mOptions.hideReferencePointers); + mRemoveHexZeroes.setChecked(mOptions.removeLeadingHexZeroes); mMaxArrayElements.setText(to!string(mOptions.maxArrayElements)); } @@ -3131,6 +3141,8 @@ class MagoPropertyPage : ResizablePropertyPage changes += changeOption(mShowVTable.isChecked(), opts.showVTable, refopts.showVTable); changes += changeOption(mFlatClassFields.isChecked(), opts.flatClassFields, refopts.flatClassFields); changes += changeOption(mExpandableStrings.isChecked(), opts.expandableStrings, refopts.expandableStrings); + changes += changeOption(mHideRefPointers.isChecked(), opts.hideReferencePointers, refopts.hideReferencePointers); + changes += changeOption(mRemoveHexZeroes.isChecked(), opts.removeLeadingHexZeroes, refopts.removeLeadingHexZeroes); import stdext.string; long maxelem; @@ -3145,6 +3157,8 @@ class MagoPropertyPage : ResizablePropertyPage CheckBox mShowVTable; CheckBox mFlatClassFields; CheckBox mExpandableStrings; + CheckBox mHideRefPointers; + CheckBox mRemoveHexZeroes; Text mMaxArrayElements; } From e49a4af650a357f93903ef009d56b263170c5b48 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 4 Oct 2019 15:26:51 +0200 Subject: [PATCH 51/73] build dmdserver on appveyor --- Makefile | 2 +- appveyor.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 82fe8535..5215ef75 100644 --- a/Makefile +++ b/Makefile @@ -169,7 +169,7 @@ install_vs_no_vs2017: install_modules fake_dparser cv2pdb mago dbuild12 dbuild install_vs_only_vs2017: install_modules dparser dparser_test cv2pdb_vs15 mago_vs15 fake_dbuild12 fake_dbuild14 dbuild15 install_only -install_modules: prerequisites visuald_vs vdserver vdextension vdext15 visualdwizard dcxxfilt +install_modules: prerequisites visuald_vs vdserver dmdserver vdextension vdext15 visualdwizard dcxxfilt install_only: if not exist ..\downloads\nul md ..\downloads diff --git a/appveyor.yml b/appveyor.yml index a6bdb233..daf09451 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -104,14 +104,14 @@ before_build: build_script: - cd c:\projects - cd visuald + # Fetch submodules + - git submodule update --init --recursive # ignore failure once, in case it needs reloading the sdk project - nmake prerequisites || nmake prerequisites # build Visual D - nmake visuald_vs # build and run Visual D unittests - nmake visuald_test - # Fetch submodules - - git submodule update --init --recursive - cd .. # Clone mago/cv2pdb (need to be two levels up) - cd .. From 45c6649339efdabae558357449dd185cf9d971b3 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 4 Oct 2019 15:53:20 +0200 Subject: [PATCH 52/73] appveyor.yml: upgrade dmd and visuald --- appveyor.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index daf09451..6cd549ef 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -27,9 +27,9 @@ environment: # cache relative to C:\projects\visuald cache: - - C:\projects\cache\dmd2083_0.7z + - C:\projects\cache\dmd2088_0.7z - C:\projects\cache\cd851.zip - - C:\projects\cache\VisualD-v0.47.0.exe + - C:\projects\cache\VisualD-v0.50.1.exe - C:\projects\cache\binutils-2.25.tar.gz #matrix: @@ -50,10 +50,10 @@ install: # Download & extract D compiler - ps: | If ($Env:D_COMPILER -eq 'dmd') { - If (-not (Test-Path 'cache\dmd2083_0.7z')) { - Start-FileDownload 'http://downloads.dlang.org/releases/2.x/2.083.0/dmd.2.083.0.windows.7z' -FileName 'cache\dmd2083_0.7z' + If (-not (Test-Path 'cache\dmd2088_0.7z')) { + Start-FileDownload 'http://downloads.dlang.org/releases/2.x/2.088.0/dmd.2.088.0.windows.7z' -FileName 'cache\dmd2088_0.7z' } - 7z x cache\dmd2083_0.7z > $null + 7z x cache\dmd2088_0.7z > $null Set-Item -path env:DMD -value c:\projects\dmd2\windows\bin\dmd.exe c:\projects\dmd2\windows\bin\dmd.exe --version } ElseIf ($Env:D_COMPILER -eq 'dmd-nightly') { @@ -77,10 +77,10 @@ install: copy c:\projects\dm\bin\coffimplib.exe c:\projects\dmd2\windows\bin # Download & install Visual D - ps: | - If (-not (Test-Path 'cache\VisualD-v0.47.0.exe')) { - Start-FileDownload 'https://github.com/dlang/visuald/releases/download/v0.47.0/VisualD-v0.47.0.exe' -FileName 'cache\VisualD-v0.47.0.exe' + If (-not (Test-Path 'cache\VisualD-v0.50.1.exe')) { + Start-FileDownload 'https://github.com/dlang/visuald/releases/download/v0.50.1/VisualD-v0.50.1.exe' -FileName 'cache\VisualD-v0.50.1.exe' } - - cache\VisualD-v0.47.0.exe /S + - cache\VisualD-v0.50.1.exe /S # configure DMD path - reg add "HKLM\SOFTWARE\DMD" /v InstallationFolder /t REG_SZ /d c:\projects /reg:32 /f # disable link dependencies monitoring, fails on AppVeyor server From 0451c35e9fbc337efb2ecff25fc41102c6137d74 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 4 Oct 2019 16:20:10 +0200 Subject: [PATCH 53/73] appveyor.yml: run dmdserver test --- Makefile | 3 +++ appveyor.yml | 2 +- vdc/dmdserver/dmdserver.visualdproj | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5215ef75..b555abb5 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,9 @@ vdserver: dmdserver: devenv /Project "dmdserver" /Build "$(CONFIG)|x64" visuald_vs10.sln +dmdserver_test: + devenv /Project "dmdserver" /Build "TestDebug|x64" visuald_vs10.sln + dparser: cd vdc\abothe && $(MSBUILD15) vdserver.sln /p:Configuration=Release;Platform="Any CPU" /p:TargetFrameworkVersion=4.5.2 /p:DefineConstants=NET40 /t:Rebuild editbin /STACK:0x800000 bin\Release\DParserCOMServer\DParserCOMServer.exe diff --git a/appveyor.yml b/appveyor.yml index 6cd549ef..5e868b5f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -111,7 +111,7 @@ build_script: # build Visual D - nmake visuald_vs # build and run Visual D unittests - - nmake visuald_test + - nmake visuald_test dmdserver_test - cd .. # Clone mago/cv2pdb (need to be two levels up) - cd .. diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index e7883971..b5fbe766 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -1084,7 +1084,7 @@ 1 2 0 - -L/STACK:8388608 + -L/STACK:8388608 -check=assert *.obj;*.cmd;*.build;*.json;*.dep From e60e8d119b7032ad5566ade8c1855c67aba80275 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 4 Oct 2019 17:49:01 +0200 Subject: [PATCH 54/73] fix TestDebug dependencies --- visuald_vs10.sln | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/visuald_vs10.sln b/visuald_vs10.sln index ca8c0bbf..2a1d6f59 100644 --- a/visuald_vs10.sln +++ b/visuald_vs10.sln @@ -432,8 +432,8 @@ Global {8760F45A-69D9-4B68-BE63-0E055B51D447}.Test|x64.Build.0 = Debug GDC|x64 {8760F45A-69D9-4B68-BE63-0E055B51D447}.TestDebug|Win32.ActiveCfg = TestDebug|Win32 {8760F45A-69D9-4B68-BE63-0E055B51D447}.TestDebug|Win32.Build.0 = TestDebug|Win32 - {8760F45A-69D9-4B68-BE63-0E055B51D447}.TestDebug|x64.ActiveCfg = Debug|x64 - {8760F45A-69D9-4B68-BE63-0E055B51D447}.TestDebug|x64.Build.0 = Debug|x64 + {8760F45A-69D9-4B68-BE63-0E055B51D447}.TestDebug|x64.ActiveCfg = TestDebug|x64 + {8760F45A-69D9-4B68-BE63-0E055B51D447}.TestDebug|x64.Build.0 = TestDebug|x64 {FE3A959D-6CFA-43BF-8637-62125B571770}.Debug COFF32|Win32.ActiveCfg = Debug COFF32|Win32 {FE3A959D-6CFA-43BF-8637-62125B571770}.Debug COFF32|Win32.Build.0 = Debug COFF32|Win32 {FE3A959D-6CFA-43BF-8637-62125B571770}.Debug COFF32|x64.ActiveCfg = Debug|x64 From 98454e3cbfa818e306d49edb41050126786ac267 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 5 Oct 2019 13:11:26 +0200 Subject: [PATCH 55/73] dparser: now creates server process per Visual Studio Instance added option to not show error squiggles and markers syntax highlight quoted code in tool tips interpret as bold in tooltips compiler versions detection: remove some command line options from that might cause failure --- vdc/abothe/Parser | 2 +- vdc/abothe/comserver/COM/ExeCOMServer.cs | 2 +- .../CodeSemantics/TooltipGenerator.cs | 12 +- vdc/abothe/comserver/VDServer.cs | 3 +- vdc/dmdserver/dmdserver.visualdproj | 6 +- vdc/dmdserver/semanalysis.d | 147 +++++++++--------- vdc/dmdserver/semvisitor.d | 47 +++--- vdc/ivdserver.d | 1 + vdextensions/quickinfo.cs | 67 ++++++-- visuald/config.d | 26 ++++ visuald/dlangsvc.d | 36 ++++- visuald/dpackage.d | 14 +- visuald/propertypage.d | 4 + 13 files changed, 239 insertions(+), 128 deletions(-) diff --git a/vdc/abothe/Parser b/vdc/abothe/Parser index 0e6499b7..693d75f2 160000 --- a/vdc/abothe/Parser +++ b/vdc/abothe/Parser @@ -1 +1 @@ -Subproject commit 0e6499b7735bfcb7f10227f145cc5fb4df2965c1 +Subproject commit 693d75f2a0b148fc09b947bc2de140dbaa5dd997 diff --git a/vdc/abothe/comserver/COM/ExeCOMServer.cs b/vdc/abothe/comserver/COM/ExeCOMServer.cs index 5162891f..af7f8b51 100644 --- a/vdc/abothe/comserver/COM/ExeCOMServer.cs +++ b/vdc/abothe/comserver/COM/ExeCOMServer.cs @@ -68,7 +68,7 @@ private void PreMessageLoop() // Register the SimpleObject class object int hResult = COMNative.CoRegisterClassObject(ref clsid, new VDServerClassFactory(), - CLSCTX.LOCAL_SERVER, REGCLS.MULTIPLEUSE | REGCLS.SUSPENDED, + CLSCTX.LOCAL_SERVER, REGCLS.SINGLEUSE | REGCLS.SUSPENDED, out _cookie); if (hResult != 0) { diff --git a/vdc/abothe/comserver/CodeSemantics/TooltipGenerator.cs b/vdc/abothe/comserver/CodeSemantics/TooltipGenerator.cs index 57a40fab..77cdb97c 100644 --- a/vdc/abothe/comserver/CodeSemantics/TooltipGenerator.cs +++ b/vdc/abothe/comserver/CodeSemantics/TooltipGenerator.cs @@ -10,15 +10,19 @@ namespace DParserCOMServer.CodeSemantics { public class TooltipGenerator - : AbstractVDServerTask, bool> + : AbstractVDServerTask, Tuple> { public TooltipGenerator(VDServer vdServer, EditorDataProvider editorDataProvider) : base(vdServer, editorDataProvider) { } protected override Tuple Process( - EditorData editorData, bool evaluateUnderneathExpression) + EditorData editorData, Tuple opts) { - // codeOffset+1 because otherwise it does not work on the first character + bool evaluateUnderneathExpression = opts.Item1; + bool quoteCode = opts.Item2; + + // codeOffset+1 because otherwise it does not work on the first character editorData.CaretOffset++; var sr = DResolver.GetScopedCodeObject(editorData); @@ -45,7 +49,7 @@ protected override Tuple Process( if (!isRenamed || at.Definition.Location == sr.Location) dt = at.Base; } - tipText.Append(NodeToolTipContentGen.Instance.GenTooltipSignature(dt)); + tipText.Append(NodeToolTipContentGen.Instance.GenTooltipSignature(dt, false, -1, quoteCode)); if (dt is DSymbol symbol) dn = symbol.Definition; diff --git a/vdc/abothe/comserver/VDServer.cs b/vdc/abothe/comserver/VDServer.cs index b1b632df..7d20375e 100644 --- a/vdc/abothe/comserver/VDServer.cs +++ b/vdc/abothe/comserver/VDServer.cs @@ -132,7 +132,8 @@ public void GetIdentifierTypesResult(out string answer) public void GetTip(string filename, int startLine, int startIndex, int endLine, int endIndex, int flags) { - _tipGenerationTask.Run(filename, new CodeLocation(startIndex + 1, startLine), (flags & 1) != 0); + _tipGenerationTask.Run(filename, new CodeLocation(startIndex + 1, startLine), + Tuple.Create((flags & 1) != 0, (flags & 2) != 0)); } public void GetTipResult(out int startLine, out int startIndex, out int endLine, out int endIndex, out string answer) diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index b5fbe766..a3197895 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -570,7 +570,7 @@ 0 0 - MARS NoBackend GC + MARS NoBackend GC LanguageServer 0 1 0 @@ -1054,7 +1054,7 @@ 0 0 - MARS NoBackend GC + MARS NoBackend GC LanguageServer 0 2 0 @@ -1296,7 +1296,7 @@ 0 0 - MARS NoBackend GC + MARS NoBackend GC LanguageServer 0 0 0 diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index 691aa6aa..1c1f081b 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -374,11 +374,11 @@ unittest dumpGC(); } - checkTip(m, 5, 8, "(local variable) int xyz"); - checkTip(m, 5, 10, "(local variable) int xyz"); + checkTip(m, 5, 8, "(local variable) `int xyz`"); + checkTip(m, 5, 10, "(local variable) `int xyz`"); checkTip(m, 5, 11, ""); - checkTip(m, 6, 8, "void std.stdio.writeln!(int, int, int)(int _param_0, int _param_1, int _param_2) @safe"); - checkTip(m, 7, 11, "(local variable) int xyz"); + checkTip(m, 6, 8, "`void std.stdio.writeln!(int, int, int)(int _param_0, int _param_1, int _param_2) @safe`"); + checkTip(m, 7, 11, "(local variable) `int xyz`"); version(traceGC) { @@ -427,27 +427,27 @@ unittest m = checkErrors(source, ""); - checkTip(m, 2, 24, "(parameter) const(string[]) args"); // function arg - checkTip(m, 3, 6, "(parameter) const(string[]) args"); // in contract - checkTip(m, 3, 34, "(parameter) const(string[]) args"); // in contract - checkTip(m, 5, 24, "(parameter) const(string[]) args"); // static if is typeof expression - checkTip(m, 6, 10, "(parameter) const(string[]) args"); // if expression - checkTip(m, 11, 21, "(parameter) const(string[]) args"); // !in expression - - checkTip(m, 19, 9, "(enum) pkg.source.EE"); // enum EE - checkTip(m, 19, 13, "(enum value) pkg.source.EE.E1 = 3"); // enum E1 - checkTip(m, 19, 21, "(enum value) pkg.source.EE.E2 = 4"); // enum E2 - checkTip(m, 22, 14, "(enum) pkg.source.EE"); // enum EE - checkTip(m, 22, 17, "(enum value) pkg.source.EE.E1 = 3"); // enum E1 - - checkTip(m, 1, 9, "(package) pkg"); - checkTip(m, 1, 13, "(module) pkg.source"); - checkTip(m, 24, 10, "(package) core"); - checkTip(m, 24, 15, "(module) core.cpuid"); - checkTip(m, 24, 23, "(alias) pkg.source.cpu_vendor = string core.cpuid.vendor() pure nothrow @nogc @property @trusted"); - checkTip(m, 24, 36, "(alias) pkg.source.cpu_vendor = string core.cpuid.vendor() pure nothrow @nogc @property @trusted"); - checkTip(m, 24, 44, "(alias) pkg.source.processor = string core.cpuid.processor() pure nothrow @nogc @property @trusted"); - checkTip(m, 28, 11, "string core.cpuid.vendor() pure nothrow @nogc @property @trusted"); + checkTip(m, 2, 24, "(parameter) `const(string[]) args`"); // function arg + checkTip(m, 3, 6, "(parameter) `const(string[]) args`"); // in contract + checkTip(m, 3, 34, "(parameter) `const(string[]) args`"); // in contract + checkTip(m, 5, 24, "(parameter) `const(string[]) args`"); // static if is typeof expression + checkTip(m, 6, 10, "(parameter) `const(string[]) args`"); // if expression + checkTip(m, 11, 21, "(parameter) `const(string[]) args`"); // !in expression + + checkTip(m, 19, 9, "(enum) `pkg.source.EE`"); // enum EE + checkTip(m, 19, 13, "(enum value) `pkg.source.EE.E1 = 3`"); // enum E1 + checkTip(m, 19, 21, "(enum value) `pkg.source.EE.E2 = 4`"); // enum E2 + checkTip(m, 22, 14, "(enum) `pkg.source.EE`"); // enum EE + checkTip(m, 22, 17, "(enum value) `pkg.source.EE.E1 = 3`"); // enum E1 + + checkTip(m, 1, 9, "(package) `pkg`"); + checkTip(m, 1, 13, "(module) `pkg.source`"); + checkTip(m, 24, 10, "(package) `core`"); + checkTip(m, 24, 15, "(module) `core.cpuid`"); + checkTip(m, 24, 23, "(alias) `pkg.source.cpu_vendor = string core.cpuid.vendor() pure nothrow @nogc @property @trusted`"); + checkTip(m, 24, 36, "(alias) `pkg.source.cpu_vendor = string core.cpuid.vendor() pure nothrow @nogc @property @trusted`"); + checkTip(m, 24, 44, "(alias) `pkg.source.processor = string core.cpuid.processor() pure nothrow @nogc @property @trusted`"); + checkTip(m, 28, 11, "`string core.cpuid.vendor() pure nothrow @nogc @property @trusted`"); source = q{ // Line 1 @@ -471,21 +471,21 @@ unittest }; m = checkErrors(source, ""); - checkTip(m, 2, 10, "(struct) source.S"); - checkTip(m, 4, 8, "(field) int source.S.field1"); - checkTip(m, 6, 8, "int source.S.fun(int par)"); - checkTip(m, 6, 16, "(parameter) int par"); - checkTip(m, 6, 30, "(field) int source.S.field1"); - checkTip(m, 6, 39, "(parameter) int par"); + checkTip(m, 2, 10, "(struct) `source.S`"); + checkTip(m, 4, 8, "(field) `int source.S.field1`"); + checkTip(m, 6, 8, "`int source.S.fun(int par)`"); + checkTip(m, 6, 16, "(parameter) `int par`"); + checkTip(m, 6, 30, "(field) `int source.S.field1`"); + checkTip(m, 6, 39, "(parameter) `int par`"); - checkTip(m, 10, 4, "(struct) source.S"); - checkTip(m, 10, 6, "(local variable) source.S anS"); - checkTip(m, 11, 12, "(local variable) source.S anS"); - checkTip(m, 11, 16, "int source.S.fun(int par)"); + checkTip(m, 10, 4, "(struct) `source.S`"); + checkTip(m, 10, 6, "(local variable) `source.S anS`"); + checkTip(m, 11, 12, "(local variable) `source.S anS`"); + checkTip(m, 11, 16, "`int source.S.fun(int par)`"); - checkTip(m, 13, 11, "(struct) source.S"); - checkTip(m, 16, 19, "(thread local variable) long source.S.stat1"); - checkTip(m, 16, 17, "(struct) source.S"); + checkTip(m, 13, 11, "(struct) `source.S`"); + checkTip(m, 16, 19, "(thread local variable) `long source.S.stat1`"); + checkTip(m, 16, 17, "(struct) `source.S`"); checkDefinition(m, 11, 16, "source.d", 6, 8); // fun checkDefinition(m, 15, 17, "source.d", 2, 10); // S @@ -512,22 +512,22 @@ unittest }; m = checkErrors(source, ""); - checkTip(m, 2, 9, "(class) source.C"); - checkTip(m, 4, 8, "(field) int source.C.field1"); - checkTip(m, 6, 8, "int source.C.fun(int par)"); - checkTip(m, 6, 16, "(parameter) int par"); - checkTip(m, 6, 30, "(field) int source.C.field1"); - checkTip(m, 6, 39, "(parameter) int par"); + checkTip(m, 2, 9, "(class) `source.C`"); + checkTip(m, 4, 8, "(field) `int source.C.field1`"); + checkTip(m, 6, 8, "`int source.C.fun(int par)`"); + checkTip(m, 6, 16, "(parameter) `int par`"); + checkTip(m, 6, 30, "(field) `int source.C.field1`"); + checkTip(m, 6, 39, "(parameter) `int par`"); - checkTip(m, 10, 4, "(class) source.C"); - checkTip(m, 10, 15, "(class) source.C"); - checkTip(m, 10, 6, "(local variable) source.C aC"); - checkTip(m, 11, 12, "(local variable) source.C aC"); - checkTip(m, 11, 16, "int source.C.fun(int par)"); + checkTip(m, 10, 4, "(class) `source.C`"); + checkTip(m, 10, 15, "(class) `source.C`"); + checkTip(m, 10, 6, "(local variable) `source.C aC`"); + checkTip(m, 11, 12, "(local variable) `source.C aC`"); + checkTip(m, 11, 16, "`int source.C.fun(int par)`"); - checkTip(m, 13, 11, "(class) source.C"); - checkTip(m, 16, 19, "(thread local variable) long source.C.stat1"); - checkTip(m, 16, 17, "(class) source.C"); + checkTip(m, 13, 11, "(class) `source.C`"); + checkTip(m, 16, 19, "(thread local variable) `long source.C.stat1`"); + checkTip(m, 16, 17, "(class) `source.C`"); checkDefinition(m, 11, 16, "source.d", 6, 8); // fun checkDefinition(m, 15, 17, "source.d", 2, 9); // C @@ -541,9 +541,9 @@ unittest }; m = checkErrors(source, ""); - checkTip(m, 2, 10, "(struct) source.ST(T)"); - checkTip(m, 4, 4, "(unresolved type) T"); - checkTip(m, 4, 6, "T f"); + checkTip(m, 2, 10, "(struct) `source.ST(T)`"); + checkTip(m, 4, 4, "(unresolved type) `T`"); + checkTip(m, 4, 6, "`T f`"); source = q{ // Line 1 @@ -568,10 +568,10 @@ unittest }; m = checkErrors(source, ""); - checkTip(m, 9, 20, "(local variable) object.Exception e"); - checkTip(m, 9, 10, "(class) object.Exception"); - checkTip(m, 11, 21, "(class) object.Error"); - checkTip(m, 12, 5, "(class) object.Exception"); + checkTip(m, 9, 20, "(local variable) `object.Exception e`"); + checkTip(m, 9, 10, "(class) `object.Exception`"); + checkTip(m, 11, 21, "(class) `object.Error`"); + checkTip(m, 12, 5, "(class) `object.Exception`"); source = q{ // Line 1 @@ -659,16 +659,16 @@ unittest m = checkErrors(source, ""); //dumpAST(m); - checkTip(m, 6, 12, "(local variable) int i"); - checkTip(m, 7, 5, "(local variable) int sum"); - checkTip(m, 7, 12, "(local variable) int i"); + checkTip(m, 6, 12, "(local variable) `int i`"); + checkTip(m, 7, 5, "(local variable) `int sum`"); + checkTip(m, 7, 12, "(local variable) `int i`"); source = q{ // Line 1 enum TOK : ubyte { reserved, leftParentheses, // Line 5 - rightParentheses, + rightParentheses, /// right parent doc } void foo(TOK op) { @@ -678,24 +678,25 @@ unittest { this(TOK op, size_t sz) {} } // Line 15 - class LeftBase : Base + /// right base doc + class RightBase : Base { this() - { - super(TOK.leftParentheses, LeftBase.sizeof);// Line 20 + { // Line 20 + super(TOK.rightParentheses, RightBase.sizeof); } } }; m = checkErrors(source, ""); //dumpAST(m); - checkTip(m, 10, 8, "(parameter) source.TOK op"); - checkTip(m, 10, 14, "(enum) source.TOK"); - checkTip(m, 10, 18, "(enum value) source.TOK.leftParentheses = 1"); - checkTip(m, 20, 11, "(enum) source.TOK"); - checkTip(m, 20, 15, "(enum value) source.TOK.leftParentheses = 1"); - checkTip(m, 20, 32, "(class) source.LeftBase"); - //checkTip(m, 20, 41, "(constant) source.LeftBase.sizeof = 8"); + checkTip(m, 10, 8, "(parameter) `source.TOK op`"); + checkTip(m, 10, 14, "(enum) `source.TOK`"); + checkTip(m, 10, 18, "(enum value) `source.TOK.leftParentheses = 1`"); + checkTip(m, 21, 11, "(enum) `source.TOK`"); + checkTip(m, 21, 15, "(enum value) `source.TOK.rightParentheses = 2`"); + checkTip(m, 21, 33, "(class) `source.RightBase`\n\nright base doc"); + //checkTip(m, 20, 41, "(constant) `source.RightBase.sizeof = 8`"); } unittest diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index ea8d4b80..3a611cfb 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -862,14 +862,21 @@ extern(C++) class FindTipVisitor : FindASTVisitor found = obj; if (obj) { - tip = tipForObject(obj); + tip = tipForObject(obj, true); stop = true; } return stop; } } -string tipForObject(RootObject obj) +string quoteCode(bool quote, string s) +{ + if (!quote || s.empty) + return s; + return "`" ~ s ~ "`"; +} + +string tipForObject(RootObject obj, bool quote) { string tipForDeclaration(Declaration decl) { @@ -882,42 +889,44 @@ string tipForObject(RootObject obj) buf.writestring(decl.toPrettyChars()); auto res = buf.peekSlice(); buf.extractSlice(); // take ownership - return cast(string)res; + return quoteCode(quote, cast(string)res); } bool fqn = true; string txt; + string kind; if (decl.isParameter()) { - txt = "(parameter) "; + kind = "(parameter) "; fqn = false; } else if (auto em = decl.isEnumMember()) { - txt = "(enum value) " ~ decl.toPrettyChars(fqn).to!string; + kind = "(enum value) "; + txt = decl.toPrettyChars(fqn).to!string; if (em.origValue) txt ~= " = " ~ cast(string)em.origValue.toString(); - return txt; + return kind ~ quoteCode(quote, txt); } else if (decl.storage_class & STC.manifest) - txt = "(constant) "; + kind = "(constant) "; else if (decl.isAliasDeclaration()) - txt = "(alias) "; + kind = "(alias) "; else if (decl.isField()) - txt = "(field) "; + kind = "(field) "; else if (decl.semanticRun >= PASS.semanticdone) // avoid lazy semantic analysis { if (!decl.isDataseg() && !decl.isCodeseg()) { - txt = "(local variable) "; + kind = "(local variable) "; fqn = false; } else if (decl.isThreadlocal()) - txt = "(thread local variable) "; + kind = "(thread local variable) "; else if (decl.type && decl.type.isShared()) - txt = "(shared variable) "; + kind = "(shared variable) "; else if (decl.type && decl.type.ty != Terror) - txt = "(__gshared variable) "; + kind = "(__gshared variable) "; } if (decl.type) @@ -929,8 +938,8 @@ string tipForObject(RootObject obj) txt ~= " = " ~ var._init.toString(); if (auto ad = decl.isAliasDeclaration()) if (ad.aliassym) - txt ~= " = " ~ tipForObject(ad.aliassym); - return txt; + txt ~= " = " ~ tipForObject(ad.aliassym, false); + return kind ~ quoteCode(quote, txt); } string tip; @@ -943,7 +952,7 @@ string tipForObject(RootObject obj) kind = "unresolved type"; else kind = t.kind().to!string; - toc = "(" ~ kind ~ ") " ~ t.toPrettyChars(true).to!string; + toc = "(" ~ kind ~ ") " ~ quoteCode(quote, t.toPrettyChars(true).to!string); if (auto sym = typeSymbol(t)) if (sym.comment) doc = sym.comment; @@ -963,7 +972,7 @@ string tipForObject(RootObject obj) break; default: if (e.type) - toc = e.type.toPrettyChars(true).to!string; + toc = quoteCode(quote, e.type.toPrettyChars(true).to!string); break; } } @@ -972,7 +981,7 @@ string tipForObject(RootObject obj) if (auto decl = s.isDeclaration()) tip = tipForDeclaration(decl); else - toc = "(" ~ s.kind().to!string ~ ") " ~ s.toPrettyChars(true).to!string; + toc = "(" ~ s.kind().to!string ~ ") " ~ quoteCode(quote, s.toPrettyChars(true).to!string); if (s.comment) doc = s.comment; @@ -980,7 +989,7 @@ string tipForObject(RootObject obj) if (!tip.length) { if (!toc) - toc = obj.toString().dup; + toc = quoteCode(quote, obj.toString().dup); tip = toc; } // append doc diff --git a/vdc/ivdserver.d b/vdc/ivdserver.d index 24a5f193..45267600 100644 --- a/vdc/ivdserver.d +++ b/vdc/ivdserver.d @@ -88,6 +88,7 @@ public: // startLine, startIndex, endLine, endIndex: selected range in the editor // if start==end, mouse hovers without selection // flags: 1 - try to evaluate constants/expressions + // flags: 2 - quote code for highlighting // // it is assumed that the semantic analysis is forwarded to some other thread // and that the status can be polled by GetTipResult diff --git a/vdextensions/quickinfo.cs b/vdextensions/quickinfo.cs index 7822be83..d05a7e22 100644 --- a/vdextensions/quickinfo.cs +++ b/vdextensions/quickinfo.cs @@ -34,11 +34,14 @@ public ClassifiedTextBlock(string text) { } - public void setForeground(System.Windows.Media.Brush brush) + public void setForeground(System.Windows.Media.Brush brush, bool bold) { Foreground = brush; foreach (var inl in Inlines) + { inl.Foreground = brush; + inl.FontWeight = FontWeight.FromOpenTypeWeight(bold ? 700 : 400); + } } public void enableLink() @@ -97,7 +100,7 @@ static bool GetQuickInfo(string fname, int line, int col, out string info, out s return false; Thread.Sleep(100); } - return true; + return !string.IsNullOrEmpty(info); } } catch @@ -141,17 +144,17 @@ public System.Windows.Media.Brush GetBrush(ITextView view, string type) return null; } - public ClassifiedTextBlock createClassifiedTextBlock(ITextView view, string text, string type) + public ClassifiedTextBlock createClassifiedTextBlock(ITextView view, string text, string type, bool bold) { var tb = new ClassifiedTextBlock(text); if (String.IsNullOrEmpty(text) || String.IsNullOrEmpty(text.Trim())) return tb; - if (type == "Identifier") - tb.enableLink(); + //if (type == "Identifier") + // tb.enableLink(); // Foreground cannot be set from the constructor?! - tb.setForeground(GetBrush(view, type)); + tb.setForeground(GetBrush(view, type), bold); return tb; } @@ -177,6 +180,44 @@ public Task GetQuickInfoItemAsync(IAsyncQuickInfoSession session, // back in the UI thread to allow creation of UIElements var rows = new List(); var secs = new List(); + bool bold = false; + Func addClassifiedTextBlock = (string txt, string type) => + { + while (!String.IsNullOrEmpty(txt)) + { + string tag = bold ? "" : ""; + string sec; + bool secbold = bold; + var pos = txt.IndexOf(tag); + if (pos >= 0) + { + bold = !bold; + sec = txt.Substring(0, pos); + txt = txt.Substring(pos + tag.Length); + } + else + { + sec = txt; + txt = null; + } + if (!String.IsNullOrEmpty(sec)) + secs.Add(createClassifiedTextBlock(session.TextView, sec, type, secbold)); + } + return txt; + }; + + Func addTextSection = (string sec, string type) => + { + var nls = sec.Split('\n'); + for (int n = 0; n < nls.Length - 1; n++) + { + addClassifiedTextBlock(nls[n], type); + rows.Add(new ContainerElement(ContainerElementStyle.Wrapped, secs)); + secs = new List(); + } + addClassifiedTextBlock(nls[nls.Length - 1], type); + return sec; + }; string[] ops = fmt.Split(';'); int prevpos = 0; @@ -194,15 +235,7 @@ public Task GetQuickInfoItemAsync(IAsyncQuickInfoSession session, if (Int32.TryParse(colname[0], out pos) && pos > prevpos) { string sec = info.Substring(prevpos, pos - prevpos); - var nls = sec.Split('\n'); - for (int n = 0; n < nls.Length - 1; n++) - { - secs.Add(createClassifiedTextBlock(session.TextView, nls[n], prevtype)); - rows.Add(new ContainerElement(ContainerElementStyle.Wrapped, secs)); - secs = new List(); - } - secs.Add(createClassifiedTextBlock(session.TextView, nls[nls.Length-1], prevtype)); - + addTextSection(sec, prevtype); prevtype = colname[1]; prevpos = pos; } @@ -212,11 +245,11 @@ public Task GetQuickInfoItemAsync(IAsyncQuickInfoSession session, if (prevtype != null && prevpos < info.Length) { string sec = info.Substring(prevpos, info.Length - prevpos); - secs.Add(createClassifiedTextBlock(session.TextView, sec, prevtype)); + addTextSection(sec, prevtype); } else { - secs.Add(createClassifiedTextBlock(session.TextView, info, PredefinedClassificationTypeNames.SymbolDefinition)); + addClassifiedTextBlock(info, PredefinedClassificationTypeNames.SymbolDefinition); } if (secs.Count > 0) rows.Add(new ContainerElement(ContainerElementStyle.Wrapped, secs)); diff --git a/visuald/config.d b/visuald/config.d index fc4f6db1..c8771ce2 100644 --- a/visuald/config.d +++ b/visuald/config.d @@ -3413,6 +3413,31 @@ class Config : DisposingComObject, return files; } + string[] filterTroublesomeOptions(string[] cmds) + { + // filter out options that can cause unexpected failures due to file accesses + size_t j = 0; + for (size_t i = 0; i < cmds.length; i++) + { + if (cmds[i] == "-lib") + continue; + if (cmds[i] == "-vcg-ast") + continue; + if (cmds[i] == "-run") + break; + if (cmds[i].startsWith("-X")) // json + continue; + if (cmds[i].startsWith("-H")) // hdr + continue; + if (cmds[i].startsWith("-D")) // doc + continue; + if (cmds[i].startsWith("-deps")) + continue; + cmds[j++] = cmds[i]; + } + return cmds[0..j]; + } + string getCompilerVersionIDs(string cmd = null) { ProjectOptions opts = GetProjectOptions(); @@ -3442,6 +3467,7 @@ class Config : DisposingComObject, try { auto cmds = tokenizeArgs(cmd); + cmds = filterTroublesomeOptions(cmds); auto res = execute(cmds, null, ExecConfig.suppressConsole); if (res.status == 0) { diff --git a/visuald/dlangsvc.d b/visuald/dlangsvc.d index 669279f0..bdf5eeb5 100644 --- a/visuald/dlangsvc.d +++ b/visuald/dlangsvc.d @@ -586,8 +586,13 @@ class LanguageService : DisposingComObject, void UpdateColorizer(bool force) { + bool showErrors = Package.GetGlobalOptions().showParseErrors; foreach(src; mSources) + { src.mColorizer.OnConfigModified(force); + if (!showErrors && src.mParseErrors.length) + src.updateParseErrors(null); + } } // IVsOutliningCapableLanguage /////////////////////////////// @@ -887,17 +892,31 @@ class LanguageService : DisposingComObject, text = replace(text, "\a", "\n\n"); text = phobosDdocExpand(text); - mLastTip = toUTF16(text); - + wstring tip = toUTF16(text); string fmt; int state = 0; - uint pos = 0; + size_t pos = 0; int prevcol = -1; - while (pos < mLastTip.length) + bool incode = false; + while (pos < tip.length) { uint prevpos = pos; - int tok; - int col = dLex.scan(state, mLastTip, pos, tok); + int tok, col; + if (tip[pos] == '`') + { + tip = tip[0 .. pos] ~ tip[pos + 1 .. $]; + incode = !incode; + state = 0; + continue; + } + if (!incode) + { + while (pos < tip.length && tip[pos] != '`') + decode(tip, pos); + col = 0; + } + else + col = dLex.scan(state, tip, pos, tok); if (col != prevcol) { if (prevpos > 0) @@ -910,6 +929,7 @@ class LanguageService : DisposingComObject, prevcol = col; } } + mLastTip = tip; mLastTipFmt = toUTF16(fmt); } @@ -931,7 +951,7 @@ class LanguageService : DisposingComObject, TextSpan span = TextSpan(col, line, col + 1, line); ConfigureSemanticProject(src); - int flags = Package.GetGlobalOptions().showValueInTooltip ? 1 : 0; + int flags = (Package.GetGlobalOptions().showValueInTooltip ? 1 : 0) | 2; mLastTipRequest = vdServerClient.GetTip(src.GetFileName(), &span, flags, &tipCallback); mLastTipIdleTaskHandled = mLastTipIdleTaskScheduled; @@ -4151,6 +4171,8 @@ else extern(D) void OnUpdateModule(uint request, string filename, string parseErrors, vdc.util.TextPos[] binaryIsIn, string tasks) { + if (!Package.GetGlobalOptions().showParseErrors) + parseErrors = null; updateParseErrors(parseErrors); mBinaryIsIn = binaryIsIn; if(IVsTextColorState colorState = qi_cast!IVsTextColorState(mBuffer)) diff --git a/visuald/dpackage.d b/visuald/dpackage.d index 8624d673..9e67a24d 100644 --- a/visuald/dpackage.d +++ b/visuald/dpackage.d @@ -1529,6 +1529,7 @@ class GlobalOptions bool autoOutlining; byte deleteFiles; // 0: ask, -1: don't delete, 1: delete (obsolete) bool parseSource = true; + bool showParseErrors = true; bool pasteIndent; bool fmtIndentCase = true; bool expandFromSemantics; @@ -1567,13 +1568,14 @@ class GlobalOptions bool ColorizeReferences; bool lastColorizeCoverage; bool lastColorizeVersions; + bool lastShowParseErrors; bool lastUseDParser; string lastInstallDirs; int vsVersion; bool isVS2017OrLater() { return vsVersion >= 15; } - bool usesUpdateSemanticModule() { return parseSource || expandFromSemantics || showTypeInTooltip || semanticGotoDef; } - bool usesQuickInfoTooltips() { return isVS2017OrLater() && !useDParser; } + bool usesUpdateSemanticModule() { return parseSource || showParseErrors || expandFromSemantics || showTypeInTooltip || semanticGotoDef; } + bool usesQuickInfoTooltips() { return isVS2017OrLater(); } this() { @@ -1913,6 +1915,7 @@ class GlobalOptions autoOutlining = getBoolOpt("autoOutlining", true); deleteFiles = cast(byte) getIntOpt("deleteFiles", 0); //parseSource = getBoolOpt("parseSource", true); + showParseErrors = getBoolOpt("showParseErrors", true); expandFromSemantics = getBoolOpt("expandFromSemantics", true); //expandFromBuffer = getBoolOpt("expandFromBuffer", true); expandFromJSON = getBoolOpt("expandFromJSON", true); @@ -2099,6 +2102,7 @@ class GlobalOptions lastColorizeCoverage = ColorizeCoverage; lastColorizeVersions = ColorizeVersions; lastUseDParser = useDParser; + lastShowParseErrors = showParseErrors; updateDefaultColors(); @@ -2189,6 +2193,7 @@ class GlobalOptions keyToolOpts.Set("autoOutlining", autoOutlining); keyToolOpts.Set("deleteFiles", deleteFiles); //keyToolOpts.Set("parseSource", parseSource); + keyToolOpts.Set("showParseErrors", showParseErrors); keyToolOpts.Set("expandFromSemantics", expandFromSemantics); //keyToolOpts.Set("expandFromBuffer", expandFromBuffer); keyToolOpts.Set("expandFromJSON", expandFromJSON); @@ -2264,6 +2269,11 @@ class GlobalOptions lastInstallDirs = installDirs; updateColorizer = true; } + if (lastShowParseErrors != showParseErrors) + { + lastShowParseErrors = showParseErrors; + updateColorizer = true; + } if(updateColorizer) if(auto svc = Package.s_instance.mLangsvc) svc.UpdateColorizer(true); diff --git a/visuald/propertypage.d b/visuald/propertypage.d index 32c628a3..bc4bfafa 100644 --- a/visuald/propertypage.d +++ b/visuald/propertypage.d @@ -2939,6 +2939,7 @@ class IntellisensePropertyPage : GlobalPropertyPage override void CreateControls() { AddTitleLine("Semantic analysis"); + AddControl("", mShowParseErrors = new CheckBox(mCanvas, "Show parsing errors (squiggles and markers)")); version(DParserOption) AddControl("", mUseDmdParser = new CheckBox(mCanvas, "Experimental: use DMD parsing engine for semantic analysis")); AddControl("", mMixinAnalysis = new CheckBox(mCanvas, "Enable mixin analysis")); AddControl("", mUFCSExpansions = new CheckBox(mCanvas, "Enable UFCS expansions")); @@ -2973,6 +2974,7 @@ class IntellisensePropertyPage : GlobalPropertyPage override void SetControls(GlobalOptions opts) { + mShowParseErrors.setChecked(opts.showParseErrors); mExpandSemantics.setChecked(opts.expandFromSemantics); //mExpandFromBuffer.setChecked(opts.expandFromBuffer); mExpandFromJSON.setChecked(opts.expandFromJSON); @@ -2992,6 +2994,7 @@ class IntellisensePropertyPage : GlobalPropertyPage override int DoApply(GlobalOptions opts, GlobalOptions refopts) { int changes = 0; + changes += changeOption(mShowParseErrors.isChecked(), opts.showParseErrors, refopts.showParseErrors); changes += changeOption(mExpandSemantics.isChecked(), opts.expandFromSemantics, refopts.expandFromSemantics); //changes += changeOption(mExpandFromBuffer.isChecked(), opts.expandFromBuffer, refopts.expandFromBuffer); changes += changeOption(mExpandFromJSON.isChecked(), opts.expandFromJSON, refopts.expandFromJSON); @@ -3007,6 +3010,7 @@ class IntellisensePropertyPage : GlobalPropertyPage return changes; } + CheckBox mShowParseErrors; CheckBox mExpandSemantics; //CheckBox mExpandFromBuffer; CheckBox mExpandFromJSON; From 63c4756f0df515899035d95b050f579550e90fb4 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 5 Oct 2019 16:06:13 +0200 Subject: [PATCH 56/73] implement tooltip for collapsed region --- visuald/dlangsvc.d | 93 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/visuald/dlangsvc.d b/visuald/dlangsvc.d index bdf5eeb5..623f6267 100644 --- a/visuald/dlangsvc.d +++ b/visuald/dlangsvc.d @@ -1551,7 +1551,8 @@ struct IdentifierType uint type; } -class Source : DisposingComObject, IVsUserDataEvents, IVsTextLinesEvents, IVsTextMarkerClient +class Source : DisposingComObject, IVsUserDataEvents, IVsTextLinesEvents, + IVsTextMarkerClient, IVsHiddenTextClient { Colorizer mColorizer; IVsTextLines mBuffer; @@ -1629,6 +1630,8 @@ class Source : DisposingComObject, IVsUserDataEvents, IVsTextLinesEvents, IVsTex return S_OK; if(queryInterface!(IVsTextMarkerClient) (this, riid, pvObject)) return S_OK; + if(queryInterface!(IVsHiddenTextClient) (this, riid, pvObject)) + return S_OK; return super.QueryInterface(riid, pvObject); } @@ -1792,6 +1795,92 @@ class Source : DisposingComObject, IVsUserDataEvents, IVsTextLinesEvents, IVsTex return S_OK; } + // IVsHiddenTextClient /////////////////////////////////////////////// + HRESULT OnHiddenRegionChange(IVsHiddenRegion pHidReg, + in HIDDEN_REGION_EVENT EventCode, // HIDDENREGIONEVENT value + in BOOL fBufferModifiable) + { + return S_OK; + } + + HRESULT GetTipText(/+[in]+/ IVsHiddenRegion pHidReg, + /+[out, optional]+/ BSTR *pbstrText) + { + TextSpan span; + HRESULT hr = pHidReg.GetSpan(&span); + if (FAILED(hr) || !pbstrText) + return hr; + wstring txt = GetText(span.iStartLine, 0, span.iEndLine, span.iEndIndex); + + LANGPREFERENCES3 langPrefs; + uint tabsz = GetUserPreferences(&langPrefs, null) == S_OK ? langPrefs.uTabSize : 8; + if (span.iStartIndex > 0 && span.iStartIndex <= txt.length) + { + int vpos = visiblePosition(txt, tabsz, span.iStartIndex); + txt = repeat(cast(wchar)' ', vpos).array().to!wstring ~ txt[span.iStartIndex .. $]; + } + // unindent text, limit line length and number of lines + enum maxLines = 30; + enum maxLineLength = 130; + wstring[] lines = txt.splitLines(); + while (lines.length > 0 && strip(lines[0]).empty) + lines = lines[1..$]; + size_t visibleLines = min(lines.length, maxLines); + size_t minIndent = size_t.max; + for (size_t ln = 0; ln < visibleLines; ln++) + { + int p; + int n = countVisualSpaces(lines[ln], tabsz, &p); + if (p < lines[ln].length && n < minIndent) // ignore empty lines + minIndent = n; + } + for (size_t ln = 0; ln < visibleLines; ln++) + { + auto line = lines[ln].detab(tabsz); + if (line.length < minIndent) + line = null; + else if (line.length > minIndent + maxLineLength) + line = line[minIndent .. minIndent + maxLineLength] ~ "..."w; + else + line = line[minIndent .. $]; + lines[ln] = line.to!wstring; + } + if (lines.length > visibleLines) + lines = lines[0..visibleLines] ~ "..."w; + wstring tipText = join(lines, "\n"w); + *pbstrText = allocwBSTR(tipText); + return S_OK; + } + + HRESULT GetMarkerCommandInfo(/+[in]+/ IVsHiddenRegion pHidReg, in int iItem, + /+[out, custom(uuid_IVsHiddenTextClient, "optional")]+/ BSTR * pbstrText, + /+[out]+/ DWORD* pcmdf) + { + return E_NOTIMPL; + } + HRESULT ExecMarkerCommand(/+[in]+/ IVsHiddenRegion pHidReg, in int iItem) + { + return E_NOTIMPL; + } + + /* + MakeBaseSpanVisible is used for visibility control. If the user does something that requires a + piece of hidden text to be visible (e.g. Goto line command, debugger stepping, find in files hit, + etc.) then we will turn around and call this for regions that the text hiding manager cannot + automatically make visible. (In the current implementation this will only happen for concealed + regions; collapsible ones will be automatically expanded.) This CANNOT fail!! You must either + destroy the hidden region by calling IVsHiddenRegion::Remove() or else reset its range so that + it is no longer hiding the hidden text. It is OK to add/remove other regions when this is called. + */ + HRESULT MakeBaseSpanVisible(/+[in]+/ IVsHiddenRegion pHidReg, in TextSpan *pBaseSpan) + { + return E_NOTIMPL; + } + HRESULT OnBeforeSessionEnd() + { + return S_OK; + } + /////////////////////////////////////////////////////////////////////////////// void setDisasmFiles(string asmfile, string linefile) { @@ -1909,7 +1998,7 @@ version(threadedOutlining) {} else { scope(exit) release(htm); if(htm.GetHiddenTextSession(mBuffer, &mHiddenTextSession) != S_OK) - htm.CreateHiddenTextSession(0, mBuffer, null, &mHiddenTextSession); + htm.CreateHiddenTextSession(0, mBuffer, this, &mHiddenTextSession); } return mHiddenTextSession; } From a93fde30b753ad092181eafdda7fdf4fc838b4d9 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 6 Oct 2019 19:57:06 +0200 Subject: [PATCH 57/73] fix and tweak parameter tooltips --- CHANGES | 11 ++ vdc/abothe/Parser | 2 +- .../CodeSemantics/TooltipGenerator.cs | 152 +++++++++++------- vdc/abothe/comserver/VDServer.cs | 5 +- vdc/ivdserver.d | 1 + vdextensions/quickinfo.cs | 2 +- visuald/completion.d | 7 + visuald/dlangsvc.d | 4 +- visuald/intellisense.d | 38 ++++- visuald/viewfilter.d | 20 ++- 10 files changed, 167 insertions(+), 75 deletions(-) diff --git a/CHANGES b/CHANGES index 724fa7b3..2c8ffc7c 100644 --- a/CHANGES +++ b/CHANGES @@ -1177,3 +1177,14 @@ Version history unreleased Version 0.51.0 * Ctrl+Click goto definition added for VS2017+ + * experimental: semantic server built from dmd frontend + * VS2017+: syntax highlighted tool tips + * mago: + - new option "hide reference pointers" + - new option: "remove leading zeroes from hex values" + - fix crash expanding pointer to empty dynamic array + - large arrays: show growing index, fix omitting last element + * dparser: now creates server process per Visual Studio Instance + * added option to not show error squiggles and markers + * added tooltip to collapsed region + * fix function signature tool tips diff --git a/vdc/abothe/Parser b/vdc/abothe/Parser index 693d75f2..0cdef0ec 160000 --- a/vdc/abothe/Parser +++ b/vdc/abothe/Parser @@ -1 +1 @@ -Subproject commit 693d75f2a0b148fc09b947bc2de140dbaa5dd997 +Subproject commit 0cdef0ec17ddf955f348403a4c81c907e30e1052 diff --git a/vdc/abothe/comserver/CodeSemantics/TooltipGenerator.cs b/vdc/abothe/comserver/CodeSemantics/TooltipGenerator.cs index 77cdb97c..878c4aac 100644 --- a/vdc/abothe/comserver/CodeSemantics/TooltipGenerator.cs +++ b/vdc/abothe/comserver/CodeSemantics/TooltipGenerator.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Text; using D_Parser.Completion; using D_Parser.Dom; @@ -10,89 +11,118 @@ namespace DParserCOMServer.CodeSemantics { public class TooltipGenerator - : AbstractVDServerTask, Tuple> + : AbstractVDServerTask, int> { public TooltipGenerator(VDServer vdServer, EditorDataProvider editorDataProvider) : base(vdServer, editorDataProvider) { } - protected override Tuple Process( - EditorData editorData, Tuple opts) + protected override Tuple Process(EditorData editorData, int flags) { - bool evaluateUnderneathExpression = opts.Item1; - bool quoteCode = opts.Item2; + bool evaluateUnderneathExpression = (flags & 1) != 0; + bool quoteCode = (flags & 2) != 0; + bool overloads = (flags & 4) != 0; // codeOffset+1 because otherwise it does not work on the first character - editorData.CaretOffset++; + // editorData.CaretOffset++; var sr = DResolver.GetScopedCodeObject(editorData); if (sr == null) return Tuple.Create(CodeLocation.Empty, CodeLocation.Empty, String.Empty); - var types = LooseResolution.ResolveTypeLoosely(editorData, sr, out _, true); - + ArgumentsResolutionResult res = null; + if (overloads) + { + res = ParameterInsightResolution.ResolveArgumentContext(editorData); + } + else + { + var types = LooseResolution.ResolveTypeLoosely(editorData, sr, out _, true); + if (types != null) + { + res = new ArgumentsResolutionResult(); + res.ResolvedTypesOrMethods = new AbstractType[1] { types }; + } + } + if (editorData.CancelToken.IsCancellationRequested) return Tuple.Create(CodeLocation.Empty, CodeLocation.Empty, String.Empty); - if (types == null) + if (res == null || res.ResolvedTypesOrMethods == null) return Tuple.Create(sr.Location, sr.EndLocation, String.Empty); - var tipText = new StringBuilder(); DNode dn = null; - - foreach (var t in AmbiguousType.TryDissolve(types)) - { - var dt = t; - if (dt is AliasedType at) + var tips = new List>(); + foreach (var types in res.ResolvedTypesOrMethods) + { + foreach (var t in AmbiguousType.TryDissolve(types)) { - // jump to original definition if it is not renamed or the caret is on the import - var isRenamed = (at.Definition as ImportSymbolAlias)?.ImportBinding?.Alias != null; - if (!isRenamed || at.Definition.Location == sr.Location) - dt = at.Base; - } - tipText.Append(NodeToolTipContentGen.Instance.GenTooltipSignature(dt, false, -1, quoteCode)); - if (dt is DSymbol symbol) - dn = symbol.Definition; - - tipText.Append("\a"); - } - - while (tipText.Length > 0 && tipText[tipText.Length - 1] == '\a') - tipText.Length--; - - if (evaluateUnderneathExpression) - { - var ctxt = editorData.GetLooseResolutionContext(LooseResolution.NodeResolutionAttempt.Normal); - ctxt.Push(editorData); - try - { - ISymbolValue v = null; - if (dn is DVariable var && var.Initializer != null && var.IsConst) - v = Evaluation.EvaluateValue(var.Initializer, ctxt); - if (v == null && sr is IExpression expression) - v = Evaluation.EvaluateValue(expression, ctxt); - if (v != null && !(v is ErrorValue)) - { - var valueStr = " = " + v; - if (tipText.Length > valueStr.Length && - tipText.ToString(tipText.Length - valueStr.Length, valueStr.Length) != valueStr) - tipText.Append(valueStr); + var tipText = new StringBuilder(); + var dt = t; + if (dt is AliasedType at) + { + // jump to original definition if it is not renamed or the caret is on the import + var isRenamed = (at.Definition as ImportSymbolAlias)?.ImportBinding?.Alias != null; + if (!isRenamed || at.Definition.Location == sr.Location) + dt = at.Base; } - } - catch (Exception e) - { - tipText.Append("\aException during evaluation = ").Append(e.Message); - } + tipText.Append(NodeToolTipContentGen.Instance.GenTooltipSignature(dt, false, -1, quoteCode)); + if (dt is DSymbol symbol) + dn = symbol.Definition; + + if (evaluateUnderneathExpression) + { + var ctxt = editorData.GetLooseResolutionContext(LooseResolution.NodeResolutionAttempt.Normal); + ctxt.Push(editorData); + try + { + ISymbolValue v = null; + if (dn is DVariable var && var.Initializer != null && var.IsConst) + v = Evaluation.EvaluateValue(var.Initializer, ctxt); + if (v == null && sr is IExpression expression) + v = Evaluation.EvaluateValue(expression, ctxt); + if (v != null && !(v is ErrorValue)) + { + var valueStr = " = " + v; + if (tipText.Length > valueStr.Length && + tipText.ToString(tipText.Length - valueStr.Length, valueStr.Length) != valueStr) + tipText.Append(valueStr); + } + } + catch (Exception e) + { + tipText.Append(" (Exception during evaluation: ").Append(e.Message).Append(")"); + } + + ctxt.Pop(); + } + var docText = new StringBuilder(); + if (dn != null) + VDServerCompletionDataGenerator.GenerateNodeTooltipBody(dn, docText); - ctxt.Pop(); + tips.Add(Tuple.Create(tipText.ToString(), docText.ToString())); + } } + var text = new StringBuilder(); + string prevDoc = ""; + bool first = true; + foreach (var tip in tips) + { + // do not emit the same doc twice + if (overloads || (tip.Item2 != "ditto" && tip.Item2 != prevDoc)) + { + if (!string.IsNullOrEmpty(prevDoc)) + text.Append("\n").Append(prevDoc); + } + if (!first) + text.Append("\a"); + first = false; + text.Append(tip.Item1); + if (tip.Item2 != "ditto") + prevDoc = tip.Item2; + } + if (!string.IsNullOrEmpty(prevDoc)) + text.Append("\n").Append(prevDoc); - if (dn != null) - VDServerCompletionDataGenerator.GenerateNodeTooltipBody(dn, tipText); - - while (tipText.Length > 0 && tipText[tipText.Length - 1] == '\a') - tipText.Length--; - - return Tuple.Create(sr.Location, sr.EndLocation, tipText.ToString()); + return Tuple.Create(sr.Location, sr.EndLocation, text.ToString()); } } } \ No newline at end of file diff --git a/vdc/abothe/comserver/VDServer.cs b/vdc/abothe/comserver/VDServer.cs index 7d20375e..8f04af5d 100644 --- a/vdc/abothe/comserver/VDServer.cs +++ b/vdc/abothe/comserver/VDServer.cs @@ -110,7 +110,7 @@ public void UpdateModule(string filename, string srcText, int flags) public void GetIdentifierTypes(string filename, int startLine, int endLine, int flags) { - _identifierTypesTask.Run(filename, new CodeLocation(startLine + 1, 0), new Tuple (endLine, (flags & 1) != 0)); + _identifierTypesTask.Run(filename, new CodeLocation(0, startLine), new Tuple (endLine, (flags & 1) != 0)); } public void GetIdentifierTypesResult(out string answer) @@ -132,8 +132,7 @@ public void GetIdentifierTypesResult(out string answer) public void GetTip(string filename, int startLine, int startIndex, int endLine, int endIndex, int flags) { - _tipGenerationTask.Run(filename, new CodeLocation(startIndex + 1, startLine), - Tuple.Create((flags & 1) != 0, (flags & 2) != 0)); + _tipGenerationTask.Run(filename, new CodeLocation(startIndex + 1, startLine), flags); } public void GetTipResult(out int startLine, out int startIndex, out int endLine, out int endIndex, out string answer) diff --git a/vdc/ivdserver.d b/vdc/ivdserver.d index 45267600..cffdf4b4 100644 --- a/vdc/ivdserver.d +++ b/vdc/ivdserver.d @@ -89,6 +89,7 @@ public: // if start==end, mouse hovers without selection // flags: 1 - try to evaluate constants/expressions // flags: 2 - quote code for highlighting + // flags: 4 - return all overloads (rather than the current best match) // // it is assumed that the semantic analysis is forwarded to some other thread // and that the status can be polled by GetTipResult diff --git a/vdextensions/quickinfo.cs b/vdextensions/quickinfo.cs index d05a7e22..96c46eec 100644 --- a/vdextensions/quickinfo.cs +++ b/vdextensions/quickinfo.cs @@ -208,7 +208,7 @@ public Task GetQuickInfoItemAsync(IAsyncQuickInfoSession session, Func addTextSection = (string sec, string type) => { - var nls = sec.Split('\n'); + var nls = sec.Split(new char[1] { '\n' }, StringSplitOptions.None); for (int n = 0; n < nls.Length - 1; n++) { addClassifiedTextBlock(nls[n], type); diff --git a/visuald/completion.d b/visuald/completion.d index 26a46751..bd7f5500 100644 --- a/visuald/completion.d +++ b/visuald/completion.d @@ -1166,6 +1166,8 @@ class MethodData : DisposingComObject, IVsMethodData { if (mCurrentMethod < GetOverloadCount() - 1) mCurrentMethod++; + else + mCurrentMethod = 0; return mCurrentMethod; } @@ -1173,6 +1175,8 @@ class MethodData : DisposingComObject, IVsMethodData { if (mCurrentMethod > 0) mCurrentMethod--; + else + mCurrentMethod = GetOverloadCount() - 1; return mCurrentMethod; } @@ -1259,6 +1263,9 @@ class MethodData : DisposingComObject, IVsMethodData case MTT_CLOSEBRACKET: result = ")"; // mMethods.CloseBracket; + string constraint = mMethods[method].GetConstraint(); + if (constraint.length) + result ~= " " ~ constraint; break; case MTT_DELIMITER: diff --git a/visuald/dlangsvc.d b/visuald/dlangsvc.d index 623f6267..1c57d5ed 100644 --- a/visuald/dlangsvc.d +++ b/visuald/dlangsvc.d @@ -975,10 +975,12 @@ class LanguageService : DisposingComObject, // semantic completion /////////////////////////////////// - uint GetTip(Source src, TextSpan* pSpan, GetTipCallBack cb) + uint GetTip(Source src, TextSpan* pSpan, bool overloads, GetTipCallBack cb) { ConfigureSemanticProject(src); int flags = Package.GetGlobalOptions().showValueInTooltip ? 1 : 0; + if (overloads) + flags |= 4; return vdServerClient.GetTip(src.GetFileName(), pSpan, flags, cb); } uint GetDefinition(Source src, TextSpan* pSpan, GetDefinitionCallBack cb) diff --git a/visuald/intellisense.d b/visuald/intellisense.d index b41bbd8f..10c2c52f 100644 --- a/visuald/intellisense.d +++ b/visuald/intellisense.d @@ -551,6 +551,7 @@ class LibraryInfo struct ParameterInfo { string rettype; + string constraint; string[] name; string[] display; string[] desc; @@ -563,9 +564,25 @@ struct ParameterInfo if(lineInfo.length == 0) return false; int pos = lineInfo.length - 1; + + void skipWhiteSpace() + { + while (pos > 0) + { + auto tok = text[lineInfo[pos].StartIndex .. lineInfo[pos].EndIndex]; + if (!dLex.isCommentOrSpace(lineInfo[pos].type, tok)) + break; + pos--; + } + } + L_skipConstraint: + name = null; + display = null; + desc = null; + skipWhiteSpace(); if(text[lineInfo[pos].StartIndex .. lineInfo[pos].EndIndex] != ")") return false; // not a function - + int braceLevel = 1; pos--; string ident; @@ -598,7 +615,19 @@ struct ParameterInfo { braceLevel--; if(braceLevel == 0) + { prependParam(); + pos--; + skipWhiteSpace(); + tok = text[lineInfo[pos].StartIndex .. lineInfo[pos].EndIndex]; + if (tok == "if") + { + constraint = text[lineInfo[pos].StartIndex .. $].to!string; + pos--; + goto L_skipConstraint; + } + continue; + } } pos--; } @@ -647,7 +676,12 @@ struct Definition { return GetParamInfo().rettype; } - + + string GetConstraint() + { + return GetParamInfo().constraint; + } + int GetParameterCount() { return GetParamInfo().name.length; diff --git a/visuald/viewfilter.d b/visuald/viewfilter.d index f558005d..90be13f2 100644 --- a/visuald/viewfilter.d +++ b/visuald/viewfilter.d @@ -1667,15 +1667,23 @@ else return S_FALSE; goto stepUp; } - +version(none) +{ span.iStartIndex = idx; span.iStartLine = line; - span.iEndIndex = idx + 1; - span.iEndLine = line; +} +else +{ + // use caret after opening parenthesis + span.iStartIndex = otherIndex + 1; + span.iStartLine = otherLine; +} + span.iEndIndex = span.iStartIndex + 1; + span.iEndLine = span.iStartLine; mPendingMethodTipWord = word; mPendingMethodTipComma = cntComma; - mPendingRequest = Package.GetLanguageService().GetTip(mCodeWinMgr.mSource, &span, &OnGetMethodTipText); + mPendingRequest = Package.GetLanguageService().GetTip(mCodeWinMgr.mSource, &span, true, &OnGetMethodTipText); return S_OK; } @@ -1692,7 +1700,7 @@ else foreach(fn; funcs) { Definition def; - def.name = mPendingMethodTipWord; + def.name = ""; // name is already in the type, was mPendingMethodTipWord; int pos = fn.indexOf("\n"); if(pos >= 0) { @@ -1835,7 +1843,7 @@ version(none) // quick info tooltips not good enough yet if(mPendingSpan != span) { mPendingSpan = span; - mPendingRequest = Package.GetLanguageService().GetTip(src, &span, &OnGetTipText); + mPendingRequest = Package.GetLanguageService().GetTip(src, &span, false, &OnGetTipText); } return E_PENDING; } From bcfaa4b0f1a2dd5bc13db73c29b229d841aba27f Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Tue, 15 Oct 2019 08:31:14 +0200 Subject: [PATCH 58/73] x64 build: fix output folder --- c2d/c2d.visualdproj | 2 +- c2d/cpp2d.visualdproj | 2 +- sdk/vsi.visualdproj | 5 ++++- stdext/stdext.visualdproj | 2 +- vdc/dmdserver/dmdserver.visualdproj | 2 +- vdc/parser.visualdproj | 4 ++-- vdc/vdserver.visualdproj | 6 +++--- 7 files changed, 13 insertions(+), 10 deletions(-) diff --git a/c2d/c2d.visualdproj b/c2d/c2d.visualdproj index bbaeeacf..d67c7799 100644 --- a/c2d/c2d.visualdproj +++ b/c2d/c2d.visualdproj @@ -795,7 +795,7 @@ m:\s\d\rainers\windows\bin\dmd.exe .. .. - ..\bin\$(ConfigurationName)\$(PLATFORMNAME) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) diff --git a/c2d/cpp2d.visualdproj b/c2d/cpp2d.visualdproj index 1754366a..1a364cb3 100644 --- a/c2d/cpp2d.visualdproj +++ b/c2d/cpp2d.visualdproj @@ -916,7 +916,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. .. - ..\bin\$(ConfigurationName)64 + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) diff --git a/sdk/vsi.visualdproj b/sdk/vsi.visualdproj index 4aaac8e6..5ff407d9 100644 --- a/sdk/vsi.visualdproj +++ b/sdk/vsi.visualdproj @@ -916,7 +916,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -2078,6 +2078,7 @@ + @@ -2149,6 +2150,7 @@ + @@ -2212,6 +2214,7 @@ + diff --git a/stdext/stdext.visualdproj b/stdext/stdext.visualdproj index c66704a8..8833dcf8 100644 --- a/stdext/stdext.visualdproj +++ b/stdext/stdext.visualdproj @@ -916,7 +916,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) diff --git a/vdc/dmdserver/dmdserver.visualdproj b/vdc/dmdserver/dmdserver.visualdproj index a3197895..4148242c 100644 --- a/vdc/dmdserver/dmdserver.visualdproj +++ b/vdc/dmdserver/dmdserver.visualdproj @@ -1397,7 +1397,7 @@ $(CC) -nologo -c -Idmd\src -Idmd\src\dmd\backend -Idmd\src\dmd\tk -Idmd\src\dmd\root -Idmd\src\vcbuild -DTARGET_WINDOS=1 -FIwarnings.h 1 1 - c:\s\d\rainers\dmd\generated\Windows\Release\x64\dmd.exe + c:\s\d\rainers\windows\bin\dmd.exe dmd\src ..\.. $(DMDInstallDir)\src\druntime\src $(DMDInstallDir)\druntime\src dmd dmd\res ..\..\bin\$(ConfigurationName)\$(PlatformName) diff --git a/vdc/parser.visualdproj b/vdc/parser.visualdproj index 75a2505e..f8b4b546 100644 --- a/vdc/parser.visualdproj +++ b/vdc/parser.visualdproj @@ -674,7 +674,7 @@ m:\s\d\rainers\windows\bin\dmd.exe .. . - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -1884,7 +1884,7 @@ .. . - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) diff --git a/vdc/vdserver.visualdproj b/vdc/vdserver.visualdproj index 4730d198..1b7dd425 100644 --- a/vdc/vdserver.visualdproj +++ b/vdc/vdserver.visualdproj @@ -311,7 +311,7 @@ m:\s\d\rainers\windows\bin\dmd_msc.exe .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -1158,7 +1158,7 @@ .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) @@ -1642,7 +1642,7 @@ .. - ..\bin\$(ConfigurationName) + ..\bin\$(ConfigurationName)\$(PlatformName) $(OutDir)\$(ProjectName) From e7ee8300cb60c83e3a63b1d24501aefe7f336148 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Tue, 15 Oct 2019 08:33:40 +0200 Subject: [PATCH 59/73] fix build with dmd 2.088 --- vdc/ast/aggr.d | 6 +++--- vdc/ast/type.d | 4 ++-- vdc/interpret.d | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/vdc/ast/aggr.d b/vdc/ast/aggr.d index 22e3eafa..0b53ba2d 100644 --- a/vdc/ast/aggr.d +++ b/vdc/ast/aggr.d @@ -312,7 +312,7 @@ class Aggregate : Type return null; } - @disable override Value _interpretProperty(Context ctx, string prop) + /*@disable*/ override Value _interpretProperty(Context ctx, string prop) { if(Value v = getStaticProperty(prop)) return v; @@ -522,7 +522,7 @@ class InheritingAggregate : Aggregate return false; } - @disable override Value _interpretProperty(Context ctx, string prop) + /*@disable*/ override Value _interpretProperty(Context ctx, string prop) { foreach(bc; baseClasses) if(Value v = bc._interpretProperty(ctx, prop)) @@ -772,7 +772,7 @@ class BaseClass : Node writer("public ", getMember(0)); // protection diffent from C } - @disable Value _interpretProperty(Context ctx, string prop) + /*@disable*/ Value _interpretProperty(Context ctx, string prop) { if(auto clss = getClass()) return clss._interpretProperty(ctx, prop); diff --git a/vdc/ast/type.d b/vdc/ast/type.d index d79031ac..edc078ab 100644 --- a/vdc/ast/type.d +++ b/vdc/ast/type.d @@ -182,7 +182,7 @@ class Type : Node return v; return semanticErrorValue("cannot calculate property ", prop, " of type ", this); } - @disable Value _interpretProperty(Context ctx, string prop) + /*@disable*/ Value _interpretProperty(Context ctx, string prop) { return null; } @@ -433,7 +433,7 @@ class BasicType : Type return Category.kVoid; } - @disable override Value _interpretProperty(Context ctx, string prop) + /*@disable*/ override Value _interpretProperty(Context ctx, string prop) { switch(prop) { diff --git a/vdc/interpret.d b/vdc/interpret.d index f5b72f45..f9de8850 100644 --- a/vdc/interpret.d +++ b/vdc/interpret.d @@ -207,7 +207,7 @@ class Value return semanticErrorValue("cannot calculate property ", prop, " of value ", toStr()); } - @disable Value _interpretProperty(Context ctx, string prop) + /*@disable*/ Value _interpretProperty(Context ctx, string prop) { return getType()._interpretProperty(ctx, prop); } @@ -1237,7 +1237,7 @@ class DynArrayValue : ArrayValue!TypeDynamicArray return super.toMixin(); } - @disable override Value _interpretProperty(Context ctx, string prop) + /*@disable*/ override Value _interpretProperty(Context ctx, string prop) { switch(prop) { @@ -1510,7 +1510,7 @@ class PointerValue : Value } } - @disable override Value _interpretProperty(Context ctx, string prop) + /*@disable*/ override Value _interpretProperty(Context ctx, string prop) { switch(prop) { @@ -1688,7 +1688,7 @@ public: } } - @disable override Value _interpretProperty(Context ctx, string prop) + /*@disable*/ override Value _interpretProperty(Context ctx, string prop) { switch(prop) { @@ -1864,7 +1864,7 @@ class AggrValue : TupleValue return "" ~ _toStr("{", "}"); } - @disable override Value _interpretProperty(Context ctx, string prop) + /*@disable*/ override Value _interpretProperty(Context ctx, string prop) { auto type = getType(); if(Value v = type.getProperty(this, prop, true)) @@ -2007,7 +2007,7 @@ class ReferenceValueT(T) : ReferenceValue return type; } - @disable override Value _interpretProperty(Context ctx, string prop) + /*@disable*/ override Value _interpretProperty(Context ctx, string prop) { if(instance) if(Value v = instance._interpretProperty(ctx, prop)) From 6f333ce838c5113b005c507260558ae9501dd57b Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Tue, 15 Oct 2019 08:40:08 +0200 Subject: [PATCH 60/73] ivdserver: add warnings option improve handling of supplemantal error messaages semvisit: look into template instances and function literals findIdentifierTypes: ensure sorted by loc --- msbuild/dbuild/VCProjectInterop.cs | 8 +- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/dmderrors.d | 147 +++++++++++++++++++---------- vdc/dmdserver/dmdinit.d | 2 + vdc/dmdserver/dmdserver.d | 49 +++++----- vdc/dmdserver/semanalysis.d | 85 ++++++++++++++--- vdc/dmdserver/semvisitor.d | 33 ++++++- vdc/ivdserver.d | 11 ++- vdc/semanticopt.d | 1 + vdc/vdserver.d | 3 +- visuald/dlangsvc.d | 34 ++++++- visuald/vdextensions.d | 1 + 12 files changed, 273 insertions(+), 103 deletions(-) diff --git a/msbuild/dbuild/VCProjectInterop.cs b/msbuild/dbuild/VCProjectInterop.cs index b634b355..0468da5c 100644 --- a/msbuild/dbuild/VCProjectInterop.cs +++ b/msbuild/dbuild/VCProjectInterop.cs @@ -40,7 +40,7 @@ public partial class VisualCHelper : IVisualCHelper { /////////////////////////////////////////////////////////////////////// static int ConfigureFlags(bool unittestOn, bool debugOn, bool x64, bool cov, bool doc, bool nobounds, bool gdc, - int versionLevel, int debugLevel, bool noDeprecated, bool ldc) + int versionLevel, int debugLevel, bool noDeprecated, bool ldc, bool warnings) { return (unittestOn ? 1 : 0) | (debugOn ? 2 : 0) @@ -52,7 +52,8 @@ static int ConfigureFlags(bool unittestOn, bool debugOn, bool x64, bool cov, boo | (noDeprecated ? 128 : 0) | ((versionLevel & 0xff) << 8) | ((debugLevel & 0xff) << 16) - | (ldc ? 0x4000000 : 0); + | (ldc ? 0x4000000 : 0) + | (warnings ? 0x10000000 : 0); } @@ -207,11 +208,12 @@ public void GetDCompileOptions(IVsHierarchy proj, uint itemid, bool doc = vcprop.GetEvaluatedPropertyValue("DocDir") != "" || vcprop.GetEvaluatedPropertyValue("DocFile") != ""; bool nobounds = vcprop.GetEvaluatedPropertyValue("BoundsCheck") == "On"; bool noDeprecated = vcprop.GetEvaluatedPropertyValue("Deprecations") == "Error"; + bool warnings = vcprop.GetEvaluatedPropertyValue("Warnings") != "None"; bool gdc = false; int versionLevel = 0; int debugLevel = 0; flags = (uint)ConfigureFlags(unittestOn, debugOn, x64, cov, doc, nobounds, gdc, - versionLevel, debugLevel, noDeprecated, ldc); + versionLevel, debugLevel, noDeprecated, ldc, warnings); } diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index d2babe31..fbe95b6b 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit d2babe31f05803aa4aef506187f31735f02b3f62 +Subproject commit fbe95b6b6cf3a745d767a5b612f6396bce4e35ea diff --git a/vdc/dmdserver/dmderrors.d b/vdc/dmdserver/dmderrors.d index 68f04875..986aab4a 100644 --- a/vdc/dmdserver/dmderrors.d +++ b/vdc/dmdserver/dmderrors.d @@ -22,10 +22,82 @@ import core.stdc.string; import core.stdc.wchar_ : wcslen; shared(Object) gErrorSync = new Object; -__gshared string gErrorFile; -__gshared char[] gErrorMessages; -__gshared char[] gOtherErrorMessages; -__gshared bool gErrorWasSupplemental; +private __gshared // under gErrorSync lock +{ + string gErrorFile; + string gErrorMessages; + string gOtherErrorMessages; + + private string gLastHeader; + private string[] gLastErrorMsgs; // all but first are supplemental + private Loc[] gLastErrorLocs; +} + +void flushLastError() +{ + if (gLastErrorLocs.empty) + return; + assert(gLastErrorLocs.length == gLastErrorMsgs.length); + + char[1014] buf; + char[] genErrorMessage(size_t pos) + { + char[] msg; + if (pos < gLastErrorLocs.length) + { + Loc loc = gLastErrorLocs[pos]; + int len = snprintf(buf.ptr, buf.length, "%d,%d,%d,%d:", loc.linnum, loc.charnum - 1, loc.linnum, loc.charnum); + msg ~= buf[0..len]; + } + + msg ~= gLastHeader; + for (size_t i = 0; i < gLastErrorLocs.length; i++) + { + if (i > 0) + msg ~= "\a"; + + Loc loc = gLastErrorLocs[i]; + if (i == pos) + { + if (i > 0) + msg ~= "--> "; + } + else if (loc.filename) + { + int len = snprintf(buf.ptr, buf.length, "%s(%d): ", loc.filename, loc.linnum); + msg ~= buf[0..len]; + } + msg ~= gLastErrorMsgs[i]; + } + return msg; + } + + size_t otherLocs; + foreach (loc; gLastErrorLocs) + if (!loc.filename || _stricmp(loc.filename, gErrorFile) != 0) + otherLocs++; + + if (otherLocs == gLastErrorLocs.length) + { + gOtherErrorMessages ~= genErrorMessage(size_t.max) ~ "\n"; + } + else + { + for (size_t i = 0; i < gLastErrorLocs.length; i++) + { + Loc loc = gLastErrorLocs[i]; + if (loc.filename && _stricmp(loc.filename, gErrorFile) == 0) + { + gErrorMessages ~= genErrorMessage(i) ~ "\n"; + gLastHeader = "Info: "; + } + } + } + + gLastHeader = null; + gLastErrorLocs.length = 0; + gLastErrorMsgs.length = 0; +} void errorPrint(const ref Loc loc, Color headerColor, const(char)* header, const(char)* format, va_list ap, const(char)* p1 = null, const(char)* p2 = null) nothrow @@ -38,79 +110,56 @@ void errorPrint(const ref Loc loc, Color headerColor, const(char)* header, bool other = _stricmp(loc.filename, gErrorFile) != 0; while (header && std.ascii.isWhite(*header)) header++; - bool supplemental = !header && !*header; + bool supplemental = !header || !*header; + + if (!supplemental) + flushLastError(); __gshared char[4096] buf; int len = 0; - if (other) - { - len = snprintf(buf.ptr, buf.length, "%s(%d):", loc.filename, loc.linnum); - } - else - { - int llen = snprintf(buf.ptr, buf.length, "%d,%d,%d,%d:", loc.linnum, loc.charnum - 1, loc.linnum, loc.charnum); - gErrorMessages ~= buf[0..llen]; - if (supplemental) - gErrorMessages ~= gOtherErrorMessages; - gOtherErrorMessages = null; - } + if (header && *header) + gLastHeader = header[0..strlen(header)].idup; if (p1 && len < buf.length) len += snprintf(buf.ptr + len, buf.length - len, "%s ", p1); if (p2 && len < buf.length) len += snprintf(buf.ptr + len, buf.length - len, "%s ", p2); if (len < buf.length) len += vsnprintf(buf.ptr + len, buf.length - len, format, ap); - char nl = other ? '\a' : '\n'; - if (len < buf.length) - buf[len++] = nl; - else - buf[$-1] = nl; - - version(DebugServer) dbglog(buf[0..len]); - if (other) - { - if (gErrorWasSupplemental) - { - if (gErrorMessages.length && gErrorMessages[$-1] == '\n') - gErrorMessages[$-1] = '\a'; - gErrorMessages ~= buf[0..len]; - gErrorMessages ~= '\n'; - } - else if (supplemental) - gOtherErrorMessages ~= buf[0..len]; - else - { - gErrorWasSupplemental = false; - gOtherErrorMessages = buf[0..len].dup; - } - } - else - { - gErrorMessages ~= buf[0..len]; - gErrorWasSupplemental = supplemental; - } + gLastErrorMsgs ~= buf[0..len].dup; + gLastErrorLocs ~= loc; } catch(Exception e) { - + // tame synchronized "throwing" } } -void initErrorFile(string fname) +void initErrorMessages(string fname) { synchronized(gErrorSync) { gErrorFile = fname; gErrorMessages = null; gOtherErrorMessages = null; - gErrorWasSupplemental = false; + + gLastErrorLocs = null; + gLastErrorMsgs = null; import std.functional; diagnosticHandler = toDelegate(&errorPrint); } } +string getErrorMessages(bool other = false) +{ + synchronized(gErrorSync) + { + flushLastError(); + return other ? gOtherErrorMessages : gErrorMessages; + } +} + int _stricmp(const(char)*str1, string s2) nothrow { const(char)[] s1 = str1[0..strlen(str1)]; diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d index 56bbeb67..14e87e97 100644 --- a/vdc/dmdserver/dmdinit.d +++ b/vdc/dmdserver/dmdinit.d @@ -163,6 +163,7 @@ struct Options bool unittestOn; bool x64; bool msvcrt; + bool warnings; bool debugOn; bool coverage; bool doDoc; @@ -241,6 +242,7 @@ void dmdSetupParams(const ref Options opts) global.params.useInline = false; global.params.obj = false; global.params.useDeprecated = opts.noDeprecated ? DiagnosticReporting.error : DiagnosticReporting.off; + global.params.warnings = opts.warnings ? DiagnosticReporting.inform : DiagnosticReporting.off; global.params.linkswitches = Strings(); global.params.libfiles = Strings(); global.params.dllfiles = Strings(); diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index 85fd150c..b8a6fb28 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -215,7 +215,7 @@ class DMDServer : ComObject, IVDServer } catch(Throwable e) { - version(DebugCmd) dbglog ("taskLoop exception: " ~ e.msg); + version(DebugCmd) dbglog ("taskLoop exception: " ~ e.toString()); } } prioritySend(tid, "done"); @@ -245,7 +245,7 @@ class DMDServer : ComObject, IVDServer uint oldflags = ConfigureFlags!()(opts.unittestOn, opts.debugOn, opts.x64, opts.coverage, opts.doDoc, opts.noBoundsCheck, opts.gdcCompiler, 0, 0, // no need to compare version levels, done in setVersionIds - opts.noDeprecated, opts.ldcCompiler, opts.msvcrt, + opts.noDeprecated, opts.ldcCompiler, opts.msvcrt, opts.warnings, opts.mixinAnalysis, opts.UFCSExpansions); opts.unittestOn = (flags & 1) != 0; @@ -260,6 +260,7 @@ class DMDServer : ComObject, IVDServer opts.UFCSExpansions = (flags & 0x2_00_00_00) != 0; opts.ldcCompiler = (flags & 0x4_00_00_00) != 0; opts.msvcrt = (flags & 0x8_00_00_00) != 0; + opts.warnings = (flags & 0x10_00_00_00) != 0; int versionlevel = (flags >> 8) & 0xff; int debuglevel = (flags >> 16) & 0xff; @@ -325,6 +326,15 @@ class DMDServer : ComObject, IVDServer { version(DebugServer) dbglog(" doParse: " ~ firstLine(text)); + string combinedErrorMessages() + { + string msgs = getErrorMessages(); + string otherMessages = getErrorMessages(true); + if (otherMessages.length) + msgs ~= "1,0,1,1: errors in imported modules: " ~ otherMessages.replace("\n", "\a"); + return msgs; + } + synchronized(gErrorSync) { modData.state = ModuleState.Parsing; @@ -333,7 +343,7 @@ class DMDServer : ComObject, IVDServer { try { - initErrorFile(fname); + initErrorMessages(fname); modData.parsedModule = createModuleFromText(fname, text); } catch(OutOfMemoryError e) @@ -342,17 +352,14 @@ class DMDServer : ComObject, IVDServer } catch(Throwable t) { - version(DebugServer) dbglog("UpdateModule.doParse: exception " ~ t.msg); - } - synchronized(gErrorSync) - { - modData.parseErrors = cast(string) gErrorMessages; + version(DebugServer) dbglog("UpdateModule.doParse: exception " ~ t.toString()); } + modData.parseErrors = combinedErrorMessages(); modData.state = ModuleState.Analyzing; try { - initErrorFile(fname); + initErrorMessages(fname); // clear all other semantic modules? analyzeModules(modData); } @@ -362,12 +369,9 @@ class DMDServer : ComObject, IVDServer } catch(Throwable t) { - version(DebugServer) dbglog("UpdateModule.doParse: exception " ~ t.msg); - } - synchronized(gErrorSync) - { - modData.analyzeErrors = cast(string) gErrorMessages; + version(DebugServer) dbglog("UpdateModule.doParse: exception " ~ t.toString()); } + modData.analyzeErrors = combinedErrorMessages(); modData.state = ModuleState.Done; } @@ -436,7 +440,7 @@ class DMDServer : ComObject, IVDServer } catch(Throwable t) { - version(DebugServer) dbglog("GetTip: exception " ~ t.msg); + version(DebugServer) dbglog("GetTip: exception " ~ t.toString()); txt = "exception: " ~ t.msg; } } @@ -503,7 +507,7 @@ class DMDServer : ComObject, IVDServer } catch(Throwable t) { - version(DebugServer) dbglog("GetDefinition: exception " ~ t.msg); + version(DebugServer) dbglog("GetDefinition: exception " ~ t.toString()); } } mLastDefFile = deffilename; @@ -562,7 +566,7 @@ class DMDServer : ComObject, IVDServer } catch(Throwable t) { - version(DebugServer) dbglog("calcExpansions: exception " ~ t.msg); + version(DebugServer) dbglog("calcExpansions: exception " ~ t.toString()); } mSemanticExpansionsRunning = false; mLastSymbols = symbols; @@ -703,7 +707,7 @@ class DMDServer : ComObject, IVDServer } catch(Throwable t) { - version(DebugServer) dbglog("GetReferences: exception " ~ t.msg); + version(DebugServer) dbglog("GetReferences: exception " ~ t.toString()); } } mLastReferences = references; @@ -765,7 +769,7 @@ class DMDServer : ComObject, IVDServer } catch(Throwable t) { - version(DebugServer) dbglog("GetIdentifierTypes: exception " ~ t.msg); + version(DebugServer) dbglog("GetIdentifierTypes: exception " ~ t.toString()); } } mLastIdentifierTypes = identiferTypes; @@ -1119,6 +1123,7 @@ unittest false, //bool noDeprecated, false, //bool ldc, true, //bool msvcrt, + false, //bool warnings, true, //bool mixinAnalysis, true); //bool ufcsExpansionsfalse, @@ -1227,9 +1232,9 @@ unittest dumpGC(); } - checkTip(5, 9, "(local variable) int xyz"); - checkTip(6, 9, "void std.stdio.writeln!(int, int, int)(int _param_0, int _param_1, int _param_2) @safe"); - checkTip(7, 12, "(local variable) int xyz"); + checkTip(5, 9, "(local variable) `int xyz`"); + checkTip(6, 9, "`void std.stdio.writeln!(int, int, int)(int _param_0, int _param_1, int _param_2) @safe`"); + checkTip(7, 12, "(local variable) `int xyz`"); version(traceGC) wipeStack(); diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index 1c1f081b..85477f18 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -164,6 +164,7 @@ Module analyzeModule(Module parsedModule, const ref Options opts) mi.createSemanticModule(); } + version(none) // do this lazily foreach(ref mi; ctxt.modules) { mi.semanticModule.importAll(null); @@ -171,6 +172,7 @@ Module analyzeModule(Module parsedModule, const ref Options opts) } Module.rootModule = ctxt.modules[rootModuleIndex].semanticModule; + Module.rootModule.importAll(null); Module.rootModule.dsymbolSemantic(null); Module.dprogress = 1; Module.runDeferredSemantic(); @@ -184,7 +186,7 @@ Module analyzeModule(Module parsedModule, const ref Options opts) //////////////////////////////////////////////////////////////// //version = traceGC; -import tracegc; +//import tracegc; extern(Windows) void OutputDebugStringA(const(char)* lpOutputString); string[] guessImportPaths() @@ -208,6 +210,7 @@ unittest opts.predefineDefaultVersions = true; opts.x64 = true; opts.msvcrt = true; + opts.warnings = true; opts.importDirs = guessImportPaths(); auto filename = "source.d"; @@ -221,11 +224,11 @@ unittest Module checkErrors(string src, string expected_err) { - initErrorFile(filename); + initErrorMessages(filename); Module parsedModule = createModuleFromText(filename, src); assert(parsedModule); Module m = analyzeModule(parsedModule, opts); - auto err = cast(string) gErrorMessages; + auto err = getErrorMessages(); assert_equal(err, expected_err); return m; } @@ -246,9 +249,9 @@ unittest void checkBinaryIsInLocations(string src, Loc[] locs) { - initErrorFile(filename); + initErrorMessages(filename); Module parsedModule = createModuleFromText(filename, src); - auto err = cast(string) gErrorMessages; + auto err = getErrorMessages(); assert(err == null); assert(parsedModule); Loc[] locdata = findBinaryIsInLocations(parsedModule); @@ -331,7 +334,7 @@ unittest return abc; } }; - Module m = checkErrors(source, "4,10,4,11:undefined identifier `abc`\n"); + Module m = checkErrors(source, "4,10,4,11:Error: undefined identifier `abc`\n"); version(traceGC) { @@ -395,10 +398,10 @@ unittest int main(in string[] args) in(args.length > 1) in{ assert(args.length > 1); } do { - static if(is(typeof(args[0]) : string)) // Line 5 + static if(is(typeof(args[0]) : string)) { // Line 5 if (args[0] is args[1]) {} else if (args[1] !is args[0]) {} - + } int[string] aa; if (auto p = args[0] in aa) // Line 10 if (auto q = args[1] !in aa) {} @@ -590,9 +593,9 @@ unittest } }; m = checkErrors(source, - "14,2,14,3:identifier or `new` expected following `.`, not `}`\n" ~ - "14,2,14,3:semicolon expected, not `}`\n" ~ - "12,14,12,15:no property `f` for type `S`\n"); + "14,2,14,3:Error: identifier or `new` expected following `.`, not `}`\n" ~ + "14,2,14,3:Error: semicolon expected, not `}`\n" ~ + "12,14,12,15:Error: no property `f` for type `S`\n"); //dumpAST(m); checkExpansions(m, 12, 16, "f", [ "field1", "field2", "fun" ]); checkExpansions(m, 13, 16, "", [ "field1", "field2", "fun", "more" ]); @@ -697,6 +700,61 @@ unittest checkTip(m, 21, 15, "(enum value) `source.TOK.rightParentheses = 2`"); checkTip(m, 21, 33, "(class) `source.RightBase`\n\nright base doc"); //checkTip(m, 20, 41, "(constant) `source.RightBase.sizeof = 8`"); + + source = q{ + void fun() + { + string cmd = "cmd"; + bool isX86_64 = true; // Line 5 + cmd = "pushd .\n" ~ `call vcvarsall.bat ` ~ (isX86_64 ? "amd64" : "x86") ~ "\n" ~ "popd\n" ~ cmd; + } + }; + m = checkErrors(source, ""); + //dumpAST(m); + + checkTip(m, 6, 49, "(local variable) `bool isX86_64`"); + checkTip(m, 6, 97, "(local variable) `string cmd`"); + + source = q{ + void fun() + { + string str = "hello"; + string cmd = () // Line 5 + { + auto local = str.length; + return str; + }(); + } + }; + m = checkErrors(source, ""); + //dumpAST(m); + + checkTip(m, 7, 10, "(local variable) `ulong local`"); + checkTip(m, 7, 18, "(local variable) `string str`"); + + source = q{ + struct S(T) + { + T member; + } // Line 5 + S!int x; + }; + m = checkErrors(source, ""); + //dumpAST(m); + + checkTip(m, 6, 9, "(thread local variable) `source.S!int source.x`"); + checkTip(m, 4, 6, "(field) `int source.S!int.member`"); + + source = q{ + void foo() + { + version(none) + { // Line 5 + } + int test; + } + }; + m = checkErrors(source, ""); } unittest @@ -712,6 +770,7 @@ unittest opts.predefineDefaultVersions = true; opts.x64 = true; opts.msvcrt = true; + opts.warnings = true; opts.importDirs = guessImportPaths() ~ srcdir; opts.stringImportDirs ~= srcdir ~ "/../res"; opts.versionIds ~= "MARS"; @@ -730,11 +789,11 @@ unittest { try { - initErrorFile(filename); + initErrorMessages(filename); Module parsedModule = createModuleFromText(filename, src); assert(parsedModule); Module m = analyzeModule(parsedModule, opts); - auto err = cast(string) gErrorMessages; + auto err = getErrorMessages(); assert_equal(err, expected_err); return m; } diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 3a611cfb..fb898ca3 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -8,7 +8,7 @@ module vdc.dmdserver.semvisitor; -import vdc.ivdserver; +import vdc.ivdserver : TypeReferenceKind; import dmd.access; import dmd.aggregate; @@ -144,6 +144,14 @@ extern(C++) class ASTVisitor : StoppableVisitor visit(cast(Expression)expr); } + override void visit(FuncExp expr) + { + visitDeclaration(expr.fd); + visitDeclaration(expr.td); + + visit(cast(Expression)expr); + } + // types override void visit(Type) {} @@ -644,9 +652,19 @@ extern(C++) class FindASTVisitor : ASTVisitor foundScope = ss.scopesym; } - override void visit(TemplateInstance) + override void visit(TemplateInstance ti) { // skip members added by semantic + visit(cast(ScopeDsymbol)ti); + } + + override void visit(TemplateDeclaration td) + { + foreach(ti; td.instances) + if (!stop) + visit(ti); + + visit(cast(ScopeDsymbol)td); } override void visit(CallExp expr) @@ -1129,8 +1147,15 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) { if (auto pid = ident in idTypes) { - if (type != (*pid)[$-1].type) - *pid ~= IdTypePos(type, line, col); + // merge sorted + import std.range; + auto a = assumeSorted!"a.line < b.line || (a.line == b.line && a.col < b.col)"(*pid); + auto itp = IdTypePos(type, line, col); + auto sections = a.trisect(itp); + if (!sections[1].empty && sections[1][0].type == type) // upperbound + sections[1][0] = itp; + else if (sections[0].empty || sections[0][$-1].type != type) // lowerbound + *pid = (*pid)[0..sections[0].length] ~ itp ~ (*pid)[sections[0].length..$]; } else idTypes[ident] = [IdTypePos(type, line, col)]; diff --git a/vdc/ivdserver.d b/vdc/ivdserver.d index cffdf4b4..30b18255 100644 --- a/vdc/ivdserver.d +++ b/vdc/ivdserver.d @@ -222,7 +222,7 @@ public: /////////////////////////////////////////////////////////////////////// uint ConfigureFlags()(bool unittestOn, bool debugOn, bool x64, bool cov, bool doc, bool nobounds, bool gdc, - int versionLevel, int debugLevel, bool noDeprecated, bool ldc, bool msvcrt, + int versionLevel, int debugLevel, bool noDeprecated, bool ldc, bool msvcrt, bool warnings, bool mixinAnalysis, bool ufcsExpansions) { return (unittestOn ? 1 : 0) @@ -235,10 +235,11 @@ uint ConfigureFlags()(bool unittestOn, bool debugOn, bool x64, bool cov, bool do | (noDeprecated ? 128 : 0) | ((versionLevel & 0xff) << 8) | ((debugLevel & 0xff) << 16) - | (mixinAnalysis ? 0x1_00_00_00 : 0) - | (ufcsExpansions ? 0x2_00_00_00 : 0) - | (ldc ? 0x4_00_00_00 : 0) - | (msvcrt ? 0x8_00_00_00 : 0); + | (mixinAnalysis ? 0x01_00_00_00 : 0) + | (ufcsExpansions ? 0x02_00_00_00 : 0) + | (ldc ? 0x04_00_00_00 : 0) + | (msvcrt ? 0x08_00_00_00 : 0) + | (warnings ? 0x10_00_00_00 : 0); } // from D_Parser: types returned by GetIdentifierTypes diff --git a/vdc/semanticopt.d b/vdc/semanticopt.d index 2e2b7937..c3656d42 100644 --- a/vdc/semanticopt.d +++ b/vdc/semanticopt.d @@ -117,6 +117,7 @@ class Options bool coverage; bool doDoc; bool noBoundsCheck; + bool warnings; bool gdcCompiler; bool ldcCompiler; bool noDeprecated; diff --git a/vdc/vdserver.d b/vdc/vdserver.d index cbacdf5f..3a9f2272 100644 --- a/vdc/vdserver.d +++ b/vdc/vdserver.d @@ -184,7 +184,7 @@ class VDServer : ComObject, IVDServer uint oldflags = ConfigureFlags!()(opts.unittestOn, opts.debugOn, opts.x64, opts.coverage, opts.doDoc, opts.noBoundsCheck, opts.gdcCompiler, 0, 0, // no need to compare version levels, done in setVersionIds - opts.noDeprecated, opts.ldcCompiler, opts.msvcrt, + opts.noDeprecated, opts.ldcCompiler, opts.msvcrt, opts.warnings, opts.mixinAnalysis, opts.UFCSExpansions); opts.unittestOn = (flags & 1) != 0; @@ -199,6 +199,7 @@ class VDServer : ComObject, IVDServer opts.UFCSExpansions = (flags & 0x2_00_00_00) != 0; opts.ldcCompiler = (flags & 0x4_00_00_00) != 0; opts.msvcrt = (flags & 0x8_00_00_00) != 0; + opts.warnings = (flags & 0x10_00_00_00) != 0; int versionlevel = (flags >> 8) & 0xff; int debuglevel = (flags >> 16) & 0xff; diff --git a/visuald/dlangsvc.d b/visuald/dlangsvc.d index 1c57d5ed..5d5a9c88 100644 --- a/visuald/dlangsvc.d +++ b/visuald/dlangsvc.d @@ -1039,7 +1039,8 @@ class LanguageService : DisposingComObject, cfgopts.compiler == Compiler.GDC, cfgopts.versionlevel, cfgopts.debuglevel, cfgopts.errDeprecated, cfgopts.compiler == Compiler.LDC, - cfgopts.useMSVCRT (), globopts.mixinAnalysis, globopts.UFCSExpansions); + cfgopts.useMSVCRT (), cfgopts.warnings, + globopts.mixinAnalysis, globopts.UFCSExpansions); string strimp = cfgopts.replaceEnvironment(cfgopts.fileImppath, cfg); stringImp = tokenizeArgs(strimp); @@ -4272,6 +4273,7 @@ else foreach(pos; mBinaryIsIn) colorState.ReColorizeLines(pos.line - 1, pos.line); } + Package.GetErrorProvider().updateTaskItems(filename, parseErrors); Package.GetTaskProvider().updateTaskItems(filename, tasks); if (Package.GetGlobalOptions().semanticHighlighting) @@ -4356,13 +4358,27 @@ else void finishParseErrors() { + string file = GetFileName(); + Config cfg = getProjectConfig(file, true); + if(!cfg) + cfg = getCurrentStartupConfig(); + auto opts = cfg ? cfg.GetProjectOptions() : null; + clearParseErrors(); for(int i = 0; i < mParseErrors.length; i++) { auto span = mParseErrors[i].span; + int mtype = MARKER_CODESENSE_ERROR; + if (mParseErrors[i].msg.startsWith("Warning:") && (!opts || opts.infowarnings)) + mtype = MARKER_WARNING; + else if (mParseErrors[i].msg.startsWith("Deprecation:") && (!opts || !opts.errDeprecated)) + mtype = MARKER_WARNING; + else if (mParseErrors[i].msg.startsWith("Info:")) + mtype = MARKER_WARNING; IVsTextLineMarker marker; - mBuffer.CreateLineMarker(MARKER_CODESENSE_ERROR, span.iStartLine - 1, span.iStartIndex, + mBuffer.CreateLineMarker(mtype, span.iStartLine - 1, span.iStartIndex, span.iEndLine - 1, span.iEndIndex, this, &marker); + //release(marker); } } @@ -4556,12 +4572,20 @@ else mOutliningState = 2; } - bool hasParseError(ParserSpan span) + int hasParseError(ParserSpan span) { for(int i = 0; i < mParseErrors.length; i++) if(spanContains(span, mParseErrors[i].span.iStartLine-1, mParseErrors[i].span.iStartIndex)) - return true; - return false; + { + if (mParseErrors[i].msg.startsWith("Warning:")) + return 2; + if (mParseErrors[i].msg.startsWith("Deprecation:")) + return 3; + if (mParseErrors[i].msg.startsWith("Info:")) + return 3; + return 1; + } + return 0; } string getParseError(int line, int index) diff --git a/visuald/vdextensions.d b/visuald/vdextensions.d index 890e12cd..7526c2d4 100644 --- a/visuald/vdextensions.d +++ b/visuald/vdextensions.d @@ -103,6 +103,7 @@ int vdhelper_GetDCompileOptions(IVsHierarchy proj, VSITEMID itemid, ProjectOptio opt.versionlevel = (flags >> 8) & 0xff; opt.debuglevel = (flags >> 16) & 0xff; opt.mscoff = true; + opt.warnings = (flags & 0x10_00_00_00) != 0; return S_OK; } From 1087a31faa39eea8531925248b716c1920c4a679 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Tue, 15 Oct 2019 08:41:41 +0200 Subject: [PATCH 61/73] add semantic errors to error list --- visuald/dpackage.d | 40 +++++++++++++++++++++++++++++++++++++++- visuald/taskprovider.d | 35 ++++++++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/visuald/dpackage.d b/visuald/dpackage.d index 9e67a24d..31af8fad 100644 --- a/visuald/dpackage.d +++ b/visuald/dpackage.d @@ -381,6 +381,16 @@ class Package : DisposingComObject, mTaskProviderCookie = 0; } } + if (mErrorProviderCookie != 0) + { + if (auto errorList = queryService!(SVsErrorList, IVsTaskList)) + { + scope(exit) release(errorList); + errorList.UnregisterTaskProvider(mErrorProviderCookie); + mErrorProvider = null; + mErrorProviderCookie = 0; + } + } mHostSP = release(mHostSP); } @@ -530,13 +540,23 @@ version(none) if (auto taskList = queryService!(IVsTaskList)) { scope(exit) release(taskList); - mTaskProvider = newCom!TaskProvider; + mTaskProvider = newCom!TaskProvider(false); if (taskList.RegisterTaskProvider (mTaskProvider, &mTaskProviderCookie) != S_OK) mTaskProvider = null; else taskList.RefreshTasks(mTaskProviderCookie); } + if (auto errorList = queryService!(SVsErrorList, IVsTaskList)) + { + scope(exit) release(errorList); + mErrorProvider = newCom!TaskProvider(true); + if (errorList.RegisterTaskProvider (mErrorProvider, &mErrorProviderCookie) != S_OK) + mErrorProvider = null; + else + errorList.RefreshTasks(mErrorProviderCookie); + } + return S_OK; // E_NOTIMPL; } @@ -1298,6 +1318,12 @@ version(none) return s_instance.mTaskProvider; } + static TaskProvider GetErrorProvider() + { + assert(s_instance); + return s_instance.mErrorProvider; + } + static GlobalOptions GetGlobalOptions() { assert(s_instance); @@ -1331,6 +1357,15 @@ version(none) } } + static void RefreshErrorList() + { + if (auto errorList = queryService!(SVsErrorList, IVsTaskList)) + { + errorList.RefreshTasks(s_instance.mErrorProviderCookie); + release(errorList); + } + } + private: IServiceProvider mHostSP; uint mLangServiceCookie; @@ -1344,6 +1379,9 @@ private: TaskProvider mTaskProvider; uint mTaskProviderCookie; + TaskProvider mErrorProvider; + uint mErrorProviderCookie; + uint mOmLibraryCookie; GlobalOptions mOptions; diff --git a/visuald/taskprovider.d b/visuald/taskprovider.d index 067d85d0..98b00e46 100644 --- a/visuald/taskprovider.d +++ b/visuald/taskprovider.d @@ -27,9 +27,11 @@ class TaskProvider : DisposingComObject, IVsTaskProvider, IVsTaskListEvents { VSTASKPRIORITY[string] mTokens; CommentTaskItem[] mTasks; + bool mInErrorList; - this() + this(bool errlist) { + mInErrorList = errlist; RefreshTokens(); } @@ -66,7 +68,7 @@ class TaskProvider : DisposingComObject, IVsTaskProvider, IVsTaskListEvents mixin(LogCallMix); return E_NOTIMPL; } - override HRESULT get_ReRegistrationKey (BSTR *pbstrKey) + override HRESULT get_ReRegistrationKey(BSTR *pbstrKey) { mixin(LogCallMix); return E_NOTIMPL; @@ -113,7 +115,7 @@ class TaskProvider : DisposingComObject, IVsTaskProvider, IVsTaskListEvents if(idx > 0) { string[] num = split(t[0..idx], ","); - if(num.length == 2) + if(num.length >= 2) { try { @@ -126,7 +128,9 @@ class TaskProvider : DisposingComObject, IVsTaskProvider, IVsTaskListEvents pos++; if (pos == mTasks.length) { - mTasks ~= newCom!CommentTaskItem(txt, prio, filename, line, col); + auto task = newCom!CommentTaskItem(txt, prio, filename, line, col); + task.mError = mInErrorList; + mTasks ~= task; modified = true; } else if (mTasks[pos].mLine != line || mTasks[pos].mColumn != col || @@ -134,7 +138,7 @@ class TaskProvider : DisposingComObject, IVsTaskProvider, IVsTaskListEvents { mTasks[pos].mLine = line; mTasks[pos].mColumn = col; - mTasks[pos].mText = txt; + mTasks[pos].mText = txt.replace("\a", "\n"); mTasks[pos].mPriority = prio; modified = true; } @@ -157,7 +161,10 @@ class TaskProvider : DisposingComObject, IVsTaskProvider, IVsTaskListEvents modified = true; } if (modified) - Package.RefreshTaskList(); + if (mInErrorList) + Package.RefreshErrorList(); + else + Package.RefreshTaskList(); } // Retrieves token settings as defined by user in Tools -> Options -> Environment -> Task List. @@ -210,6 +217,7 @@ class CommentTaskItem : DComObject, IVsTaskItem, IVsErrorItem string mText; VSTASKPRIORITY mPriority; bool mChecked; + bool mError; this(string txt, VSTASKPRIORITY prio, string file, int line, int col) { @@ -241,7 +249,7 @@ class CommentTaskItem : DComObject, IVsTaskItem, IVsErrorItem override HRESULT get_Category(/+[out, retval]+/ VSTASKCATEGORY *pCat) { - *pCat = CAT_COMMENTS; + *pCat = mError ? CAT_CODESENSE : CAT_COMMENTS; return S_OK; } @@ -253,7 +261,7 @@ class CommentTaskItem : DComObject, IVsTaskItem, IVsErrorItem override HRESULT get_ImageListIndex(/+[out,retval]+/ int *pIndex) { - *pIndex = BMP_COMMENT; + *pIndex = mError ? BMP_SQUIGGLE : BMP_COMMENT; return S_OK; } @@ -352,7 +360,16 @@ class CommentTaskItem : DComObject, IVsTaskItem, IVsErrorItem // Returns the category of this item: error, warning, or informational message. HRESULT GetCategory(/+[out]+/ VSERRORCATEGORY* pCategory) { - *pCategory = EC_MESSAGE; + if (!mError) + *pCategory = EC_MESSAGE; + else if (mText.startsWith ("Deprecation:")) + *pCategory = EC_MESSAGE; + else if (mText.startsWith ("Info:")) + *pCategory = EC_MESSAGE; + else if (mText.startsWith ("Warning:")) + *pCategory = EC_WARNING; + else + *pCategory = EC_ERROR; return S_OK; } } From 0c7135dc9dce5cfd5fd658cf9ec642cd73a3babc Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Thu, 17 Oct 2019 09:19:33 +0200 Subject: [PATCH 62/73] flatten: do not modify actual processing, pass and collect original statements up the AST instead --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/semvisitor.d | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index fbe95b6b..5075ca4b 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit fbe95b6b6cf3a745d767a5b612f6396bce4e35ea +Subproject commit 5075ca4b9d2513a435910c995c394f22c68b40e8 diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index fb898ca3..8110811b 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -15,6 +15,7 @@ import dmd.aggregate; import dmd.apply; import dmd.arraytypes; import dmd.attrib; +import dmd.ast_node; import dmd.builtin; import dmd.cond; import dmd.console; @@ -66,7 +67,7 @@ extern(C++) class ASTVisitor : StoppableVisitor alias visit = StoppableVisitor.visit; - Expression[] visiting; + ASTNode[] visiting; size_t currentVisiting; void visitExpression(Expression expr) @@ -91,8 +92,16 @@ extern(C++) class ASTVisitor : StoppableVisitor if (stop || !stmt) return; + if (currentVisiting >= visiting.length) + visiting ~= stmt; + else + visiting[currentVisiting] = stmt; + currentVisiting++; + if (walkPostorder(stmt, this)) stop = true; + + visiting[--currentVisiting] = null; } void visitDeclaration(Dsymbol sym) @@ -283,7 +292,9 @@ extern(C++) class ASTVisitor : StoppableVisitor // statements override void visit(Statement stmt) { - visitStatement(stmt.original); + if (stmt.original) + if (!visiting.contains(stmt.original)) + visitStatement(stmt.original); } override void visit(ExpStatement stmt) @@ -591,6 +602,9 @@ extern(C++) class FindASTVisitor : ASTVisitor Statement s = (*cs.statements)[i]; if (!s) continue; + if (visiting.contains(s)) + continue; + if (s.loc.filename) { if (s.loc.filename !is filename || s.loc.linnum > endLine) @@ -617,6 +631,7 @@ extern(C++) class FindASTVisitor : ASTVisitor } s.accept(this); } + visit(cast(Statement)cs); } override void visit(ScopeDsymbol scopesym) From 876737846e2c22a52b1f0eba1767c6293b8cef69 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Fri, 18 Oct 2019 12:02:11 +0200 Subject: [PATCH 63/73] allow syntax-copying of classes in object.d pass -unittest to dmdserver --- vdc/dmdserver/dmdinit.d | 1 + vdc/dmdserver/dmdserver.d | 1 + vdc/dmdserver/semanalysis.d | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/vdc/dmdserver/dmdinit.d b/vdc/dmdserver/dmdinit.d index 14e87e97..7aa418c1 100644 --- a/vdc/dmdserver/dmdinit.d +++ b/vdc/dmdserver/dmdinit.d @@ -232,6 +232,7 @@ void dmdSetupParams(const ref Options opts) global.params.errorLimit = 0; global.params.color = false; global.params.link = true; + global.params.useUnitTests = opts.unittestOn; global.params.useAssert = opts.debugOn ? CHECKENABLE.on : CHECKENABLE.off; global.params.useInvariants = opts.debugOn ? CHECKENABLE.on : CHECKENABLE.off; global.params.useIn = opts.debugOn ? CHECKENABLE.on : CHECKENABLE.off; diff --git a/vdc/dmdserver/dmdserver.d b/vdc/dmdserver/dmdserver.d index b8a6fb28..85ac2c56 100644 --- a/vdc/dmdserver/dmdserver.d +++ b/vdc/dmdserver/dmdserver.d @@ -162,6 +162,7 @@ class DMDServer : ComObject, IVDServer override ULONG Release() { + version(SingleThread) if(count == 1 && mTid != mTid.init) { // avoid recursive calls if the object is temporarily ref-counted diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index 85477f18..01f8d364 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -205,12 +205,14 @@ unittest import core.memory; dmdInit(); + dmdReinit(); Options opts; opts.predefineDefaultVersions = true; opts.x64 = true; opts.msvcrt = true; opts.warnings = true; + opts.unittestOn = true; opts.importDirs = guessImportPaths(); auto filename = "source.d"; @@ -229,7 +231,9 @@ unittest assert(parsedModule); Module m = analyzeModule(parsedModule, opts); auto err = getErrorMessages(); + auto other = getErrorMessages(true); assert_equal(err, expected_err); + assert_equal(other, ""); return m; } @@ -745,6 +749,7 @@ unittest checkTip(m, 6, 9, "(thread local variable) `source.S!int source.x`"); checkTip(m, 4, 6, "(field) `int source.S!int.member`"); + // check for conditional not producing warning "unreachable code" source = q{ void foo() { @@ -755,6 +760,34 @@ unittest } }; m = checkErrors(source, ""); + + // check for semantics in unittest + source = q{ + unittest + { + int var1 = 1; + int var2 = var1 + 1; // Line 5 + } + }; + m = checkErrors(source, ""); + checkTip(m, 5, 15, "(local variable) `int var1`"); + + // can object.d create reserved classes, e.g. Error? + source = q{ + module object; + alias ulong size_t; + class Object + { + } + class Throwable + { + } + class Error : Throwable + { + } + }; + m = checkErrors(source, ""); + // beware: bad object.d after this point } unittest @@ -764,6 +797,8 @@ unittest import std.file; dmdInit(); + lastContext = null; + string srcdir = "dmd/src"; Options opts; @@ -794,7 +829,9 @@ unittest assert(parsedModule); Module m = analyzeModule(parsedModule, opts); auto err = getErrorMessages(); + auto other = getErrorMessages(true); assert_equal(err, expected_err); + assert_equal(other, ""); return m; } catch(Throwable t) From b7d7836796fdcd14e6d9cf636607928bfdd6962a Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 20 Oct 2019 13:41:21 +0200 Subject: [PATCH 64/73] fix highlighting types --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/semanalysis.d | 52 ++++++++++++++-- vdc/dmdserver/semvisitor.d | 120 +++++++++++++++++++++++++++++------- vdc/ivdserver.d | 3 + 4 files changed, 150 insertions(+), 27 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index 5075ca4b..c4c97160 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit 5075ca4b9d2513a435910c995c394f22c68b40e8 +Subproject commit c4c9716078fef138c665a5e77d202fc29a886631 diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index 01f8d364..fa13cfc5 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -554,7 +554,7 @@ unittest source = q{ // Line 1 - void foo() + inout(Exception) foo(inout(char)* ptr) { int x = 1; try @@ -565,20 +565,24 @@ unittest { // Line 10 auto err = cast(Error) e; Exception* pe = &e; + const(Exception*) cpe = &e; throw new Error("unexpected"); } finally { x = 0; } + return null; } }; m = checkErrors(source, ""); - checkTip(m, 9, 20, "(local variable) `object.Exception e`"); - checkTip(m, 9, 10, "(class) `object.Exception`"); + checkTip(m, 9, 20, "(local variable) `object.Exception e`"); + checkTip(m, 9, 10, "(class) `object.Exception`"); checkTip(m, 11, 21, "(class) `object.Error`"); - checkTip(m, 12, 5, "(class) `object.Exception`"); + checkTip(m, 12, 5, "(class) `object.Exception`"); + checkTip(m, 13, 11, "(class) `const(object.Exception)`"); + checkTip(m, 2, 9, "(class) `inout(object.Exception)`"); source = q{ // Line 1 @@ -634,6 +638,7 @@ unittest ]; checkIdentifierTypes(m, exp); + // references source = q{ // Line 1 struct S @@ -693,6 +698,18 @@ unittest super(TOK.rightParentheses, RightBase.sizeof); } } + TOK[Base] mapBaseTOK; + + void testcase(int op) + { + switch(op) + { // from object.d + case TypeInfo_Class.ClassFlags.isCOMclass: // Line 30 + case TypeInfo_Class.ClassFlags.noPointers: + default: + break; + } + } }; m = checkErrors(source, ""); //dumpAST(m); @@ -703,8 +720,35 @@ unittest checkTip(m, 21, 11, "(enum) `source.TOK`"); checkTip(m, 21, 15, "(enum value) `source.TOK.rightParentheses = 2`"); checkTip(m, 21, 33, "(class) `source.RightBase`\n\nright base doc"); + checkTip(m, 24, 19, "(thread local variable) `source.TOK[source.Base] source.mapBaseTOK`"); + checkTip(m, 24, 7, "(class) `source.Base`"); + checkTip(m, 24, 3, "(enum) `source.TOK`"); + checkTip(m, 30, 10, "(class) `object.TypeInfo_Class`"); + checkTip(m, 30, 25, "(enum) `object.TypeInfo_Class.ClassFlags`"); + checkTip(m, 30, 36, "(enum value) `object.TypeInfo_Class.ClassFlags.isCOMclass = 1u`"); //checkTip(m, 20, 41, "(constant) `source.RightBase.sizeof = 8`"); + IdTypePos[][string] exp2 = [ + "size_t": [ IdTypePos(TypeReferenceKind.BasicType) ], + "Base": [ IdTypePos(TypeReferenceKind.Class) ], + "mapBaseTOK": [ IdTypePos(TypeReferenceKind.TLSVariable) ], + "TOK": [ IdTypePos(TypeReferenceKind.Enum) ], + "testcase": [ IdTypePos(TypeReferenceKind.Function) ], + "rightParentheses": [ IdTypePos(TypeReferenceKind.EnumValue) ], + "__ctor": [ IdTypePos(TypeReferenceKind.Method) ], + "sz": [ IdTypePos(TypeReferenceKind.ParameterVariable) ], + "RightBase": [ IdTypePos(TypeReferenceKind.Class) ], + "foo": [ IdTypePos(TypeReferenceKind.Function) ], + "leftParentheses": [ IdTypePos(TypeReferenceKind.EnumValue) ], + "op": [ IdTypePos(TypeReferenceKind.ParameterVariable) ], + "reserved": [ IdTypePos(TypeReferenceKind.EnumValue) ], + "noPointers": [ IdTypePos(TypeReferenceKind.EnumValue) ], + "isCOMclass": [ IdTypePos(TypeReferenceKind.EnumValue) ], + "TypeInfo_Class": [ IdTypePos(TypeReferenceKind.Class) ], + "ClassFlags": [ IdTypePos(TypeReferenceKind.Enum) ], + ]; + checkIdentifierTypes(m, exp2); + source = q{ void fun() { diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 8110811b..8d89e964 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -800,8 +800,11 @@ extern(C++) class FindASTVisitor : ASTVisitor override void visit(FuncDeclaration decl) { super.visit(decl); + if (found && !foundScope) foundScope = decl.scopesym; + + visitTypeIdentifier(decl.originalType, decl.type); } void visitTypeIdentifier(Type originalType, Type resolvedType) @@ -814,13 +817,25 @@ extern(C++) class FindASTVisitor : ASTVisitor return; switch (originalType.ty) { + case Taarray: + { + auto originalAA = cast(TypeAArray) originalType; + auto resolvedAA = cast(TypeAArray) resolvedType; + visitTypeIdentifier(originalAA.index, resolvedAA.index); + if (found) + return; + goto case; + } case Tarray: case Tpointer: case Treference: case Tsarray: case Tvector: + case Tfunction: originalType = (cast(TypeNext) originalType).next; resolvedType = (cast(TypeNext) resolvedType).next; + if (!originalType || !resolvedType) + return; break; default: return; @@ -978,17 +993,24 @@ string tipForObject(RootObject obj, bool quote) string tip; string toc; const(char)* doc; - if (auto t = obj.isType()) + + string tipForType(Type t) { string kind; if (t.isTypeIdentifier()) kind = "unresolved type"; else kind = t.kind().to!string; - toc = "(" ~ kind ~ ") " ~ quoteCode(quote, t.toPrettyChars(true).to!string); + string txt = "(" ~ kind ~ ") " ~ quoteCode(quote, t.toPrettyChars(true).to!string); if (auto sym = typeSymbol(t)) if (sym.comment) doc = sym.comment; + return txt; + } + + if (auto t = obj.isType()) + { + toc = tipForType(t); } else if (auto e = obj.isExpression()) { @@ -1005,7 +1027,7 @@ string tipForObject(RootObject obj, bool quote) break; default: if (e.type) - toc = quoteCode(quote, e.type.toPrettyChars(true).to!string); + toc = tipForType(e.type); break; } } @@ -1182,6 +1204,24 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) addTypePos(ident.toString(), type, loc.linnum, loc.charnum); } + void addIdentByType(ref const Loc loc, Identifier ident, Type t) + { + if (ident && t && loc.filename is filename) + { + int type = TypeReferenceKind.Unknown; + switch (t.ty) + { + case Tstruct: type = TypeReferenceKind.Struct; break; + //case Tunion: type = TypeReferenceKind.Union; break; + case Tclass: type = TypeReferenceKind.Class; break; + case Tenum: type = TypeReferenceKind.Enum; break; + default: break; + } + if (type != TypeReferenceKind.Unknown) + addTypePos(ident.toString(), type, loc.linnum, loc.charnum); + } + } + void addPackages(IdentifiersAtLoc* packages) { if (packages) @@ -1264,6 +1304,46 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) addIdent(sym.loc, sym.ident, TypeReferenceKind.Variable); } + override void visit(Parameter sym) + { + addIdent(sym.ident.loc, sym.ident, TypeReferenceKind.ParameterVariable); + } + + override void visit(Module mod) + { + if (mod.md) + { + addPackages(mod.md.packages); + addIdent(mod.md.loc, mod.md.id, TypeReferenceKind.Module); + } + visit(cast(Package)mod); + } + + override void visit(Import imp) + { + addPackages(imp.packages); + + addIdent(imp.loc, imp.id, TypeReferenceKind.Module); + + for (int n = 0; n < imp.names.dim; n++) + { + addIdent(imp.names[n].loc, imp.names[n].ident, TypeReferenceKind.Alias); + if (imp.aliases[n].ident && n < imp.aliasdecls.dim) + addDeclaration(imp.aliases[n].loc, imp.aliasdecls[n]); + } + // symbol has ident of first package, so don't forward + } + + override void visit(DebugCondition cond) + { + addIdent(cond.loc, cond.ident, TypeReferenceKind.VersionIdentifier); + } + + override void visit(VersionCondition cond) + { + addIdent(cond.loc, cond.ident, TypeReferenceKind.VersionIdentifier); + } + override void visit(VarDeclaration decl) { addType(decl.loc, decl.type, decl.originalType); @@ -1291,31 +1371,27 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) super.visit(ne); } - override void visit(DotVarExp dve) + override void visit(TypeExp expr) { - if (dve.var && dve.var.ident) - addDeclaration(dve.varloc.filename ? dve.varloc : dve.loc, dve.var); - super.visit(dve); - } - - override void visit(Import imp) - { - addPackages(imp.packages); - - addIdent(imp.loc, imp.id, TypeReferenceKind.Module); - - for (int n = 0; n < imp.names.dim; n++) + if (expr.original && expr.type) { - addIdent(imp.names[n].loc, imp.names[n].ident, TypeReferenceKind.Alias); - if (imp.aliases[n].ident && n < imp.aliasdecls.dim) - addDeclaration(imp.aliases[n].loc, imp.aliasdecls[n]); + if (auto ie = expr.original.isIdentifierExp()) + { + addIdentByType(ie.loc, ie.ident, expr.type); + } + else if (auto die = expr.original.isDotIdExp()) + { + addIdentByType(die.ident.loc, die.ident, expr.type); + } } - // symbol has ident of first package, so don't forward + super.visit(expr); } - override void visit(Parameter sym) + override void visit(DotVarExp dve) { - addIdent(sym.ident.loc, sym.ident, TypeReferenceKind.ParameterVariable); + if (dve.var && dve.var.ident) + addDeclaration(dve.varloc.filename ? dve.varloc : dve.loc, dve.var); + super.visit(dve); } override void visit(EnumDeclaration ed) diff --git a/vdc/ivdserver.d b/vdc/ivdserver.d index 30b18255..471c5433 100644 --- a/vdc/ivdserver.d +++ b/vdc/ivdserver.d @@ -271,4 +271,7 @@ enum TypeReferenceKind : uint Function, Method, BasicType, + + DebugIdentifier, + VersionIdentifier, } From 4b4a10363ed75b5aa7e17ec8a42869ecbcee1a35 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 2 Nov 2019 14:14:29 +0100 Subject: [PATCH 65/73] dmdserver: fix base class references, show kind interface and union --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/semanalysis.d | 67 ++++++++++++++++++++++++++++++++++--- vdc/dmdserver/semvisitor.d | 48 ++++++++++++++++++++------ 3 files changed, 101 insertions(+), 16 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index c4c97160..88ac060c 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit c4c9716078fef138c665a5e77d202fc29a886631 +Subproject commit 88ac060ccad64d70769a2d59ffe98d11b3ea40eb diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index fa13cfc5..d9987f3b 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -206,6 +206,7 @@ unittest dmdInit(); dmdReinit(); + lastContext = null; Options opts; opts.predefineDefaultVersions = true; @@ -332,13 +333,14 @@ unittest } string source; + Module m; source = q{ int main() { return abc; } }; - Module m = checkErrors(source, "4,10,4,11:Error: undefined identifier `abc`\n"); + m = checkErrors(source, "4,10,4,11:Error: undefined identifier `abc`\n"); version(traceGC) { @@ -655,7 +657,7 @@ unittest }; m = checkErrors(source, ""); - checkReferences(m, 4, 8, [TextPos(4,8), TextPos(5, 23), TextPos(10, 16)]); + checkReferences(m, 4, 8, [TextPos(4,8), TextPos(5, 23), TextPos(10, 16)]); // fun // foreach lowered to for source = q{ // Line 1 @@ -686,7 +688,7 @@ unittest { if (op == TOK.leftParentheses) {} // Line 10 } - class Base + class Base : Object { this(TOK op, size_t sz) {} } // Line 15 @@ -700,7 +702,7 @@ unittest } TOK[Base] mapBaseTOK; - void testcase(int op) + c_long testcase(int op) { switch(op) { // from object.d @@ -709,7 +711,9 @@ unittest default: break; } + return 0; } + import core.stdc.config; }; m = checkErrors(source, ""); //dumpAST(m); @@ -746,6 +750,11 @@ unittest "isCOMclass": [ IdTypePos(TypeReferenceKind.EnumValue) ], "TypeInfo_Class": [ IdTypePos(TypeReferenceKind.Class) ], "ClassFlags": [ IdTypePos(TypeReferenceKind.Enum) ], + "Object": [ IdTypePos(TypeReferenceKind.Class) ], + "core": [ IdTypePos(TypeReferenceKind.Package) ], + "stdc": [ IdTypePos(TypeReferenceKind.Package) ], + "config": [ IdTypePos(TypeReferenceKind.Module) ], + "c_long": [ IdTypePos(TypeReferenceKind.BasicType) ], ]; checkIdentifierTypes(m, exp2); @@ -816,6 +825,54 @@ unittest m = checkErrors(source, ""); checkTip(m, 5, 15, "(local variable) `int var1`"); + // check position of var in AddrExp + source = q{ + void fun(int* p); + void foo() + { + int var = 1; // Line 5 + fun(&var); + } + }; + m = checkErrors(source, ""); + checkReferences(m, 5, 8, [TextPos(5,8), TextPos(6, 9)]); // var + source = q{ + bool isReserved(const(char)[] ident) + { + // more than 7 cases use dup + switch (ident) + { + case "DigitalMars": + case "GNU": + case "LDC": + case "SDC": + case "Windows": + case "Win32": + case "Win64": + case "linux": + case "OSX": + case "iOS": + case "TVOS": + case "WatchOS": + case "FreeBSD": + case "OpenBSD": + case "NetBSD": + case "DragonFlyBSD": + case "BSD": + case "Solaris": + return true; + default: + return false; + } + } + }; + m = checkErrors(source, ""); + + // change settings to restart everything + opts.unittestOn = false; + filename = "source2.d"; + m = checkErrors(source, ""); + // can object.d create reserved classes, e.g. Error? source = q{ module object; @@ -832,6 +889,7 @@ unittest }; m = checkErrors(source, ""); // beware: bad object.d after this point + lastContext = null; } unittest @@ -841,7 +899,6 @@ unittest import std.file; dmdInit(); - lastContext = null; string srcdir = "dmd/src"; diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 8d89e964..e8c50a5f 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -999,6 +999,10 @@ string tipForObject(RootObject obj, bool quote) string kind; if (t.isTypeIdentifier()) kind = "unresolved type"; + else if (auto tc = t.isTypeClass()) + kind = tc.sym.isInterfaceDeclaration() ? "interface" : "class"; + else if (auto ts = t.isTypeStruct()) + kind = ts.sym.isUnionDeclaration() ? "union" : "struct"; else kind = t.kind().to!string; string txt = "(" ~ kind ~ ") " ~ quoteCode(quote, t.toPrettyChars(true).to!string); @@ -1260,7 +1264,7 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) addIdent(loc, ident, TypeReferenceKind.GSharedVariable); } - void addType(ref const Loc loc, Type type, Type originalType) + void addType(Type type, Type originalType) { while (type && originalType && type.ty == originalType.ty) { @@ -1284,16 +1288,18 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) switch (t.ty) { case Tident: return TypeReferenceKind.TemplateTypeParameter; - case Tclass: return TypeReferenceKind.Class; - case Tstruct: return TypeReferenceKind.Struct; + case Tclass: return (cast(TypeClass)t).sym.isInterfaceDeclaration() ? TypeReferenceKind.Interface + : TypeReferenceKind.Class; + case Tstruct: return (cast(TypeStruct)t).sym.isUnionDeclaration() ? TypeReferenceKind.Union + : TypeReferenceKind.Struct; case Tenum: return TypeReferenceKind.Enum; default: return TypeReferenceKind.BasicType; } } if (originalType && originalType.ty == Tident && type) - addIdent(loc, (cast(TypeIdentifier) originalType).ident, refkind(type)); + addIdent((cast(TypeIdentifier) originalType).loc, (cast(TypeIdentifier) originalType).ident, refkind(type)); else if (type && type.ty == Tident) // not yet semantically analyzed (or a template declaration) - addIdent(loc, (cast(TypeIdentifier) type).ident, TypeReferenceKind.TemplateTypeParameter); + addIdent((cast(TypeIdentifier) type).loc, (cast(TypeIdentifier) type).ident, TypeReferenceKind.TemplateTypeParameter); } override void visit(Dsymbol sym) @@ -1346,9 +1352,9 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) override void visit(VarDeclaration decl) { - addType(decl.loc, decl.type, decl.originalType); + addType(decl.type, decl.originalType); if (decl.parsedType != decl.originalType) - addType(decl.loc, decl.type, decl.parsedType); + addType(decl.type, decl.parsedType); super.visit(decl); } @@ -1364,9 +1370,9 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) if (ne.member) ne.member.accept(this); - addType(ne.loc, ne.newtype, ne.parsedType); + addType(ne.newtype, ne.parsedType); if (ne.newtype != ne.parsedType) - addType(ne.loc, ne.newtype, ne.newtype); + addType(ne.newtype, ne.newtype); super.visit(ne); } @@ -1400,6 +1406,18 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) super.visit(ed); } + override void visit(FuncDeclaration decl) + { + super.visit(decl); + + if (decl.type) + { + auto ft = decl.type.isTypeFunction(); + auto ot = decl.originalType ? decl.originalType.isTypeFunction() : null; + addType(ft ? ft.nextOf() : null, ot ? ot.nextOf() : null); // the return type + } + } + override void visit(AggregateDeclaration ad) { if (ad.isInterfaceDeclaration) @@ -1412,6 +1430,15 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) addIdent(ad.loc, ad.ident, TypeReferenceKind.Struct); super.visit(ad); } + + override void visit(ClassDeclaration cd) + { + if (cd.baseclasses) + foreach (bc; *(cd.baseclasses)) + addType(bc.type, bc.parsedType); + + return super.visit(cd); + } } scope IdentifierTypesVisitor itv = new IdentifierTypesVisitor; @@ -1448,7 +1475,8 @@ Reference[] findReferencesInModule(Module mod, int line, int index) void addReference(ref const Loc loc, Identifier ident) { if (loc.filename && ident) - references ~= Reference(loc, ident); + if (!references.contains(Reference(loc, ident))) + references ~= Reference(loc, ident); } override void visit(Dsymbol sym) From 7265726b51104feadf3cf77b9584aa9f59ae59c5 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 2 Nov 2019 18:10:43 +0100 Subject: [PATCH 66/73] fix crash --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/dmdrmem.d | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index 88ac060c..5a3674fe 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit 88ac060ccad64d70769a2d59ffe98d11b3ea40eb +Subproject commit 5a3674fe2119a09cecb452b7881bd67bc6ebe5bc diff --git a/vdc/dmdserver/dmdrmem.d b/vdc/dmdserver/dmdrmem.d index feaaa199..539fc424 100644 --- a/vdc/dmdserver/dmdrmem.d +++ b/vdc/dmdserver/dmdrmem.d @@ -20,13 +20,13 @@ extern (C++) struct Mem static void* xmalloc(size_t n) nothrow pure { if (*pcancel) - throw *pcancelError; + throw new Error("cancel malloc"); //*pcancelError; return GC.malloc(n); } static void* xmalloc_noscan(size_t n) nothrow pure { if (*pcancel) - throw *pcancelError; + throw new Error("cancel malloc");//*pcancelError; return GC.malloc(n, GC.BlkAttr.NO_SCAN); } From c3f65b48e76ccd69eb6a9c02b18f5b8d5e8ca111 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 2 Nov 2019 18:13:26 +0100 Subject: [PATCH 67/73] basic DUB support: update and refresh if project contains dub.json or dub.sdl --- CHANGES | 2 ++ visuald/Resources/pkgcmd.vsct | 8 +++++++ visuald/build.d | 19 +++++++++++----- visuald/config.d | 41 +++++++++++++++-------------------- visuald/dproject.d | 17 +++++++++++++++ visuald/hierarchy.d | 9 +++++--- visuald/taskprovider.d | 2 ++ 7 files changed, 66 insertions(+), 32 deletions(-) diff --git a/CHANGES b/CHANGES index 2c8ffc7c..fa53fe41 100644 --- a/CHANGES +++ b/CHANGES @@ -1188,3 +1188,5 @@ unreleased Version 0.51.0 * added option to not show error squiggles and markers * added tooltip to collapsed region * fix function signature tool tips + * error list now filled with intellisense errors + * basic DUB support: update and refresh if project contains dub.json or dub.sdl diff --git a/visuald/Resources/pkgcmd.vsct b/visuald/Resources/pkgcmd.vsct index f1b47c22..34ba99aa 100644 --- a/visuald/Resources/pkgcmd.vsct +++ b/visuald/Resources/pkgcmd.vsct @@ -291,6 +291,14 @@ DUB Upgrade + @@ -297,6 +316,8 @@ + + $(VisualDMSBuildDir) pipelink.exe diff --git a/tools/pipedmd.d b/tools/pipedmd.d index adb57cd3..4cb2034b 100644 --- a/tools/pipedmd.d +++ b/tools/pipedmd.d @@ -71,12 +71,16 @@ string eatArg(string cmd) version(pipeLink) { + import core.stdc.stdlib : getenv; extern(C) int putenv(const char*); int main(string[] argv) { + const(char)* p = getenv("dbuild_LinkToolExe"); + string link = p ? fromMBSz(cast(immutable)p) : "link.exe"; + // printf("pipelink called with: dbuild_LinkToolExe=%s\n", p); string cmd = to!string(GetCommandLineW()); //printf("pipelink called with: %.*s\n", cast(int)cmd.length, cmd.ptr); - cmd = "link.exe" ~ eatArg(cmd); + cmd = link ~ eatArg(cmd); putenv("VS_UNICODE_OUTPUT="); // disable unicode output for link.exe int exitCode = runProcess(cmd, null, true, true, false, true, false); return exitCode; From 11c07b0f7d7014043f09125316e7e5594f3e866f Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 16 Nov 2019 14:43:23 +0100 Subject: [PATCH 70/73] dmdserver: fix evaluating TypeIdentifier, referencing manifest constant, some locs --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/semanalysis.d | 120 +++++++++++++++++++++++++++++++++-- vdc/dmdserver/semvisitor.d | 121 +++++++++++++++++++++++++++++++----- 3 files changed, 220 insertions(+), 23 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index 0d09345e..a7280476 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit 0d09345e0dff96d1d0a9bc70fa2c007962ad80d7 +Subproject commit a7280476c3531e1424fa57e8abce49cc9e81967d diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index 3b645156..e8d11547 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -541,6 +541,21 @@ unittest checkDefinition(m, 11, 16, "source.d", 6, 8); // fun checkDefinition(m, 15, 17, "source.d", 2, 9); // C + // enum value + source = + q{ // Line 1 + enum TTT = 9; + void fun() + { + int x = TTT; // Line 5 + } + }; + m = checkErrors(source, ""); + + checkTip(m, 2, 8, "(constant) `int source.TTT = 9`"); + checkTip(m, 5, 13, "(constant) `int source.TTT = 9`"); + + // template struct without instances source = q{ // Line 1 struct ST(T) @@ -782,7 +797,7 @@ unittest } }; m = checkErrors(source, ""); - dumpAST(m); + //dumpAST(m); checkTip(m, 6, 9, "(foreach variable) `object.ModuleInfo* m`"); checkTip(m, 5, 12, "(foreach variable) `object.ModuleInfo* m`"); checkTip(m, 5, 15, "(module) `object`"); @@ -861,6 +876,89 @@ unittest }; m = checkErrors(source, ""); checkReferences(m, 5, 8, [TextPos(5,8), TextPos(6, 9)]); // var + + // check position of var in AddrExp + source = q{ + struct S { int x = 3; } + void fun(T)(T* p) {} + void foo() + { + S var; // Line 6 + fun!(S)(&var); + } + }; + m = checkErrors(source, ""); + + checkTip(m, 7, 9, "(struct) `source.S`"); + + // check template arguments + source = q{ + void fun(T)() {} + void foo() + { + fun!(object.ModuleInfo)(); // Line 5 + } + }; + m = checkErrors(source, ""); + + checkTip(m, 5, 9, "(module) `object`"); + checkTip(m, 5, 16, "(struct) `object.ModuleInfo`"); + + exp2 = [ + "fun": [ IdTypePos(TypeReferenceKind.Function) ], + "foo": [ IdTypePos(TypeReferenceKind.Function) ], + "object": [ IdTypePos(TypeReferenceKind.Module) ], + "ModuleInfo": [ IdTypePos(TypeReferenceKind.Struct) ], + ]; + checkIdentifierTypes(m, exp2); + + // check FQN types in cast + source = q{ + void foo() + { + auto e = cast(object.Exception) null; + auto p = cast(object.Exception*) null; // Line 5 + } + }; + m = checkErrors(source, ""); + //dumpAST(m); + + checkTip(m, 4, 18, "(module) `object`"); + checkTip(m, 4, 25, "(class) `object.Exception`"); + checkTip(m, 5, 18, "(module) `object`"); + checkTip(m, 5, 25, "(class) `object.Exception`"); + + exp2 = [ + "foo": [ IdTypePos(TypeReferenceKind.Function) ], + "object": [ IdTypePos(TypeReferenceKind.Module) ], + "Exception": [ IdTypePos(TypeReferenceKind.Class) ], + "e": [ IdTypePos(TypeReferenceKind.LocalVariable) ], + "p": [ IdTypePos(TypeReferenceKind.LocalVariable) ], + ]; + checkIdentifierTypes(m, exp2); + + // fqn, function call on static members + source = q{ + struct Mem + { + static Mem foo(int sz) { return Mem(); } + } // Line 5 + __gshared Mem mem; + void fun() + { + source.Mem m = source.mem.foo(1234); + } // Line 10 + }; + m = checkErrors(source, ""); + //dumpAST(m); + + checkTip(m, 9, 30, "`Mem source.Mem.foo(int sz)`"); + checkTip(m, 9, 19, "(module) `source`"); + checkTip(m, 9, 26, "(__gshared variable) `source.Mem source.mem`"); + checkTip(m, 9, 11, "(struct) `source.Mem`"); + checkTip(m, 9, 4, "(module) `source`"); + + /////////////////////////////////////////////////////////// // check array initializer filename = "tok.d"; source = q{ @@ -949,6 +1047,7 @@ unittest ]; checkIdentifierTypes(m, exp3); + // more than 7 cases translated to table source = q{ bool isReserved(const(char)[] ident) { @@ -1058,10 +1157,21 @@ unittest } // https://issues.dlang.org/show_bug.cgi?id=20253 +enum TTT = 9; void dummy() { - enum string s1 = "int xx;"; - enum string s2 = "int yy;"; - mixin(s1, s2); - int t = xx + yy; + import std.file; + std.file.read(""); // no tip on std and file + auto x = TTT; +} + +struct XMem +{ + static XMem foo(int sz) { return XMem(); } +} +__gshared XMem xmem; + +void fun() +{ + vdc.dmdserver.semanalysis.XMem m = vdc.dmdserver.semanalysis.xmem.foo(1234); } diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index c55d39ae..15c43d85 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -54,6 +54,7 @@ import dmd.root.filename; import dmd.root.rmem; import dmd.root.rootobject; +import std.algorithm; import std.string; import std.conv; import stdext.array; @@ -587,7 +588,7 @@ extern(C++) class FindASTVisitor : ASTVisitor override void visit(CastExp expr) { - visitTypeIdentifier(expr.parsedTo, expr.to); + visitTypeIdentifier(expr.parsedTo, expr.to, true); if (expr.parsedTo != expr.to) visitTypeIdentifier(expr.to, expr.to); super.visit(expr); @@ -687,6 +688,22 @@ extern(C++) class FindASTVisitor : ASTVisitor super.visit(expr); } + override void visit(ScopeExp expr) + { + if (auto ti = expr.sds.isTemplateInstance()) + { + if (ti.tiargs && ti.parsedArgs) + { + size_t args = min(ti.tiargs.dim, ti.parsedArgs.dim); + for (size_t a = 0; a < args; a++) + if (Type tip = (*ti.parsedArgs)[a].isType()) + if (Type tir = (*ti.tiargs)[a].isType()) + visitTypeIdentifier(tip, tir); + } + } + super.visit(expr); + } + override void visit(SymbolExp expr) { if (!found && expr.var) @@ -776,7 +793,7 @@ extern(C++) class FindASTVisitor : ASTVisitor override void visit(VarDeclaration decl) { - visitTypeIdentifier(decl.parsedType, decl.type); + visitTypeIdentifier(decl.parsedType, decl.type, true); if (!found && decl.originalType != decl.parsedType) visitTypeIdentifier(decl.originalType, decl.type); if (!found && decl.type != decl.originalType && decl.type != decl.parsedType) @@ -824,7 +841,7 @@ extern(C++) class FindASTVisitor : ASTVisitor visitTypeIdentifier(decl.originalType, decl.type); } - void visitTypeIdentifier(Type originalType, Type resolvedType) + void visitTypeIdentifier(Type originalType, Type resolvedType, bool syntaxCopiedOriginal = false) { if (found || !originalType || !resolvedType) return; @@ -866,23 +883,30 @@ extern(C++) class FindASTVisitor : ASTVisitor } } auto otype = cast(TypeIdentifier) originalType; + if (otype.copiedFrom && syntaxCopiedOriginal) + otype = otype.copiedFrom; Loc loc = otype.loc; if (matchIdentifier(loc, otype.ident)) { - foundNode(resolvedType); + if (otype.parentScopes.dim > 0) + foundNode(otype.parentScopes[0]); + else + foundNode(resolvedType); } else { // guess qualified name to be without spaces - loc.charnum += otype.ident.toString().length + 1; - foreach (id; otype.idents) + foreach (i, id; otype.idents) { - if (id.dyncast() == DYNCAST.identifier) + RootObject obj = id; + if (obj.dyncast() == DYNCAST.identifier) { - auto ident = cast(Identifier)id; - if (matchIdentifier(loc, ident)) - foundNode(resolvedType); - loc.charnum += ident.toString().length + 1; + auto ident = cast(Identifier)obj; + if (matchIdentifier(id.loc, ident)) + if (otype.parentScopes.dim > i + 1) + foundNode(otype.parentScopes[i + 1]); + else + foundNode(resolvedType); } } } @@ -1066,6 +1090,9 @@ string tipForObject(RootObject obj, bool quote) } else if (auto s = obj.isDsymbol()) { + if (auto imp = s.isImport()) + if (imp.mod) + s = imp.mod; if (auto decl = s.isDeclaration()) tip = tipForDeclaration(decl); else @@ -1293,7 +1320,7 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) addIdent(loc, ident, TypeReferenceKind.GSharedVariable); } - void addType(Type type, Type originalType) + void addType(Type type, Type originalType, bool syntaxCopiedOriginal = false) { while (type && originalType && (type.ty == originalType.ty || (originalType.ty == Taarray && type.ty == Tsarray))) @@ -1310,7 +1337,7 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) { auto originalAA = cast(TypeAArray) originalType; auto resolvedAA = cast(TypeAArray) type; - addType(resolvedAA.index, originalAA.index); + addType(resolvedAA.index, originalAA.index, syntaxCopiedOriginal); goto case Tarray; } case Tarray: @@ -1338,10 +1365,48 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) default: return TypeReferenceKind.BasicType; } } + void addTypeIdentifier(TypeIdentifier tid, Type resolvedType) + { + if (tid.copiedFrom && syntaxCopiedOriginal) + tid = tid.copiedFrom; + if (tid.parentScopes.dim > 0) + addObject(tid.loc, tid.parentScopes[0]); + else + addIdent(tid.loc, tid.ident, refkind(resolvedType)); + + foreach (i, id; tid.idents) + { + RootObject obj = id; + if (obj.dyncast() == DYNCAST.identifier) + { + auto ident = cast(Identifier)obj; + if (tid.parentScopes.dim > i + 1) + addObject(id.loc, tid.parentScopes[i + 1]); + else + addIdent(id.loc, id, refkind(resolvedType)); + } + } + } + if (originalType && originalType.ty == Tident && type) - addIdent((cast(TypeIdentifier) originalType).loc, (cast(TypeIdentifier) originalType).ident, refkind(type)); + addTypeIdentifier(cast(TypeIdentifier) originalType, type); else if (type && type.ty == Tident) // not yet semantically analyzed (or a template declaration) - addIdent((cast(TypeIdentifier) type).loc, (cast(TypeIdentifier) type).ident, TypeReferenceKind.TemplateTypeParameter); + addTypeIdentifier(cast(TypeIdentifier) type, type); + } + + void addObject(ref const Loc loc, RootObject obj) + { + if (auto t = obj.isType()) + addType(t, t); + else if (auto s = obj.isDsymbol()) + { + if (auto imp = s.isImport()) + if (imp.mod) + s = imp.mod; + addSymbol(loc, s); + } + else if (auto e = obj.isExpression()) + e.accept(this); } void addSymbol(ref const Loc loc, Dsymbol sym) @@ -1405,7 +1470,7 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) { addType(decl.type, decl.originalType); if (decl.parsedType != decl.originalType) - addType(decl.type, decl.parsedType); + addType(decl.type, decl.parsedType, true); super.visit(decl); } @@ -1421,7 +1486,7 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) if (ne.member) ne.member.accept(this); - addType(ne.newtype, ne.parsedType); + addType(ne.newtype, ne.parsedType, true); if (ne.newtype != ne.parsedType) addType(ne.newtype, ne.newtype); @@ -1475,6 +1540,28 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) super.visit(dve); } + override void visit(ScopeExp expr) + { + if (auto ti = expr.sds.isTemplateInstance()) + { + if (ti.tiargs && ti.parsedArgs) + { + size_t args = min(ti.tiargs.dim, ti.parsedArgs.dim); + for (size_t a = 0; a < args; a++) + if (Type tip = (*ti.parsedArgs)[a].isType()) + if (Type tir = (*ti.tiargs)[a].isType()) + addType(tir, tip); + } + } + super.visit(expr); + } + + override void visit(CastExp expr) + { + addType(expr.to, expr.parsedTo, true); + super.visit(expr); + } + override void visit(EnumDeclaration ed) { addIdent(ed.loc, ed.ident, TypeReferenceKind.Enum); From d94d76b9ff4cf7a9a343c0e28ce29d0e21f606fc Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 17 Nov 2019 15:24:28 +0100 Subject: [PATCH 71/73] implement builtin properties --- vdc/dmdserver/dmd | 2 +- vdc/dmdserver/semanalysis.d | 52 ++++++++++++++++++------- vdc/dmdserver/semvisitor.d | 77 ++++++++++++++++++++++++++++++++++--- 3 files changed, 112 insertions(+), 19 deletions(-) diff --git a/vdc/dmdserver/dmd b/vdc/dmdserver/dmd index a7280476..5e821dfe 160000 --- a/vdc/dmdserver/dmd +++ b/vdc/dmdserver/dmd @@ -1 +1 @@ -Subproject commit a7280476c3531e1424fa57e8abce49cc9e81967d +Subproject commit 5e821dfe2d697ffe9336c064d4536db69c6c0511 diff --git a/vdc/dmdserver/semanalysis.d b/vdc/dmdserver/semanalysis.d index e8d11547..c39d219c 100644 --- a/vdc/dmdserver/semanalysis.d +++ b/vdc/dmdserver/semanalysis.d @@ -745,7 +745,7 @@ unittest checkTip(m, 30, 10, "(class) `object.TypeInfo_Class`"); checkTip(m, 30, 25, "(enum) `object.TypeInfo_Class.ClassFlags`"); checkTip(m, 30, 36, "(enum value) `object.TypeInfo_Class.ClassFlags.isCOMclass = 1u`"); - //checkTip(m, 20, 41, "(constant) `source.RightBase.sizeof = 8`"); + checkTip(m, 21, 43, "(constant) `ulong source.RightBase.sizeof = 8LU`"); IdTypePos[][string] exp2 = [ "size_t": [ IdTypePos(TypeReferenceKind.BasicType) ], @@ -770,6 +770,7 @@ unittest "stdc": [ IdTypePos(TypeReferenceKind.Package) ], "config": [ IdTypePos(TypeReferenceKind.Module) ], "c_long": [ IdTypePos(TypeReferenceKind.BasicType) ], + "sizeof": [ IdTypePos(TypeReferenceKind.Constant) ], ]; checkIdentifierTypes(m, exp2); @@ -1019,20 +1020,28 @@ unittest 1 : TypeInfo_Class.ClassFlags.isCOMclass ]; int[] iarr = [ TypeInfo_Class.ClassFlags.noPointers : 1 ]; + void fun() + { // Line 10 + auto a = darr.length + aarr.length; + auto p = darr.ptr; + } }; m = checkErrors(source, ""); - checkTip(m, 2, 18, "(class) `object.TypeInfo_Class`"); - checkTip(m, 2, 33, "(enum) `object.TypeInfo_Class.ClassFlags`"); - checkTip(m, 2, 44, "(enum value) `object.TypeInfo_Class.ClassFlags.isCOMclass = 1u`"); - checkTip(m, 5, 4, "(class) `object.TypeInfo_Class`"); - checkTip(m, 5, 19, "(enum) `object.TypeInfo_Class.ClassFlags`"); - checkTip(m, 5, 30, "(enum value) `object.TypeInfo_Class.ClassFlags.isCOMclass = 1u`"); - checkTip(m, 6, 8, "(class) `object.TypeInfo_Class`"); - checkTip(m, 6, 23, "(enum) `object.TypeInfo_Class.ClassFlags`"); - checkTip(m, 6, 34, "(enum value) `object.TypeInfo_Class.ClassFlags.isCOMclass = 1u`"); - checkTip(m, 8, 18, "(class) `object.TypeInfo_Class`"); - checkTip(m, 8, 33, "(enum) `object.TypeInfo_Class.ClassFlags`"); - checkTip(m, 8, 44, "(enum value) `object.TypeInfo_Class.ClassFlags.noPointers = 2u`"); + checkTip(m, 2, 18, "(class) `object.TypeInfo_Class`"); + checkTip(m, 2, 33, "(enum) `object.TypeInfo_Class.ClassFlags`"); + checkTip(m, 2, 44, "(enum value) `object.TypeInfo_Class.ClassFlags.isCOMclass = 1u`"); + checkTip(m, 5, 4, "(class) `object.TypeInfo_Class`"); + checkTip(m, 5, 19, "(enum) `object.TypeInfo_Class.ClassFlags`"); + checkTip(m, 5, 30, "(enum value) `object.TypeInfo_Class.ClassFlags.isCOMclass = 1u`"); + checkTip(m, 6, 8, "(class) `object.TypeInfo_Class`"); + checkTip(m, 6, 23, "(enum) `object.TypeInfo_Class.ClassFlags`"); + checkTip(m, 6, 34, "(enum value) `object.TypeInfo_Class.ClassFlags.isCOMclass = 1u`"); + checkTip(m, 8, 18, "(class) `object.TypeInfo_Class`"); + checkTip(m, 8, 33, "(enum) `object.TypeInfo_Class.ClassFlags`"); + checkTip(m, 8, 44, "(enum value) `object.TypeInfo_Class.ClassFlags.noPointers = 2u`"); + checkTip(m, 11, 18, "(field) `ulong int[].length`"); + checkTip(m, 11, 32, "(field) `ulong int[int].length`"); + checkTip(m, 12, 18, "(field) `int* int[].ptr`"); checkReferences(m, 2, 44, [TextPos(2,44), TextPos(5, 30), TextPos(6, 34)]); // isCOMclass @@ -1044,6 +1053,11 @@ unittest "darr": [ IdTypePos(TypeReferenceKind.TLSVariable) ], "aarr": [ IdTypePos(TypeReferenceKind.TLSVariable) ], "iarr": [ IdTypePos(TypeReferenceKind.TLSVariable) ], + "fun": [ IdTypePos(TypeReferenceKind.Function) ], + "length": [ IdTypePos(TypeReferenceKind.MemberVariable) ], + "ptr": [ IdTypePos(TypeReferenceKind.MemberVariable) ], + "a": [ IdTypePos(TypeReferenceKind.LocalVariable) ], + "p": [ IdTypePos(TypeReferenceKind.LocalVariable) ], ]; checkIdentifierTypes(m, exp3); @@ -1163,6 +1177,18 @@ void dummy() import std.file; std.file.read(""); // no tip on std and file auto x = TTT; + int[] arr; + auto s = arr.ptr; + auto y = arr.length; + auto my = arr.mangleof; + auto zi = size_t.init; + auto z0 = size_t.min; + auto z1 = size_t.max; + auto z2 = size_t.alignof; + auto z3 = size_t.stringof; + float flt; + auto q = [flt.sizeof, flt.init, flt.epsilon, flt.mant_dig, flt.infinity, flt.re, flt.min_normal, flt.min_10_exp]; + auto ti = Object.classinfo; } struct XMem diff --git a/vdc/dmdserver/semvisitor.d b/vdc/dmdserver/semvisitor.d index 15c43d85..b03c99c5 100644 --- a/vdc/dmdserver/semvisitor.d +++ b/vdc/dmdserver/semvisitor.d @@ -1064,6 +1064,29 @@ string tipForObject(RootObject obj, bool quote) doc = sym.comment; return txt; } + string tipForDotIdExp(DotIdExp die) + { + bool isConstant = die.original.isConstantExpr(); + Expression e1; + if (!isConstant && !die.original.isArrayLengthExp() && die.type) + { + e1 = isAALenCall(die.original); + if (!e1 && die.ident == Id.ptr && die.original.isCastExp()) + e1 = die.original; + if (!e1) + return tipForType(die.type); + } + if (!e1) + e1 = die.e1; + string tip = isConstant ? "(constant) `" : "(field) `"; + tip ~= die.original.type.toPrettyChars(true).to!string ~ " "; + tip ~= e1.type ? die.e1.type.toPrettyChars(true).to!string : e1.toString(); + tip ~= "." ~ die.ident.toString(); + if (isConstant) + tip ~= " = " ~ die.original.toString(); + tip ~= "`"; + return tip; + } if (auto t = obj.isType()) { @@ -1082,6 +1105,13 @@ string tipForObject(RootObject obj, bool quote) tip = tipForDeclaration((cast(DotVarExp)e).var); doc = (cast(DotVarExp)e).var.comment; break; + case TOK.dotIdentifier: + if (e.original && e.original.type) + { + tip = tipForDotIdExp(e.isDotIdExp()); + break; + } + goto default; default: if (e.type) toc = tipForType(e.type); @@ -1525,11 +1555,13 @@ FindIdentifierTypesResult findIdentifierTypes(Module mod) override void visit(DotIdExp expr) { -// if (expr.type) -// addIdentByType(expr.identloc, expr.ident, expr.type); -// else if (expr.original && expr.original.type) -// addIdentByType(expr.identloc, expr.ident, expr.original.type); -// else + auto orig = expr.original; + if (orig && orig.type && orig.isConstantExpr()) + addIdent(expr.identloc, expr.ident, TypeReferenceKind.Constant); + else if (orig && orig.type && + (orig.isArrayLengthExp() || orig.isAALenCall() || (expr.ident == Id.ptr && orig.isCastExp()))) + addIdent(expr.identloc, expr.ident, TypeReferenceKind.MemberVariable); + else super.visit(expr); } @@ -1796,6 +1828,41 @@ string[] findExpansions(Module mod, int line, int index, string tok) //////////////////////////////////////////////////////////////////////////////// +bool isConstantExpr(Expression expr) +{ + switch(expr.op) + { + case TOK.int64, TOK.float64, TOK.char_, TOK.complex80: + case TOK.null_, TOK.void_: + case TOK.string_: + case TOK.arrayLiteral, TOK.assocArrayLiteral, TOK.structLiteral: + case TOK.classReference: + //case TOK.type: + case TOK.vector: + case TOK.function_, TOK.delegate_: + case TOK.symbolOffset, TOK.address: + case TOK.typeid_: + case TOK.slice: + return true; + default: + return false; + } +} + +// return first argument to aaLen() +Expression isAALenCall(Expression expr) +{ + // unpack first argument of _aaLen(aa) + if (auto ce = expr.isCallExp()) + if (auto ve = ce.e1.isVarExp()) + if (ve.var.ident is Id.aaLen) + if (ce.arguments && ce.arguments.dim > 0) + return (*ce.arguments)[0]; + return null; +} + +//////////////////////////////////////////////////////////////////////////////// + ScopeDsymbol typeSymbol(Type type) { if (auto ts = type.isTypeStruct()) From 6aaeec680c4d33e1b626be40b539ff9db59540b0 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 17 Nov 2019 17:27:38 +0100 Subject: [PATCH 72/73] fix signature tooltips --- visuald/viewfilter.d | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/visuald/viewfilter.d b/visuald/viewfilter.d index 90be13f2..26b6a787 100644 --- a/visuald/viewfilter.d +++ b/visuald/viewfilter.d @@ -1667,17 +1667,8 @@ else return S_FALSE; goto stepUp; } -version(none) -{ span.iStartIndex = idx; span.iStartLine = line; -} -else -{ - // use caret after opening parenthesis - span.iStartIndex = otherIndex + 1; - span.iStartLine = otherLine; -} span.iEndIndex = span.iStartIndex + 1; span.iEndLine = span.iStartLine; @@ -1714,6 +1705,8 @@ else fn = fn[0..$-1]; if(fn.endsWith(":")) fn = fn[0..$-1]; + if (fn.endsWith("`") && fn.indexOf('`') < fn.length - 1) + fn = fn[fn.indexOf('`')+1..$-1]; def.setType(fn); defs ~= def; } From 43dd53078805f3a8bd98f261c3fd6a2dd8e17fbe Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sun, 17 Nov 2019 18:26:53 +0100 Subject: [PATCH 73/73] bump version to 0.51.0-beta1 --- CHANGES | 6 ++++-- VERSION | 2 +- nsis/visuald.nsi | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index fa53fe41..ae0d0bea 100644 --- a/CHANGES +++ b/CHANGES @@ -1184,9 +1184,11 @@ unreleased Version 0.51.0 - new option: "remove leading zeroes from hex values" - fix crash expanding pointer to empty dynamic array - large arrays: show growing index, fix omitting last element - * dparser: now creates server process per Visual Studio Instance + * installer: add sections for "Build Tools VS2017/2019"" + * dparser: now creates server process per Visual Studio instance * added option to not show error squiggles and markers * added tooltip to collapsed region * fix function signature tool tips * error list now filled with intellisense errors - * basic DUB support: update and refresh if project contains dub.json or dub.sdl + * basic DUB support: upgrade and refresh if project contains dub.json or dub.sdl + * msbuild: pass original variable LinkToolExe to pipelink.exe through environment \ No newline at end of file diff --git a/VERSION b/VERSION index e4dee504..a70f9852 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ #define VERSION_MAJOR 0 #define VERSION_MINOR 51 #define VERSION_REVISION 0 -#define VERSION_BETA -alpha +#define VERSION_BETA -beta #define VERSION_BUILD 1 diff --git a/nsis/visuald.nsi b/nsis/visuald.nsi index 885b3399..38ecc040 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.087.1" +!define DMD_VERSION "2.089.0" !define DMD_SRC c:\d\dmd-${DMD_VERSION} ; define LDC to include ldc installation ; !define LDC -!define LDC_VERSION "1.17.0" +!define LDC_VERSION "1.18.0" !define LDC_SRC c:\d\ldc2-${LDC_VERSION}-windows-multilib ; define VS2019 to include VS2019 support