From a20a318e259cc1c250de5fe07174394b9881df43 Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Wed, 23 Nov 2022 17:45:43 +0100 Subject: [PATCH 1/5] test implementation of includes paths for syntax --- .../Core/Parser/AbstractCodeParser.cs | 14 ++++++++++++- VSRAD.Syntax/Core/Parser/Asm1Parser.cs | 8 ++++--- VSRAD.Syntax/Core/Parser/Asm2Parser.cs | 8 ++++--- VSRAD.Syntax/Options/GeneralOptionProvider.cs | 2 ++ VSRAD.Syntax/Options/GeneralOptions.cs | 21 ++++++++++++++++++- 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs b/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs index b5693c692..2313bba28 100644 --- a/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs +++ b/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs @@ -20,12 +20,14 @@ internal abstract class AbstractCodeParser : IParser private readonly IDocumentFactory _documentFactory; private readonly AsmType _asmType; private HashSet _instructions; + private IReadOnlyList _includes; - protected AbstractCodeParser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, AsmType asmType) + protected AbstractCodeParser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes, AsmType asmType) { _asmType = asmType; _documentFactory = documentFactory; _instructions = new HashSet(); + _includes = includes; OtherInstructions = new HashSet(); instructionListManager.InstructionsUpdated += InstructionsUpdated; @@ -63,6 +65,16 @@ protected async Task AddExternalDefinitionsAsync(string path, TrackingToken incl var externalFilePath = Path.Combine(Path.GetDirectoryName(path), externalFileName); var externalDocument = _documentFactory.GetOrCreateDocument(externalFilePath); + if (externalDocument == null) + { + foreach(var curPath in _includes) + { + externalFilePath = Path.Combine(curPath, externalFileName); + externalDocument = _documentFactory.GetOrCreateDocument(externalFilePath); + if (externalDocument != null) break; + } + } + if (externalDocument != null) { var externalDocumentAnalysis = externalDocument.DocumentAnalysis; diff --git a/VSRAD.Syntax/Core/Parser/Asm1Parser.cs b/VSRAD.Syntax/Core/Parser/Asm1Parser.cs index 060325be2..81f440d30 100644 --- a/VSRAD.Syntax/Core/Parser/Asm1Parser.cs +++ b/VSRAD.Syntax/Core/Parser/Asm1Parser.cs @@ -11,6 +11,7 @@ using VSRAD.Syntax.Helpers; using VSRAD.Syntax.Options.Instructions; using VSRAD.SyntaxParser; +using VSRAD.Syntax.Options; namespace VSRAD.Syntax.Core.Parser { @@ -23,12 +24,13 @@ internal sealed class Asm1Parser : AbstractCodeParser var serviceProvider = ServiceProvider.GlobalProvider; var documentFactory = serviceProvider.GetMefService(); var instructionListManager = serviceProvider.GetMefService(); + var options = serviceProvider.GetMefService(); - return new Asm1Parser(documentFactory, instructionListManager); + return new Asm1Parser(documentFactory, instructionListManager, options.IncludePaths); }); - private Asm1Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager) - : base(documentFactory, instructionListManager, AsmType.RadAsm) { } + private Asm1Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes) + : base(documentFactory, instructionListManager, includes, AsmType.RadAsm) { } public override Task RunAsync(IDocument document, ITextSnapshot version, ITokenizerCollection trackingTokens, CancellationToken cancellation) diff --git a/VSRAD.Syntax/Core/Parser/Asm2Parser.cs b/VSRAD.Syntax/Core/Parser/Asm2Parser.cs index a1cf47596..894975a05 100644 --- a/VSRAD.Syntax/Core/Parser/Asm2Parser.cs +++ b/VSRAD.Syntax/Core/Parser/Asm2Parser.cs @@ -11,6 +11,7 @@ using VSRAD.Syntax.Helpers; using VSRAD.Syntax.Options.Instructions; using VSRAD.SyntaxParser; +using VSRAD.Syntax.Options; namespace VSRAD.Syntax.Core.Parser { @@ -23,12 +24,13 @@ internal sealed class Asm2Parser : AbstractCodeParser var serviceProvider = ServiceProvider.GlobalProvider; var documentFactory = serviceProvider.GetMefService(); var instructionListManager = serviceProvider.GetMefService(); + var options = serviceProvider.GetMefService(); - return new Asm2Parser(documentFactory, instructionListManager); + return new Asm2Parser(documentFactory, instructionListManager, options.IncludePaths); }); - private Asm2Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager) - : base(documentFactory, instructionListManager, AsmType.RadAsm2) { } + private Asm2Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes) + : base(documentFactory, instructionListManager, includes, AsmType.RadAsm2) { } public override Task RunAsync(IDocument document, ITextSnapshot version, ITokenizerCollection trackingTokens, CancellationToken cancellation) diff --git a/VSRAD.Syntax/Options/GeneralOptionProvider.cs b/VSRAD.Syntax/Options/GeneralOptionProvider.cs index a4ddcfb45..51c632caa 100644 --- a/VSRAD.Syntax/Options/GeneralOptionProvider.cs +++ b/VSRAD.Syntax/Options/GeneralOptionProvider.cs @@ -31,6 +31,7 @@ public OptionsProvider() Asm1FileExtensions = Constants.DefaultFileExtensionAsm1; Asm2FileExtensions = Constants.DefaultFileExtensionAsm2; InstructionsPaths = GetDefaultInstructionDirectoryPath(); + IncludePaths = new List(); Asm1InstructionSet = string.Empty; Asm2InstructionSet = string.Empty; AutocompleteInstructions = false; @@ -50,6 +51,7 @@ public OptionsProvider() public IReadOnlyList Asm1FileExtensions; public IReadOnlyList Asm2FileExtensions; public string InstructionsPaths; + public IReadOnlyList IncludePaths; public string Asm1InstructionSet; public string Asm2InstructionSet; public bool AutocompleteInstructions; diff --git a/VSRAD.Syntax/Options/GeneralOptions.cs b/VSRAD.Syntax/Options/GeneralOptions.cs index 17c94d61e..8948fb003 100644 --- a/VSRAD.Syntax/Options/GeneralOptions.cs +++ b/VSRAD.Syntax/Options/GeneralOptions.cs @@ -80,7 +80,7 @@ public string Asm2FileExtensions [Category("Instructions")] [DisplayName("Instruction folder paths")] - [Description("List of folder path separated by semicolon wit assembly instructions with .radasm file extension")] + [Description("List of folder paths separated by semicolon with assembly instructions with .radasm file extension")] [Editor(typeof(FolderPathsEditor), typeof(System.Drawing.Design.UITypeEditor))] public string InstructionsPaths { @@ -88,6 +88,16 @@ public string InstructionsPaths set => _optionsProvider.InstructionsPaths = value; } + [Category("Instructions")] + [DisplayName("Include paths")] + [Description("List of folder paths separated by semicolon that contains sources to be included")] + [Editor(typeof(FolderPathsEditor), typeof(System.Drawing.Design.UITypeEditor))] + public string IncludePaths + { + get => ConvertExtensionsTo(_optionsProvider.IncludePaths); + set => _optionsProvider.IncludePaths = ConvertExtensionsFrom(value); + } + [Category("Instructions")] [DisplayName("Asm1 selected set")] [Browsable(false)] @@ -156,6 +166,10 @@ public override async Task LoadAsync() InstructionsPaths = userSettingsStore.PropertyExists(InstructionCollectionName, nameof(InstructionsPaths)) ? userSettingsStore.GetString(InstructionCollectionName, nameof(InstructionsPaths)) : OptionsProvider.GetDefaultInstructionDirectoryPath(); + + IncludePaths = userSettingsStore.PropertyExists(InstructionCollectionName, nameof(IncludePaths)) + ? userSettingsStore.GetString(InstructionCollectionName, nameof(IncludePaths)) + : string.Empty; } public override async Task SaveAsync() @@ -174,6 +188,11 @@ public override async Task SaveAsync() { userSettingsStore.SetString(InstructionCollectionName, nameof(InstructionsPaths), InstructionsPaths); } + + if (!string.IsNullOrEmpty(IncludePaths)) + { + userSettingsStore.SetString(InstructionCollectionName, nameof(IncludePaths), IncludePaths); + } } private static IReadOnlyList ConvertExtensionsFrom(string str) => From 244e78726195027cec3d84beb674e68ec47de1b3 Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Thu, 15 Dec 2022 19:55:53 +0100 Subject: [PATCH 2/5] added single definition container (MVP) (asm2 only) --- .../Core/Parser/AbstractCodeParser.cs | 7 ++-- VSRAD.Syntax/Core/Parser/Asm1Parser.cs | 2 +- VSRAD.Syntax/Core/Parser/Asm2Parser.cs | 34 ++++++++++--------- .../Core/Parser/DefinitionContainer.cs | 2 ++ 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs b/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs index 2313bba28..c09578588 100644 --- a/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs +++ b/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs @@ -21,13 +21,16 @@ internal abstract class AbstractCodeParser : IParser private readonly AsmType _asmType; private HashSet _instructions; private IReadOnlyList _includes; + protected DefinitionContainer _container; - protected AbstractCodeParser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes, AsmType asmType) + protected AbstractCodeParser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, + IReadOnlyList includes, DefinitionContainer container, AsmType asmType) { _asmType = asmType; _documentFactory = documentFactory; _instructions = new HashSet(); _includes = includes; + _container = container; OtherInstructions = new HashSet(); instructionListManager.InstructionsUpdated += InstructionsUpdated; @@ -83,7 +86,7 @@ protected async Task AddExternalDefinitionsAsync(string path, TrackingToken incl .ConfigureAwait(false); foreach (var externalDefinition in externalAnalysisResult.GetGlobalDefinitions()) - definitionContainer.Add(block, externalDefinition); + _container.Add(block, externalDefinition); } } catch (Exception e) when (e is ArgumentException || e is FileNotFoundException) { /* invalid path */ } diff --git a/VSRAD.Syntax/Core/Parser/Asm1Parser.cs b/VSRAD.Syntax/Core/Parser/Asm1Parser.cs index 81f440d30..fc924bde2 100644 --- a/VSRAD.Syntax/Core/Parser/Asm1Parser.cs +++ b/VSRAD.Syntax/Core/Parser/Asm1Parser.cs @@ -30,7 +30,7 @@ internal sealed class Asm1Parser : AbstractCodeParser }); private Asm1Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes) - : base(documentFactory, instructionListManager, includes, AsmType.RadAsm) { } + : base(documentFactory, instructionListManager, includes, null, AsmType.RadAsm) { } public override Task RunAsync(IDocument document, ITextSnapshot version, ITokenizerCollection trackingTokens, CancellationToken cancellation) diff --git a/VSRAD.Syntax/Core/Parser/Asm2Parser.cs b/VSRAD.Syntax/Core/Parser/Asm2Parser.cs index 894975a05..ebc228c73 100644 --- a/VSRAD.Syntax/Core/Parser/Asm2Parser.cs +++ b/VSRAD.Syntax/Core/Parser/Asm2Parser.cs @@ -25,12 +25,14 @@ internal sealed class Asm2Parser : AbstractCodeParser var documentFactory = serviceProvider.GetMefService(); var instructionListManager = serviceProvider.GetMefService(); var options = serviceProvider.GetMefService(); + var container = serviceProvider.GetMefService(); - return new Asm2Parser(documentFactory, instructionListManager, options.IncludePaths); + return new Asm2Parser(documentFactory, instructionListManager, options.IncludePaths, container); }); - private Asm2Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes) - : base(documentFactory, instructionListManager, includes, AsmType.RadAsm2) { } + private Asm2Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes, + DefinitionContainer container) + : base(documentFactory, instructionListManager, includes, container, AsmType.RadAsm2) { } public override Task RunAsync(IDocument document, ITextSnapshot version, ITokenizerCollection trackingTokens, CancellationToken cancellation) @@ -56,7 +58,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v .WithCancellation(cancellation) .ToArray(); - var definitionContainer = new DefinitionContainer(); + //var definitionContainer = new DefinitionContainer(); var referenceCandidates = new LinkedList<(string text, TrackingToken trackingToken, IBlock block)>(); var blocks = new List(); @@ -110,7 +112,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v && tokens[i + 3].Type == RadAsm2Lexer.EOL) { var labelDefinition = new DefinitionToken(RadAsmTokenType.Label, tokens[i + 1], version); - definitionContainer.Add(currentBlock, labelDefinition); + _container.Add(currentBlock, labelDefinition); currentBlock.AddToken(labelDefinition); i += 2; } @@ -122,7 +124,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v if (tokens[i + 2].Type == RadAsm2Lexer.EOL) { var funcDefinition = new DefinitionToken(RadAsmTokenType.FunctionName, tokens[i + 1], version); - definitionContainer.Add(currentBlock, funcDefinition); + _container.Add(currentBlock, funcDefinition); currentBlock = blocks.AppendBlock(new FunctionBlock(currentBlock, BlockType.Function, token, funcDefinition)); currentBlock.SetStart(tokens[i + 1].GetEnd(version)); i += 1; @@ -130,7 +132,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v else if (tokens[i + 2].Type == RadAsm2Lexer.LPAREN) { var funcDefinition = new DefinitionToken(RadAsmTokenType.FunctionName, tokens[i + 1], version); - definitionContainer.Add(currentBlock, funcDefinition); + _container.Add(currentBlock, funcDefinition); currentBlock = blocks.AppendBlock(new FunctionBlock(currentBlock, BlockType.Function, token, funcDefinition)); parserState = ParserState.SearchArguments; @@ -149,7 +151,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v if (tokens.Length > 2) { currentBlock.SetEnd(tokens[i - 1].Start.GetPosition(version), token); - definitionContainer.ClearScope(currentBlock); + _container.ClearScope(currentBlock); currentBlock = currentBlock.GetParent(); currentBlock = blocks.AppendBlock(new Block(currentBlock, BlockType.Condition, token)); @@ -166,7 +168,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v if (currentBlock.Type == BlockType.Function || currentBlock.Type == BlockType.Condition || currentBlock.Type == BlockType.Loop) { currentBlock.SetEnd(token.GetEnd(version), token); - definitionContainer.ClearScope(currentBlock); + _container.ClearScope(currentBlock); currentBlock = currentBlock.GetParent(); } } @@ -180,7 +182,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v if (currentBlock.Type == BlockType.Repeat) { currentBlock.SetEnd(token.GetEnd(version), token); - definitionContainer.ClearScope(currentBlock); + _container.ClearScope(currentBlock); currentBlock = currentBlock.GetParent(); } } @@ -191,14 +193,14 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v var variableDefinition = (tokens.Length - i > 3 && tokens[i + 2].Type == RadAsm2Lexer.EQ && tokens[i + 3].Type == RadAsm2Lexer.CONSTANT) ? new VariableToken(currentBlock.Type == BlockType.Root ? RadAsmTokenType.GlobalVariable : RadAsmTokenType.LocalVariable, tokens[i + 1], version, tokens[i + 3]) : new VariableToken(currentBlock.Type == BlockType.Root ? RadAsmTokenType.GlobalVariable : RadAsmTokenType.LocalVariable, tokens[i + 1], version); - definitionContainer.Add(currentBlock, variableDefinition); + _container.Add(currentBlock, variableDefinition); currentBlock.AddToken(variableDefinition); } } else if (token.Type == RadAsm2Lexer.CLOSURE_IDENTIFIER) { var tokenText = token.GetText(version).Substring(1); // remove first '#' symbol - if (!TryAddReference(tokenText, token, currentBlock, version, definitionContainer, cancellation)) + if (!TryAddReference(tokenText, token, currentBlock, version, _container, cancellation)) { referenceCandidates.AddLast((tokenText, token, currentBlock)); } @@ -207,7 +209,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v { var tokenText = token.GetText(version); if (!TryAddInstruction(tokenText, token, currentBlock, version) && - !TryAddReference(tokenText, token, currentBlock, version, definitionContainer, cancellation)) + !TryAddReference(tokenText, token, currentBlock, version, _container, cancellation)) { referenceCandidates.AddLast((tokenText, token, currentBlock)); } @@ -216,7 +218,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v { if (tokens.Length - i > 1 && tokens[i + 1].Type == RadAsm2Lexer.STRING_LITERAL) { - await AddExternalDefinitionsAsync(document.Path, tokens[i + 1], currentBlock, definitionContainer); + await AddExternalDefinitionsAsync(document.Path, tokens[i + 1], currentBlock, _container); i += 1; } } @@ -238,7 +240,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v else if (token.Type == RadAsm2Lexer.IDENTIFIER) { var parameterDefinition = new DefinitionToken(RadAsmTokenType.FunctionParameter, token, version); - definitionContainer.Add(currentBlock, parameterDefinition); + _container.Add(currentBlock, parameterDefinition); currentBlock.AddToken(parameterDefinition); } } @@ -246,7 +248,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v foreach (var (text, trackingToken, block) in referenceCandidates) { - if (!TryAddReference(text, trackingToken, block, version, definitionContainer, cancellation) && OtherInstructions.Contains(text)) + if (!TryAddReference(text, trackingToken, block, version, _container, cancellation) && OtherInstructions.Contains(text)) errors.Add(new ErrorToken(trackingToken, version, ErrorMessages.InvalidInstructionSetErrorMessage)); } diff --git a/VSRAD.Syntax/Core/Parser/DefinitionContainer.cs b/VSRAD.Syntax/Core/Parser/DefinitionContainer.cs index 11275a73d..4e957f244 100644 --- a/VSRAD.Syntax/Core/Parser/DefinitionContainer.cs +++ b/VSRAD.Syntax/Core/Parser/DefinitionContainer.cs @@ -1,9 +1,11 @@ using System.Collections.Generic; +using System.ComponentModel.Composition; using VSRAD.Syntax.Core.Blocks; using VSRAD.Syntax.Core.Tokens; namespace VSRAD.Syntax.Core.Parser { + [Export(typeof(DefinitionContainer))] public class DefinitionContainer { private readonly Dictionary> _container; From 03375488c1da64fcad208c01cd3253bcac538ceb Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Wed, 21 Dec 2022 18:44:58 +0100 Subject: [PATCH 3/5] document manager wip --- .../Core/Parser/AbstractCodeParser.cs | 8 ++- VSRAD.Syntax/Core/Parser/Asm1Parser.cs | 4 +- VSRAD.Syntax/Core/Parser/Asm2Parser.cs | 9 ++-- VSRAD.Syntax/Core/Parser/DocumentManager.cs | 53 +++++++++++++++++++ VSRAD.Syntax/VSRAD.Syntax.csproj | 1 + 5 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 VSRAD.Syntax/Core/Parser/DocumentManager.cs diff --git a/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs b/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs index c09578588..47a60cfe7 100644 --- a/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs +++ b/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs @@ -22,15 +22,17 @@ internal abstract class AbstractCodeParser : IParser private HashSet _instructions; private IReadOnlyList _includes; protected DefinitionContainer _container; + protected DocumentManager _manager; protected AbstractCodeParser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, - IReadOnlyList includes, DefinitionContainer container, AsmType asmType) + IReadOnlyList includes, DefinitionContainer container, DocumentManager manager, AsmType asmType) { _asmType = asmType; _documentFactory = documentFactory; _instructions = new HashSet(); _includes = includes; _container = container; + _manager = manager; OtherInstructions = new HashSet(); instructionListManager.InstructionsUpdated += InstructionsUpdated; @@ -60,8 +62,9 @@ private void InstructionsUpdated(IInstructionListManager sender, AsmType asmType } } - protected async Task AddExternalDefinitionsAsync(string path, TrackingToken includeStr, IBlock block, DefinitionContainer definitionContainer) + protected async Task AddExternalDefinitionsAsync(IDocument document, string path, TrackingToken includeStr, IBlock block, DefinitionContainer definitionContainer) { + // wip : we do not need to pass path and definition container here because we can get them from doc and docManager try { var externalFileName = includeStr.GetText(block.Snapshot).Trim('"'); @@ -84,6 +87,7 @@ protected async Task AddExternalDefinitionsAsync(string path, TrackingToken incl var externalAnalysisResult = await externalDocumentAnalysis .GetAnalysisResultAsync(externalDocument.CurrentSnapshot) .ConfigureAwait(false); + _manager.AddChild(document, externalDocument); foreach (var externalDefinition in externalAnalysisResult.GetGlobalDefinitions()) _container.Add(block, externalDefinition); diff --git a/VSRAD.Syntax/Core/Parser/Asm1Parser.cs b/VSRAD.Syntax/Core/Parser/Asm1Parser.cs index fc924bde2..b218cdc3e 100644 --- a/VSRAD.Syntax/Core/Parser/Asm1Parser.cs +++ b/VSRAD.Syntax/Core/Parser/Asm1Parser.cs @@ -30,7 +30,7 @@ internal sealed class Asm1Parser : AbstractCodeParser }); private Asm1Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes) - : base(documentFactory, instructionListManager, includes, null, AsmType.RadAsm) { } + : base(documentFactory, instructionListManager, includes, null, null, AsmType.RadAsm) { } public override Task RunAsync(IDocument document, ITextSnapshot version, ITokenizerCollection trackingTokens, CancellationToken cancellation) @@ -213,7 +213,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v { if (tokens.Length - i > 1 && tokens[i + 1].Type == RadAsm1Lexer.STRING_LITERAL) { - await AddExternalDefinitionsAsync(document.Path, tokens[i + 1], currentBlock, definitionContainer); + await AddExternalDefinitionsAsync(document, document.Path, tokens[i + 1], currentBlock, definitionContainer); i += 1; } } diff --git a/VSRAD.Syntax/Core/Parser/Asm2Parser.cs b/VSRAD.Syntax/Core/Parser/Asm2Parser.cs index ebc228c73..4a679b9a3 100644 --- a/VSRAD.Syntax/Core/Parser/Asm2Parser.cs +++ b/VSRAD.Syntax/Core/Parser/Asm2Parser.cs @@ -26,13 +26,14 @@ internal sealed class Asm2Parser : AbstractCodeParser var instructionListManager = serviceProvider.GetMefService(); var options = serviceProvider.GetMefService(); var container = serviceProvider.GetMefService(); + var manager = serviceProvider.GetMefService(); - return new Asm2Parser(documentFactory, instructionListManager, options.IncludePaths, container); + return new Asm2Parser(documentFactory, instructionListManager, options.IncludePaths, container, manager); }); private Asm2Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes, - DefinitionContainer container) - : base(documentFactory, instructionListManager, includes, container, AsmType.RadAsm2) { } + DefinitionContainer container, DocumentManager manager) + : base(documentFactory, instructionListManager, includes, container, manager, AsmType.RadAsm2) { } public override Task RunAsync(IDocument document, ITextSnapshot version, ITokenizerCollection trackingTokens, CancellationToken cancellation) @@ -218,7 +219,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v { if (tokens.Length - i > 1 && tokens[i + 1].Type == RadAsm2Lexer.STRING_LITERAL) { - await AddExternalDefinitionsAsync(document.Path, tokens[i + 1], currentBlock, _container); + await AddExternalDefinitionsAsync(document, document.Path, tokens[i + 1], currentBlock, _container); i += 1; } } diff --git a/VSRAD.Syntax/Core/Parser/DocumentManager.cs b/VSRAD.Syntax/Core/Parser/DocumentManager.cs new file mode 100644 index 000000000..4ec941c87 --- /dev/null +++ b/VSRAD.Syntax/Core/Parser/DocumentManager.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; + +namespace VSRAD.Syntax.Core.Parser +{ + [Export(typeof(DocumentManager))] + public class DocumentManager + { + private List _documents; + + public DocumentManager() + { + _documents = new List(); + } + + private DocumentNode GetNodeForDoc(IDocument document) + { + var node = _documents.FirstOrDefault(d => d.Document == document); + if (node == default(DocumentNode)) + { + node = new DocumentNode(document); + _documents.Add(node); + } + return node; + } + + public DefinitionContainer GetContainerForDoc(IDocument document) + => GetNodeForDoc(document).DefinitionContainer; + + public void AddChild(IDocument parent, IDocument child) + { + var pNode = GetNodeForDoc(parent); + var cNode = GetNodeForDoc(child); + if (!pNode.Children.Contains(cNode)) + pNode.Children.Add(cNode); + } + } + + sealed class DocumentNode + { + public readonly IDocument Document; + public readonly DefinitionContainer DefinitionContainer; + public readonly List Children; + + public DocumentNode(IDocument doc) + { + Document = doc; + DefinitionContainer = new DefinitionContainer(); + Children = new List(); + } + } +} diff --git a/VSRAD.Syntax/VSRAD.Syntax.csproj b/VSRAD.Syntax/VSRAD.Syntax.csproj index 9c7936a45..b450763a4 100644 --- a/VSRAD.Syntax/VSRAD.Syntax.csproj +++ b/VSRAD.Syntax/VSRAD.Syntax.csproj @@ -92,6 +92,7 @@ + From d286deb810ddfa1d0cd0ed3bf1144107eade7c9c Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Wed, 21 Dec 2022 19:46:54 +0100 Subject: [PATCH 4/5] actually using doc manager --- .../Core/Parser/AbstractCodeParser.cs | 12 +++---- VSRAD.Syntax/Core/Parser/Asm1Parser.cs | 4 +-- VSRAD.Syntax/Core/Parser/Asm2Parser.cs | 34 +++++++++---------- .../Core/Parser/DefinitionContainer.cs | 1 - 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs b/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs index 47a60cfe7..6cc109832 100644 --- a/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs +++ b/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs @@ -21,17 +21,15 @@ internal abstract class AbstractCodeParser : IParser private readonly AsmType _asmType; private HashSet _instructions; private IReadOnlyList _includes; - protected DefinitionContainer _container; protected DocumentManager _manager; protected AbstractCodeParser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, - IReadOnlyList includes, DefinitionContainer container, DocumentManager manager, AsmType asmType) + IReadOnlyList includes, DocumentManager manager, AsmType asmType) { _asmType = asmType; _documentFactory = documentFactory; _instructions = new HashSet(); _includes = includes; - _container = container; _manager = manager; OtherInstructions = new HashSet(); @@ -62,9 +60,8 @@ private void InstructionsUpdated(IInstructionListManager sender, AsmType asmType } } - protected async Task AddExternalDefinitionsAsync(IDocument document, string path, TrackingToken includeStr, IBlock block, DefinitionContainer definitionContainer) + protected async Task AddExternalDefinitionsAsync(IDocument document, string path, TrackingToken includeStr, IBlock block) { - // wip : we do not need to pass path and definition container here because we can get them from doc and docManager try { var externalFileName = includeStr.GetText(block.Snapshot).Trim('"'); @@ -89,8 +86,9 @@ protected async Task AddExternalDefinitionsAsync(IDocument document, string path .ConfigureAwait(false); _manager.AddChild(document, externalDocument); - foreach (var externalDefinition in externalAnalysisResult.GetGlobalDefinitions()) - _container.Add(block, externalDefinition); + //var pContainer = _manager.GetContainerForDoc(document); + //foreach (var externalDefinition in externalAnalysisResult.GetGlobalDefinitions()) + // pContainer.Add(block, externalDefinition); } } catch (Exception e) when (e is ArgumentException || e is FileNotFoundException) { /* invalid path */ } diff --git a/VSRAD.Syntax/Core/Parser/Asm1Parser.cs b/VSRAD.Syntax/Core/Parser/Asm1Parser.cs index b218cdc3e..b522bd12d 100644 --- a/VSRAD.Syntax/Core/Parser/Asm1Parser.cs +++ b/VSRAD.Syntax/Core/Parser/Asm1Parser.cs @@ -30,7 +30,7 @@ internal sealed class Asm1Parser : AbstractCodeParser }); private Asm1Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes) - : base(documentFactory, instructionListManager, includes, null, null, AsmType.RadAsm) { } + : base(documentFactory, instructionListManager, includes, null, AsmType.RadAsm) { } public override Task RunAsync(IDocument document, ITextSnapshot version, ITokenizerCollection trackingTokens, CancellationToken cancellation) @@ -213,7 +213,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v { if (tokens.Length - i > 1 && tokens[i + 1].Type == RadAsm1Lexer.STRING_LITERAL) { - await AddExternalDefinitionsAsync(document, document.Path, tokens[i + 1], currentBlock, definitionContainer); + await AddExternalDefinitionsAsync(document, document.Path, tokens[i + 1], currentBlock); i += 1; } } diff --git a/VSRAD.Syntax/Core/Parser/Asm2Parser.cs b/VSRAD.Syntax/Core/Parser/Asm2Parser.cs index 4a679b9a3..d6d723e71 100644 --- a/VSRAD.Syntax/Core/Parser/Asm2Parser.cs +++ b/VSRAD.Syntax/Core/Parser/Asm2Parser.cs @@ -25,15 +25,13 @@ internal sealed class Asm2Parser : AbstractCodeParser var documentFactory = serviceProvider.GetMefService(); var instructionListManager = serviceProvider.GetMefService(); var options = serviceProvider.GetMefService(); - var container = serviceProvider.GetMefService(); var manager = serviceProvider.GetMefService(); - return new Asm2Parser(documentFactory, instructionListManager, options.IncludePaths, container, manager); + return new Asm2Parser(documentFactory, instructionListManager, options.IncludePaths, manager); }); - private Asm2Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes, - DefinitionContainer container, DocumentManager manager) - : base(documentFactory, instructionListManager, includes, container, manager, AsmType.RadAsm2) { } + private Asm2Parser(IDocumentFactory documentFactory, IInstructionListManager instructionListManager, IReadOnlyList includes, DocumentManager manager) + : base(documentFactory, instructionListManager, includes, manager, AsmType.RadAsm2) { } public override Task RunAsync(IDocument document, ITextSnapshot version, ITokenizerCollection trackingTokens, CancellationToken cancellation) @@ -59,9 +57,9 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v .WithCancellation(cancellation) .ToArray(); - //var definitionContainer = new DefinitionContainer(); var referenceCandidates = new LinkedList<(string text, TrackingToken trackingToken, IBlock block)>(); + var definitionContainer = _manager.GetContainerForDoc(document); var blocks = new List(); var errors = new List(); IBlock currentBlock = new Block(version); @@ -113,7 +111,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v && tokens[i + 3].Type == RadAsm2Lexer.EOL) { var labelDefinition = new DefinitionToken(RadAsmTokenType.Label, tokens[i + 1], version); - _container.Add(currentBlock, labelDefinition); + definitionContainer.Add(currentBlock, labelDefinition); currentBlock.AddToken(labelDefinition); i += 2; } @@ -125,7 +123,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v if (tokens[i + 2].Type == RadAsm2Lexer.EOL) { var funcDefinition = new DefinitionToken(RadAsmTokenType.FunctionName, tokens[i + 1], version); - _container.Add(currentBlock, funcDefinition); + definitionContainer.Add(currentBlock, funcDefinition); currentBlock = blocks.AppendBlock(new FunctionBlock(currentBlock, BlockType.Function, token, funcDefinition)); currentBlock.SetStart(tokens[i + 1].GetEnd(version)); i += 1; @@ -133,7 +131,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v else if (tokens[i + 2].Type == RadAsm2Lexer.LPAREN) { var funcDefinition = new DefinitionToken(RadAsmTokenType.FunctionName, tokens[i + 1], version); - _container.Add(currentBlock, funcDefinition); + definitionContainer.Add(currentBlock, funcDefinition); currentBlock = blocks.AppendBlock(new FunctionBlock(currentBlock, BlockType.Function, token, funcDefinition)); parserState = ParserState.SearchArguments; @@ -152,7 +150,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v if (tokens.Length > 2) { currentBlock.SetEnd(tokens[i - 1].Start.GetPosition(version), token); - _container.ClearScope(currentBlock); + definitionContainer.ClearScope(currentBlock); currentBlock = currentBlock.GetParent(); currentBlock = blocks.AppendBlock(new Block(currentBlock, BlockType.Condition, token)); @@ -169,7 +167,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v if (currentBlock.Type == BlockType.Function || currentBlock.Type == BlockType.Condition || currentBlock.Type == BlockType.Loop) { currentBlock.SetEnd(token.GetEnd(version), token); - _container.ClearScope(currentBlock); + definitionContainer.ClearScope(currentBlock); currentBlock = currentBlock.GetParent(); } } @@ -183,7 +181,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v if (currentBlock.Type == BlockType.Repeat) { currentBlock.SetEnd(token.GetEnd(version), token); - _container.ClearScope(currentBlock); + definitionContainer.ClearScope(currentBlock); currentBlock = currentBlock.GetParent(); } } @@ -194,14 +192,14 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v var variableDefinition = (tokens.Length - i > 3 && tokens[i + 2].Type == RadAsm2Lexer.EQ && tokens[i + 3].Type == RadAsm2Lexer.CONSTANT) ? new VariableToken(currentBlock.Type == BlockType.Root ? RadAsmTokenType.GlobalVariable : RadAsmTokenType.LocalVariable, tokens[i + 1], version, tokens[i + 3]) : new VariableToken(currentBlock.Type == BlockType.Root ? RadAsmTokenType.GlobalVariable : RadAsmTokenType.LocalVariable, tokens[i + 1], version); - _container.Add(currentBlock, variableDefinition); + definitionContainer.Add(currentBlock, variableDefinition); currentBlock.AddToken(variableDefinition); } } else if (token.Type == RadAsm2Lexer.CLOSURE_IDENTIFIER) { var tokenText = token.GetText(version).Substring(1); // remove first '#' symbol - if (!TryAddReference(tokenText, token, currentBlock, version, _container, cancellation)) + if (!TryAddReference(tokenText, token, currentBlock, version, definitionContainer, cancellation)) { referenceCandidates.AddLast((tokenText, token, currentBlock)); } @@ -210,7 +208,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v { var tokenText = token.GetText(version); if (!TryAddInstruction(tokenText, token, currentBlock, version) && - !TryAddReference(tokenText, token, currentBlock, version, _container, cancellation)) + !TryAddReference(tokenText, token, currentBlock, version, definitionContainer, cancellation)) { referenceCandidates.AddLast((tokenText, token, currentBlock)); } @@ -219,7 +217,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v { if (tokens.Length - i > 1 && tokens[i + 1].Type == RadAsm2Lexer.STRING_LITERAL) { - await AddExternalDefinitionsAsync(document, document.Path, tokens[i + 1], currentBlock, _container); + await AddExternalDefinitionsAsync(document, document.Path, tokens[i + 1], currentBlock); i += 1; } } @@ -241,7 +239,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v else if (token.Type == RadAsm2Lexer.IDENTIFIER) { var parameterDefinition = new DefinitionToken(RadAsmTokenType.FunctionParameter, token, version); - _container.Add(currentBlock, parameterDefinition); + definitionContainer.Add(currentBlock, parameterDefinition); currentBlock.AddToken(parameterDefinition); } } @@ -249,7 +247,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v foreach (var (text, trackingToken, block) in referenceCandidates) { - if (!TryAddReference(text, trackingToken, block, version, _container, cancellation) && OtherInstructions.Contains(text)) + if (!TryAddReference(text, trackingToken, block, version, definitionContainer, cancellation) && OtherInstructions.Contains(text)) errors.Add(new ErrorToken(trackingToken, version, ErrorMessages.InvalidInstructionSetErrorMessage)); } diff --git a/VSRAD.Syntax/Core/Parser/DefinitionContainer.cs b/VSRAD.Syntax/Core/Parser/DefinitionContainer.cs index 4e957f244..3ff368bb0 100644 --- a/VSRAD.Syntax/Core/Parser/DefinitionContainer.cs +++ b/VSRAD.Syntax/Core/Parser/DefinitionContainer.cs @@ -5,7 +5,6 @@ namespace VSRAD.Syntax.Core.Parser { - [Export(typeof(DefinitionContainer))] public class DefinitionContainer { private readonly Dictionary> _container; From 59b49ebd167fd1db04bd983af04f086181c25dee Mon Sep 17 00:00:00 2001 From: johnny-keker Date: Thu, 12 Jan 2023 18:45:43 +0100 Subject: [PATCH 5/5] includes actually workgit diff --staged! --- .../Core/Parser/AbstractCodeParser.cs | 22 +++++++++++++++++-- VSRAD.Syntax/Core/Parser/Asm1Parser.cs | 4 ++-- VSRAD.Syntax/Core/Parser/Asm2Parser.cs | 6 ++--- VSRAD.Syntax/Core/Parser/DocumentManager.cs | 7 +++--- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs b/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs index 6cc109832..abb069e75 100644 --- a/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs +++ b/VSRAD.Syntax/Core/Parser/AbstractCodeParser.cs @@ -94,10 +94,15 @@ protected async Task AddExternalDefinitionsAsync(IDocument document, string path catch (Exception e) when (e is ArgumentException || e is FileNotFoundException) { /* invalid path */ } } - protected bool TryAddReference(string tokenText, TrackingToken token, IBlock block, ITextSnapshot version, DefinitionContainer definitionContainer, CancellationToken cancellation) + protected bool TryAddReference(IDocument doc, string tokenText, TrackingToken token, IBlock block, + ITextSnapshot version, CancellationToken cancellation) { cancellation.ThrowIfCancellationRequested(); - if (definitionContainer.TryGetDefinition(tokenText, out var definitionToken)) + + var node = _manager.GetNodeForDoc(doc); + var definitionToken = SearchForToken(node, tokenText); + + if (definitionToken != null) { RadAsmTokenType referenceType; switch (definitionToken.Type) @@ -133,6 +138,19 @@ protected bool TryAddReference(string tokenText, TrackingToken token, IBlock blo return false; } + private DefinitionToken SearchForToken(DocumentNode node, string tokenText) + { + DefinitionToken token; + if (node.DefinitionContainer.TryGetDefinition(tokenText, out token)) + return token; // look for token in current node + foreach (var child in node.Children) // going deeper in recursion + { + token = SearchForToken(child, tokenText); + if (token != null) break; // found token in child node + } + return token; // can still be null, in case non of children contains token + } + protected bool TryAddInstruction(string tokenText, TrackingToken token, IBlock block, ITextSnapshot version) { if (_instructions.Contains(tokenText)) diff --git a/VSRAD.Syntax/Core/Parser/Asm1Parser.cs b/VSRAD.Syntax/Core/Parser/Asm1Parser.cs index b522bd12d..a773162cc 100644 --- a/VSRAD.Syntax/Core/Parser/Asm1Parser.cs +++ b/VSRAD.Syntax/Core/Parser/Asm1Parser.cs @@ -194,7 +194,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v { var tokenText = token.GetText(version); if (!TryAddInstruction(tokenText, token, currentBlock, version) && - !TryAddReference(tokenText, token, currentBlock, version, definitionContainer, cancellation)) + !TryAddReference(document, tokenText, token, currentBlock, version, cancellation)) { if (tokens.Length - i > 1 && tokens[i + 1].Type == RadAsm1Lexer.EQ) { @@ -238,7 +238,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v foreach (var (text, trackingToken, block) in referenceCandidates) { - if (!TryAddReference(text, trackingToken, block, version, definitionContainer, cancellation) && OtherInstructions.Contains(text)) + if (!TryAddReference(document, text, trackingToken, block, version, cancellation) && OtherInstructions.Contains(text)) errors.Add(new ErrorToken(trackingToken, version, ErrorMessages.InvalidInstructionSetErrorMessage)); } diff --git a/VSRAD.Syntax/Core/Parser/Asm2Parser.cs b/VSRAD.Syntax/Core/Parser/Asm2Parser.cs index d6d723e71..a7152216d 100644 --- a/VSRAD.Syntax/Core/Parser/Asm2Parser.cs +++ b/VSRAD.Syntax/Core/Parser/Asm2Parser.cs @@ -199,7 +199,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v else if (token.Type == RadAsm2Lexer.CLOSURE_IDENTIFIER) { var tokenText = token.GetText(version).Substring(1); // remove first '#' symbol - if (!TryAddReference(tokenText, token, currentBlock, version, definitionContainer, cancellation)) + if (!TryAddReference(document, tokenText, token, currentBlock, version, cancellation)) { referenceCandidates.AddLast((tokenText, token, currentBlock)); } @@ -208,7 +208,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v { var tokenText = token.GetText(version); if (!TryAddInstruction(tokenText, token, currentBlock, version) && - !TryAddReference(tokenText, token, currentBlock, version, definitionContainer, cancellation)) + !TryAddReference(document, tokenText, token, currentBlock, version, cancellation)) { referenceCandidates.AddLast((tokenText, token, currentBlock)); } @@ -247,7 +247,7 @@ private async Task ParseAsync(IDocument document, ITextSnapshot v foreach (var (text, trackingToken, block) in referenceCandidates) { - if (!TryAddReference(text, trackingToken, block, version, definitionContainer, cancellation) && OtherInstructions.Contains(text)) + if (!TryAddReference(document, text, trackingToken, block, version, cancellation) && OtherInstructions.Contains(text)) errors.Add(new ErrorToken(trackingToken, version, ErrorMessages.InvalidInstructionSetErrorMessage)); } diff --git a/VSRAD.Syntax/Core/Parser/DocumentManager.cs b/VSRAD.Syntax/Core/Parser/DocumentManager.cs index 4ec941c87..817700b6f 100644 --- a/VSRAD.Syntax/Core/Parser/DocumentManager.cs +++ b/VSRAD.Syntax/Core/Parser/DocumentManager.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.ComponentModel.Composition; using System.Linq; +using VSRAD.Syntax.Core.Blocks; namespace VSRAD.Syntax.Core.Parser { @@ -14,7 +15,7 @@ public DocumentManager() _documents = new List(); } - private DocumentNode GetNodeForDoc(IDocument document) + public DocumentNode GetNodeForDoc(IDocument document) { var node = _documents.FirstOrDefault(d => d.Document == document); if (node == default(DocumentNode)) @@ -37,10 +38,10 @@ public void AddChild(IDocument parent, IDocument child) } } - sealed class DocumentNode + public sealed class DocumentNode { public readonly IDocument Document; - public readonly DefinitionContainer DefinitionContainer; + public DefinitionContainer DefinitionContainer; public readonly List Children; public DocumentNode(IDocument doc)