public static void SortImports(Document doc = null) { doc = doc ?? IdeApp.Workbench.ActiveDocument; if (doc == null) { return; } var ddoc = doc.ParsedDocument as ParsedDModule; if (ddoc == null || ddoc.DDom == null) { return; } var scope = DResolver.SearchBlockAt(ddoc.DDom, new CodeLocation(doc.Editor.Caret.Column, doc.Editor.Caret.Line)) as DBlockNode; if (scope == null) { return; } var editor = doc.Editor; using (editor.Document.OpenUndoGroup(Mono.TextEditor.OperationType.Undefined)) { SortImportsRefactoring.SortImports(scope, new TextDocumentAdapter(editor), SortImportsSeparatePackagesFromEachOther); } editor.Parent.TextViewMargin.PurgeLayoutCache(); editor.Parent.QueueDraw(); }
public void IncrementalParsing_LambdaParameters() { var code = @"module A; int foo; void main() { }"; var m = DParser.ParseString(code); var main = m ["main"].First() as DMethod; var foo = m ["foo"].First() as DVariable; var b = DResolver.SearchBlockAt(m, new CodeLocation(1, 4)); Assert.That(b, Is.SameAs(main)); code = @"module A; int foo; void main() { int a; (string ; }"; var caret = new CodeLocation(9, 5); bool _u; var newMod = IncrementalParsing.UpdateBlockPartly(main.Body, code, DocumentHelper.LocationToOffset(code, caret), caret, out _u) as DMethod; var lambda = newMod.Children [0] as DMethod; Assert.That(lambda, Is.Not.Null); Assert.That(lambda.Parameters.Count, Is.EqualTo(1)); Assert.That(lambda.Parameters [0].Type, Is.Not.Null); Assert.That(lambda.Parameters [0].NameHash, Is.EqualTo(DTokens.IncompleteIdHash)); }
public static ResolutionContext Create(IEditorData editor, ConditionalCompilationFlags globalConditions = null) { IStatement stmt; return(new ResolutionContext(editor.ParseCache, globalConditions ?? new ConditionalCompilationFlags(editor), DResolver.SearchBlockAt(editor.SyntaxTree, editor.CaretLocation, out stmt) ?? editor.SyntaxTree, stmt)); }
public static ISyntaxRegion FindCurrentCaretContext(IEditorData editor, ref IBlockNode currentScope, out bool isInsideNonCodeSegment) { isInsideNonCodeSegment = false; if (currentScope == null) { currentScope = DResolver.SearchBlockAt(editor.SyntaxTree, editor.CaretLocation); } if (currentScope == null) { return(null); } // class asd : | if (currentScope is IBlockNode && (currentScope as IBlockNode).BlockStartLocation > editor.CaretLocation) { currentScope = currentScope.Parent as IBlockNode; } BlockStatement blockStmt; // Always skip lambdas as they're too quirky for accurate scope calculation // ISSUE: May be other anon symbols too? var dm = currentScope as DMethod; if (dm != null && (dm.SpecialType & DMethod.MethodType.Lambda) != 0) { currentScope = dm.Parent as IBlockNode; } if (currentScope is DMethod && (blockStmt = (currentScope as DMethod).GetSubBlockAt(editor.CaretLocation)) != null) { var tempBlock = blockStmt.UpdateBlockPartly(editor, out isInsideNonCodeSegment); if (tempBlock == null) { return(null); } currentScope = DResolver.SearchBlockAt(tempBlock, editor.CaretLocation); } else { while (currentScope is DMethod) { currentScope = currentScope.Parent as IBlockNode; } if (currentScope == null) { return(null); } var tempBlock = (currentScope as DBlockNode).UpdateBlockPartly(editor, out isInsideNonCodeSegment); currentScope = DResolver.SearchBlockAt(tempBlock, editor.CaretLocation); } return(currentScope); }
void _th(object pcl_shared) { var pcl = (ParseCacheList)pcl_shared; var ctxt = new ResolverContextStack(pcl, new ResolverContext { ScopedBlock = ast }); // Make it as most performing as possible by avoiding unnecessary base types. // Aliases should be analyzed deeper though. ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.StopAfterFirstOverloads | ResolutionOptions.DontResolveBaseTypes | //TODO: Exactly find out which option can be enabled here. Resolving variables' types is needed sometimes - but only, when highlighting a variable reference is wanted explicitly. ResolutionOptions.NoTemplateParameterDeduction | ResolutionOptions.ReturnMethodReferencesOnly; ISyntaxRegion sr = null; int i = 0; while (curQueueOffset < queueCount) { // Avoid race condition runtime errors lock (_lockObject) { i = curQueueOffset; curQueueOffset++; } // Resolve gotten syntax object sr = q[i]; var sb = ctxt.CurrentContext.ScopedBlock; ctxt.CurrentContext.ScopedBlock = DResolver.SearchBlockAt( sb == null || sr.Location <sb.BlockStartLocation || sr.EndLocation> sb.EndLocation ? ast : sb, sr.Location, out ctxt.CurrentContext.ScopedStatement); if (sr is PostfixExpression_Access) { HandleAccessExpressions((PostfixExpression_Access)sr, ctxt); } else { AbstractType t = null; if (sr is IExpression) { t = DResolver.StripAliasSymbol(Evaluation.EvaluateType((IExpression)sr, ctxt)); } else if (sr is ITypeDeclaration) { t = DResolver.StripAliasSymbol(TypeDeclarationResolver.ResolveSingle((ITypeDeclaration)sr, ctxt)); } // Enter into the result list HandleResult(sr, t); } } }
public static ResolverContextStack Create(IEditorData editor) { IStatement stmt = null; return(new ResolverContextStack(editor.ParseCache, new ResolverContext { ScopedBlock = DResolver.SearchBlockAt(editor.SyntaxTree, editor.CaretLocation, out stmt), ScopedStatement = stmt })); }
void UpdateOutlineSelection(object sender, Mono.TextEditor.DocumentLocationEventArgs e) { if (clickedOnOutlineItem || SyntaxTree == null || TreeStore == null) { return; } IStatement stmt = null; var caretLocation = Document.Editor.Caret.Location; var caretLocationD = new CodeLocation(caretLocation.Column, caretLocation.Line); var currentblock = DResolver.SearchBlockAt(SyntaxTree, caretLocationD, out stmt); INode selectedASTNode = null; if (currentblock == null) { return; } foreach (var n in currentblock) { if (caretLocationD >= n.Location && caretLocationD <= n.EndLocation) { selectedASTNode = n; break; } } if (selectedASTNode == null) { selectedASTNode = stmt != null ? stmt.ParentNode : currentblock; } if (selectedASTNode == null) { return; } TreeStore.Foreach((TreeModel model, TreePath path, TreeIter iter) => { var n = model.GetValue(iter, 0); if (n == selectedASTNode) { dontJumpToDeclaration = true; TreeView.Selection.SelectIter(iter); TreeView.ScrollToCell(path, TreeView.GetColumn(0), true, 0, 0); dontJumpToDeclaration = false; return(true); } return(false); }); }
public static AbstractTooltipContent[] BuildToolTip(IEditorData Editor) { try { IStatement curStmt = null; var rr = DResolver.ResolveType(Editor, new ResolverContext { ScopedBlock = DResolver.SearchBlockAt(Editor.SyntaxTree, Editor.CaretLocation, out curStmt), ScopedStatement = curStmt, ParseCache = Editor.ParseCache, ImportCache = Editor.ImportCache }, true, true); if (rr.Length < 1) { return(null); } var l = new List <AbstractTooltipContent>(rr.Length); foreach (var res in rr) { var modRes = res as ModuleResult; var memRes = res as MemberResult; var typRes = res as TypeResult; // Only show one description for items sharing descriptions string description = ""; if (modRes != null) { description = modRes.ResolvedModule.Description; } else if (memRes != null) { description = memRes.ResolvedMember.Description; } else if (typRes != null) { description = typRes.ResolvedTypeDefinition.Description; } l.Add(new AbstractTooltipContent { ResolveResult = res, Title = (res is ModuleResult ? (res as ModuleResult).ResolvedModule.FileName : res.ToString()), Description = description }); } return(l.ToArray()); } catch { } return(null); }
public void IsExpressionAlias_InMethod() { var ctxt = ResolutionTests.CreateCtxt("A", @"module A; void main(){ pre; static if(is(const(int)* U == const(U)*)) { U var; } post; } "); IExpression x; AbstractType t; DSymbol ds; var main = ctxt.ParseCache[0]["A"]["main"].First() as DMethod; ctxt.PushNewScope(main, main.Body.SubStatements.First()); t = TypeDeclarationResolver.ResolveSingle(new IdentifierDeclaration("U") { Location = main.Body.SubStatements.First().Location }, ctxt); Assert.That(t, Is.Null); ctxt.Pop(); ctxt.PushNewScope(main, main.Body.SubStatements.ElementAt(2)); t = TypeDeclarationResolver.ResolveSingle(new IdentifierDeclaration("U") { Location = main.Body.SubStatements.ElementAt(2).Location }, ctxt); Assert.That(t, Is.Null); ctxt.Pop(); x = DParser.ParseExpression("var"); IStatement stmt; DResolver.SearchBlockAt(main, (x as IdentifierExpression).Location = new CodeLocation(3, 7), out stmt); ctxt.PushNewScope(main, stmt); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); ds = t as DSymbol; Assert.That(t, Is.TypeOf(typeof(MemberSymbol))); Assert.That(ds.Base, Is.TypeOf(typeof(TemplateParameterSymbol))); ds = ds.Base as DSymbol; Assert.That(ds.Base, Is.TypeOf(typeof(PrimitiveType))); Assert.That((ds.Base as PrimitiveType).Modifier, Is.EqualTo(0)); }
public void DeepBlockSearch() { var m = DParser.ParseString(@"module modA; class A { int a; int b; int c; int d; } class B { class subB { int a; int b; int c; } } void main() { int a; } class C { }"); IStatement s; var n = DResolver.SearchBlockAt(m, ((IBlockNode)m["A"].First())["d"].First().Location, out s); Assert.AreEqual("A", n.Name); var loc = ((IBlockNode)m["C"].First()).BlockStartLocation; n = DResolver.SearchBlockAt(m, loc, out s); Assert.AreEqual("C", n.Name); loc = ((IBlockNode)((IBlockNode)m["B"].First())["subB"].First())["c"].First().Location; n = DResolver.SearchBlockAt(m, loc, out s); Assert.AreEqual("subB", n.Name); n = DResolver.SearchBlockAt(m, new CodeLocation(1, 10), out s); Assert.AreEqual(m, n); loc = (((DMethod)m["main"].First()).Body.First() as IDeclarationContainingStatement).Declarations[0].EndLocation; n = DResolver.SearchBlockAt(m, loc, out s); Assert.AreEqual("main", n.Name); }
public bool TryAssignDefaultType(TemplateTypeParameter p) { if (p == null || p.Default == null) { return(false); } using (ctxt.Push(DResolver.SearchBlockAt(ctxt.ScopedBlock.NodeRoot as IBlockNode, p.Default.Location), p.Default.Location)) { var defaultTypeRes = TypeDeclarationResolver.ResolveSingle(p.Default, ctxt); return(defaultTypeRes != null && Set(p, defaultTypeRes, 0)); } }
public void IncrementalParsing_Lambdas() { var code = @"module A; int foo; void main() { }"; var m = DParser.ParseString(code); var main = m ["main"].First() as DMethod; var foo = m ["foo"].First() as DVariable; IStatement stmt; var b = DResolver.SearchBlockAt(m, new CodeLocation(1, 4), out stmt); Assert.That(b, Is.SameAs(main)); Assert.That(stmt, Is.TypeOf(typeof(BlockStatement))); code = @"module A; int foo; void main() { int a; (string b) => ; }"; var caret = new CodeLocation(15, 5); bool _u; IncrementalParsing.UpdateBlockPartly(stmt as BlockStatement, code, DocumentHelper.LocationToOffset(code, caret), caret, out _u); var main2 = m ["main"].First() as DMethod; Assert.That(main, Is.SameAs(main2)); var foo2 = m ["foo"].First() as DVariable; Assert.That(foo2, Is.SameAs(foo)); var lambda = main2.AdditionalChildren [0] as DMethod; Assert.That(lambda, Is.Not.Null); Assert.That(lambda.Parameters.Count, Is.EqualTo(1)); Assert.That(lambda.Parameters [0].Type, Is.Not.Null); Assert.That(lambda.Parameters [0].Name, Is.EqualTo("b")); b = DResolver.SearchBlockAt(m, caret, out stmt); Assert.That(lambda, Is.SameAs(b)); Assert.That(stmt, Is.TypeOf(typeof(ReturnStatement))); }
bool Handle(TemplateTypeParameter p, ISemantic arg) { // if no argument given, try to handle default arguments if (arg == null) { if (p.Default == null) { return(false); } else { IStatement stmt = null; ctxt.PushNewScope(DResolver.SearchBlockAt(ctxt.ScopedBlock.NodeRoot as IBlockNode, p.Default.Location, out stmt)); ctxt.ScopedStatement = stmt; var defaultTypeRes = TypeDeclarationResolver.Resolve(p.Default, ctxt); bool b = false; if (defaultTypeRes != null) { b = Set(p, defaultTypeRes.First()); } ctxt.Pop(); return(b); } } // If no spezialization given, assign argument immediately if (p.Specialization == null) { return(Set(p, arg)); } bool handleResult = HandleDecl(p, p.Specialization, arg); if (!handleResult) { return(false); } // Apply the entire argument to parameter p if there hasn't been no explicit association yet if (!TargetDictionary.ContainsKey(p.Name) || TargetDictionary[p.Name] == null) { TargetDictionary[p.Name] = new TemplateParameterSymbol(p, arg); } return(true); }
public void BeginUpdate() { if (hasBegun) { return; } hasBegun = true; currentCol = Document.Editor.Caret.Column; currentLine = Document.Editor.Caret.Line; var caret = new CodeLocation(currentCol, currentLine); currentBlock = DResolver.SearchBlockAt(Ast, caret, out currentStmt); isBeforeBlockStart = currentBlock != null && caret <= currentBlock.BlockStartLocation; isAtStmtStart = currentStmt != null && caret == currentStmt.Location; }
public static bool CanSortImports(Document doc = null) { doc = doc ?? IdeApp.Workbench.ActiveDocument; if (doc == null) { return(false); } var ddoc = doc.ParsedDocument as ParsedDModule; if (ddoc == null || ddoc.DDom == null) { return(false); } return(DResolver.SearchBlockAt(ddoc.DDom, new CodeLocation(doc.Editor.Caret.Column, doc.Editor.Caret.Line)) is DBlockNode); }
public bool TryAssignDefaultType(TemplateTypeParameter p) { if (p == null || p.Default == null) { return(false); } IStatement stmt = null; ctxt.PushNewScope(DResolver.SearchBlockAt(ctxt.ScopedBlock.NodeRoot as IBlockNode, p.Default.Location, out stmt), stmt); var defaultTypeRes = TypeDeclarationResolver.Resolve(p.Default, ctxt); var b = defaultTypeRes != null && Set(p, defaultTypeRes [0], 0); ctxt.Pop(); return(b); }
public static ResolutionContext CreateCurrentContext() { Document doc = null; DispatchService.GuiSyncDispatch(() => doc = Ide.IdeApp.Workbench.ActiveDocument); if (doc != null) { var ddoc = doc.ParsedDocument as ParsedDModule; if (ddoc != null) { var ast = ddoc.DDom; if (ast != null) { IStatement stmt; var caret = new D_Parser.Dom.CodeLocation(doc.Editor.Caret.Column, doc.Editor.Caret.Line); var bn = DResolver.SearchBlockAt(ast, caret, out stmt); var dbn = bn as DBlockNode; if (stmt == null && dbn != null) { //TODO: If inside an expression statement, search the nearest function call or template instance expression - and try to evaluate that one. if (dbn.StaticStatements.Count != 0) { foreach (var ss in dbn.StaticStatements) { if (caret >= ss.Location && caret <= ss.EndLocation) { stmt = ss; break; } } } } var ed = DResolverWrapper.CreateEditorData(doc); return(new ResolutionContext(ed.ParseCache, new ConditionalCompilationFlags(ed), bn, stmt)); } } } return(new ResolutionContext(DResolverWrapper.CreateCacheList(), new ConditionalCompilationFlags(VersionIdEvaluation.GetOSAndCPUVersions(), 1, true), null)); }
public static DParameterDataProvider Create(Document doc, IAbstractSyntaxTree SyntaxTree, CodeCompletionContext ctx) { var caretOffset = ctx.TriggerOffset; var caretLocation = new CodeLocation(ctx.TriggerLineOffset, ctx.TriggerLine); IStatement stmt = null; var curBlock = DResolver.SearchBlockAt(SyntaxTree, caretLocation, out stmt); if (curBlock == null) { return(null); } //doc.Edito if (!(curBlock is D_Parser.Dom.DMethod)) { return(null); } try { var argsResult = DResolver.ResolveArgumentContext( doc.Editor.Text, caretOffset, caretLocation, curBlock as D_Parser.Dom.DMethod, DCodeCompletionSupport.EnumAvailableModules(doc), null); if (argsResult == null || argsResult.ResolvedTypesOrMethods == null || argsResult.ResolvedTypesOrMethods.Length < 1) { return(null); } return(new DParameterDataProvider(doc, argsResult)); } catch { return(null); } }
public void IncrementalParsing_() { var code = @"module A; int foo; void main() {}"; var m = DParser.ParseString(code); var main = m ["main"].First() as DMethod; var foo = m ["foo"].First() as DVariable; IStatement stmt; var b = DResolver.SearchBlockAt(m, new CodeLocation(11, 3), out stmt); Assert.That(b, Is.SameAs(main)); Assert.That(stmt, Is.Null); code = @"module A; int foo; void main( string ) { }"; var caret = new CodeLocation(8, 4); bool _u; IncrementalParsing.UpdateBlockPartly(m, code, DocumentHelper.LocationToOffset(code, caret), caret, out _u); var main2 = m ["main"].First() as DMethod; Assert.That(main, Is.Not.SameAs(main2)); Assert.That(main2.Parameters.Count, Is.EqualTo(1)); Assert.That(main2.Parameters [0].Type, Is.Not.Null); Assert.That(main2.Parameters [0].NameHash, Is.EqualTo(DTokens.IncompleteIdHash)); var foo2 = m ["foo"].First() as DVariable; Assert.That(foo2, Is.SameAs(foo)); }
public void BuildCompletionData(IEditorData Editor, string EnteredText, out string lastResultPath) { lastResultPath = null; IStatement curStmt = null; var curBlock = DResolver.SearchBlockAt(Editor.SyntaxTree, Editor.CaretLocation, out curStmt); if (curBlock == null) { return; } IEnumerable <INode> listedItems = null; // Usually shows variable members #region DotCompletion if (EnteredText == ".") { alreadyAddedModuleNameParts.Clear(); var resolveResults = DResolver.ResolveType( Editor, new ResolverContext { ScopedBlock = curBlock, ParseCache = Editor.ParseCache, ImportCache = Editor.ImportCache, ScopedStatement = curStmt } ); if (resolveResults == null) //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope { return; } /* * Note: When having entered a module name stub only (e.g. "std." or "core.") it's needed to show all packages that belong to that root namespace */ foreach (var rr in resolveResults) { lastResultPath = ResolveResult.GetResolveResultString(rr); BuildCompletionData(rr, curBlock); } } #endregion else if (EnteredText == null || EnteredText == " " || EnteredText.Length < 1 || IsIdentifierChar(EnteredText[0])) { // 1) Get current context the caret is at. ParserTrackerVariables trackVars = null; var parsedBlock = DResolver.FindCurrentCaretContext( Editor.ModuleCode, curBlock, Editor.CaretOffset, Editor.CaretLocation, out trackVars); bool CaretAfterLastParsedObject = false; if (trackVars != null && trackVars.LastParsedObject != null) { if (trackVars.LastParsedObject is IExpression) { CaretAfterLastParsedObject = Editor.CaretLocation > (trackVars.LastParsedObject as IExpression).EndLocation; } else if (trackVars.LastParsedObject is INode) { CaretAfterLastParsedObject = Editor.CaretLocation > (trackVars.LastParsedObject as INode).EndLocation; } } // 2) If in declaration and if node identifier is expected, do not show any data if (trackVars == null || (trackVars.LastParsedObject is INode && !CaretAfterLastParsedObject && trackVars.ExpectingIdentifier) || (trackVars.LastParsedObject is TokenExpression && !CaretAfterLastParsedObject && DTokens.BasicTypes[(trackVars.LastParsedObject as TokenExpression).Token] && !string.IsNullOrEmpty(EnteredText) && IsIdentifierChar(EnteredText[0])) ) { return; } var visibleMembers = DResolver.MemberTypes.All; if (trackVars.LastParsedObject is ImportStatement && !CaretAfterLastParsedObject) { visibleMembers = DResolver.MemberTypes.Imports; } else if (trackVars.LastParsedObject is NewExpression && (trackVars.IsParsingInitializer || !CaretAfterLastParsedObject)) { visibleMembers = DResolver.MemberTypes.Imports | DResolver.MemberTypes.Types; } else if (EnteredText == " ") { return; } // In class bodies, do not show variables else if (!(parsedBlock is BlockStatement) && !trackVars.IsParsingInitializer) { visibleMembers = DResolver.MemberTypes.Imports | DResolver.MemberTypes.Types | DResolver.MemberTypes.Keywords; } // In a method, parse from the method's start until the actual caret position to get an updated insight if (visibleMembers.HasFlag(DResolver.MemberTypes.Variables) && curBlock is DMethod) { if (parsedBlock is BlockStatement) { var blockStmt = parsedBlock as BlockStatement; // Insert the updated locals insight. // Do not take the caret location anymore because of the limited parsing of our code. var scopedStmt = blockStmt.SearchStatementDeeply(blockStmt.EndLocation /*Editor.CaretLocation*/); var decls = BlockStatement.GetItemHierarchy(scopedStmt, Editor.CaretLocation); foreach (var n in decls) { CompletionDataGenerator.Add(n); } } } if (visibleMembers != DResolver.MemberTypes.Imports) // Do not pass the curStmt because we already inserted all updated locals a few lines before! { listedItems = DResolver.EnumAllAvailableMembers(curBlock, null /*, curStmt*/, Editor.CaretLocation, Editor.ParseCache, visibleMembers); } //TODO: Split the keywords into such that are allowed within block statements and non-block statements // Insert typable keywords if (visibleMembers.HasFlag(DResolver.MemberTypes.Keywords)) { foreach (var kv in DTokens.Keywords) { CompletionDataGenerator.Add(kv.Key); } } #region Add module name stubs of importable modules if (visibleMembers.HasFlag(DResolver.MemberTypes.Imports)) { var nameStubs = new Dictionary <string, string>(); var availModules = new List <IAbstractSyntaxTree>(); foreach (var mod in Editor.ParseCache) { if (string.IsNullOrEmpty(mod.ModuleName)) { continue; } var parts = mod.ModuleName.Split('.'); if (!nameStubs.ContainsKey(parts[0]) && !availModules.Contains(mod)) { if (parts[0] == mod.ModuleName) { availModules.Add(mod); } else { nameStubs.Add(parts[0], GetModulePath(mod.FileName, parts.Length, 1)); } } } foreach (var kv in nameStubs) { CompletionDataGenerator.Add(kv.Key, PathOverride: kv.Value); } foreach (var mod in availModules) { CompletionDataGenerator.Add(mod.ModuleName, mod); } } #endregion } // Add all found items to the referenced list if (listedItems != null) { foreach (var i in listedItems) { if (CanItemBeShownGenerally(i) /* && dm.IsStatic*/) { CompletionDataGenerator.Add(i); } } } }
/// <summary> /// Item1 - True, if isExpression returns true /// Item2 - If Item1 is true, it contains the type of the alias that is defined in the isExpression /// </summary> private Tuple <bool, AbstractType> evalIsExpression_EvalSpecToken(IsExpression isExpression, AbstractType typeToCheck, bool DoAliasHandling = false) { bool r = false; AbstractType res = null; switch (isExpression.TypeSpecializationToken) { /* * To handle semantic tokens like "return" or "super" it's just needed to * look into the current resolver context - * then, we'll be able to gather either the parent method or the currently scoped class definition. */ case DTokens.Struct: case DTokens.Union: case DTokens.Class: case DTokens.Interface: if (r = typeToCheck is UserDefinedType && ((TemplateIntermediateType)typeToCheck).Definition.ClassType == isExpression.TypeSpecializationToken) { res = typeToCheck; } break; case DTokens.Enum: if (!(typeToCheck is EnumType)) { break; } { var tr = (UserDefinedType)typeToCheck; r = true; res = tr.Base; } break; case DTokens.Function: case DTokens.Delegate: if (typeToCheck is DelegateType) { var isFun = false; var dgr = (DelegateType)typeToCheck; if (!dgr.IsFunctionLiteral) { r = isExpression.TypeSpecializationToken == ( (isFun = ((DelegateDeclaration)dgr.DeclarationOrExpressionBase).IsFunction) ? DTokens.Function : DTokens.Delegate); } // Must be a delegate otherwise else { isFun = !(r = isExpression.TypeSpecializationToken == DTokens.Delegate); } if (r) { //TODO if (isFun) { // TypeTuple of the function parameter types. For C- and D-style variadic functions, only the non-variadic parameters are included. // For typesafe variadic functions, the ... is ignored. } else { // the function type of the delegate } } } else // Normal functions are also accepted as delegates { r = isExpression.TypeSpecializationToken == DTokens.Delegate && typeToCheck is MemberSymbol && ((DSymbol)typeToCheck).Definition is DMethod; //TODO: Alias handling, same as couple of lines above } break; case DTokens.Super: //TODO: Test this var dc = DResolver.SearchClassLikeAt(ctxt.ScopedBlock, isExpression.Location) as DClassLike; if (dc != null) { var udt = DResolver.ResolveBaseClasses(new ClassType(dc, dc, null), ctxt, true) as ClassType; if (r = udt.Base != null && ResultComparer.IsEqual(typeToCheck, udt.Base)) { var l = new List <AbstractType>(); if (udt.Base != null) { l.Add(udt.Base); } if (udt.BaseInterfaces != null && udt.BaseInterfaces.Length != 0) { l.AddRange(udt.BaseInterfaces); } res = new DTuple(isExpression, l); } } break; case DTokens.Const: case DTokens.Immutable: case DTokens.InOut: // TODO? case DTokens.Shared: if (r = typeToCheck.Modifier == isExpression.TypeSpecializationToken) { res = typeToCheck; } break; case DTokens.Return: // TODO: Test IStatement _u = null; var dm = DResolver.SearchBlockAt(ctxt.ScopedBlock, isExpression.Location, out _u) as DMethod; if (dm != null) { var retType_ = TypeDeclarationResolver.GetMethodReturnType(dm, ctxt); if (r = retType_ != null && ResultComparer.IsEqual(typeToCheck, retType_)) { res = retType_; } } break; } return(new Tuple <bool, AbstractType>(r, res)); }
public IDisposable Push(IEditorData editor) { return(Push(DResolver.SearchBlockAt(editor.SyntaxTree, editor.CaretLocation) ?? editor.SyntaxTree, editor.CaretLocation)); }
public static int CalculateForward(IBlockNode module, CodeLocation caret) { return(CalculateBackward(DResolver.SearchBlockAt(module, caret), caret)); }
public static ISyntaxRegion FindCurrentCaretContext(IEditorData editor, out ParserTrackerVariables trackerVariables, ref IBlockNode currentScope, out IStatement currentStatement) { if (currentScope == null) { currentScope = DResolver.SearchBlockAt(editor.SyntaxTree, editor.CaretLocation, out currentStatement); } if (currentScope == null) { trackerVariables = null; currentStatement = null; return(null); } bool ParseDecl = false; int blockStart = 0; var blockStartLocation = currentScope != null ? currentScope.BlockStartLocation : editor.CaretLocation; if (currentScope is DMethod) { var block = (currentScope as DMethod).GetSubBlockAt(editor.CaretLocation); if (block != null) { blockStart = DocumentHelper.GetOffsetByRelativeLocation(editor.ModuleCode, editor.CaretLocation, editor.CaretOffset, blockStartLocation = block.Location); } else { currentScope = currentScope.Parent as IBlockNode; return(FindCurrentCaretContext(editor, out trackerVariables, ref currentScope, out currentStatement)); } } else if (currentScope != null) { if (currentScope.BlockStartLocation.IsEmpty || (editor.CaretLocation < currentScope.BlockStartLocation && editor.CaretLocation > currentScope.Location)) { ParseDecl = true; blockStart = DocumentHelper.GetOffsetByRelativeLocation(editor.ModuleCode, editor.CaretLocation, editor.CaretOffset, blockStartLocation = currentScope.Location); } else { blockStart = DocumentHelper.GetOffsetByRelativeLocation(editor.ModuleCode, editor.CaretLocation, editor.CaretOffset, currentScope.BlockStartLocation); } } if (blockStart >= 0 && editor.CaretOffset - blockStart > 0) { using (var sr = new Misc.StringView(editor.ModuleCode, blockStart, editor.CaretOffset - blockStart)) { var psr = DParser.Create(sr); /* Deadly important! For correct resolution behaviour, * it is required to set the parser virtually to the blockStart position, * so that everything using the returned object is always related to * the original code file, not our code extraction! */ psr.Lexer.SetInitialLocation(blockStartLocation); ISyntaxRegion ret = null; if (currentScope == null) { ret = psr.Parse(); } else if (currentScope is DMethod) { psr.Step(); var dm = currentScope as DMethod; dm.Clear(); if ((dm.SpecialType & DMethod.MethodType.Lambda) != 0 && psr.Lexer.LookAhead.Kind != DTokens.OpenCurlyBrace) { psr.LambdaSingleStatementBody(dm); ret = dm.Body; } else { var methodRegion = DTokens.Body; if (dm.In != null && blockStartLocation == dm.In.Location) { methodRegion = DTokens.In; } if (dm.Out != null && blockStartLocation == dm.Out.Location) { methodRegion = DTokens.Out; } var newBlock = psr.BlockStatement(currentScope); ret = newBlock; switch (methodRegion) { case DTokens.Body: newBlock.EndLocation = dm.Body.EndLocation; dm.Body = newBlock; break; case DTokens.In: newBlock.EndLocation = dm.In.EndLocation; dm.In = newBlock; break; case DTokens.Out: newBlock.EndLocation = dm.Out.EndLocation; dm.Out = newBlock; break; } } } else if (currentScope is DModule) { ret = psr.Root(); } else { psr.Step(); if (ParseDecl) { var ret2 = psr.Declaration(currentScope); if (ret2 != null && ret2.Length > 0) { ret = ret2[0]; } } else if (currentScope is DClassLike) { var t = new DClassLike((currentScope as DClassLike).ClassType); t.AssignFrom(currentScope); t.Clear(); psr.ClassBody(t); ret = t; } else if (currentScope is DEnum) { var t = new DEnum(); t.AssignFrom(currentScope); t.Clear(); psr.EnumBody(t); ret = t; } } currentScope = DResolver.SearchBlockAt(currentScope, psr.Lexer.CurrentToken != null ? psr.Lexer.CurrentToken.EndLocation : editor.CaretLocation, out currentStatement); trackerVariables = psr.TrackerVariables; return(ret); } } trackerVariables = null; currentStatement = null; return(null); }
/// <summary> /// Reparses the given method's fucntion body until the cursor position, /// searches the last occurring method call or template instantiation, /// counts its already typed arguments /// and returns a wrapper containing all the information. /// </summary> public static ArgumentsResolutionResult ResolveArgumentContext( IEditorData Editor, ResolverContextStack ctxt) { ParserTrackerVariables trackVars = null; IStatement curStmt = null; IExpression lastParamExpression = null; // Get the currently scoped block var curBlock = DResolver.SearchBlockAt(Editor.SyntaxTree, Editor.CaretLocation, out curStmt); if (curBlock == null) { return(null); } // Get an updated abstract view on the module's code var parsedStmtBlock = CtrlSpaceCompletionProvider.FindCurrentCaretContext( Editor.ModuleCode, curBlock, Editor.CaretOffset, Editor.CaretLocation, out trackVars) as StatementContainingStatement; if (parsedStmtBlock == null) { return(null); } // Search the returned statement block (i.e. function body) for the current statement var exStmt = BlockStatement.SearchBlockStatement(parsedStmtBlock, Editor.CaretLocation) as IExpressionContainingStatement; lastParamExpression = ExpressionHelper.SearchForMethodCallsOrTemplateInstances(exStmt, Editor.CaretLocation); if (lastParamExpression == null) { // Give it a last chance by handling the lastly parsed object // - which is a TemplateInstanceExpression in quite all cases lastParamExpression = trackVars.LastParsedObject as IExpression; } /* * Then handle the lastly found expression regarding the following points: * * 1) foo( -- normal arguments only * 2) foo!(...)( -- normal arguments + template args * 3) foo!( -- template args only * 4) new myclass( -- ctor call * 5) new myclass!( -- ditto * 6) new myclass!(...)( * 7) mystruct( -- opCall call */ var res = new ArgumentsResolutionResult() { ParsedExpression = lastParamExpression }; // 1), 2) if (lastParamExpression is PostfixExpression_MethodCall) { res.IsMethodArguments = true; var call = (PostfixExpression_MethodCall)lastParamExpression; res.MethodIdentifier = call.PostfixForeExpression; res.ResolvedTypesOrMethods = Evaluation.TryGetUnfilteredMethodOverloads(call.PostfixForeExpression, ctxt, call); if (call.Arguments != null) { int i = 0; foreach (var arg in call.Arguments) { if (Editor.CaretLocation >= arg.Location && Editor.CaretLocation <= arg.EndLocation) { res.CurrentlyTypedArgumentIndex = i; break; } i++; } } } // 3) else if (lastParamExpression is TemplateInstanceExpression) { var templ = (TemplateInstanceExpression)lastParamExpression; res.IsTemplateInstanceArguments = true; res.MethodIdentifier = templ; res.ResolvedTypesOrMethods = Evaluation.GetOverloads(templ, ctxt, null, false); if (templ.Arguments != null) { int i = 0; foreach (var arg in templ.Arguments) { if (Editor.CaretLocation >= arg.Location && Editor.CaretLocation <= arg.EndLocation) { res.CurrentlyTypedArgumentIndex = i; break; } i++; } } } else if (lastParamExpression is PostfixExpression_Access) { var acc = (PostfixExpression_Access)lastParamExpression; res.MethodIdentifier = acc.PostfixForeExpression; res.ResolvedTypesOrMethods = Evaluation.TryGetUnfilteredMethodOverloads(acc.PostfixForeExpression, ctxt, acc); if (res.ResolvedTypesOrMethods == null) { return(res); } if (acc.AccessExpression is NewExpression) { CalculateCurrentArgument(acc.AccessExpression as NewExpression, res, Editor.CaretLocation, ctxt, res.ResolvedTypesOrMethods); } } else if (lastParamExpression is NewExpression) { HandleNewExpression((NewExpression)lastParamExpression, res, Editor, ctxt, curBlock); } /* * alias int function(int a, bool b) myDeleg; * alias myDeleg myDeleg2; * * myDeleg dg; * * dg( -- it's not needed to have myDeleg but the base type for what it stands for * * ISSUE: * myDeleg( -- not allowed though * myDeleg2( -- allowed neither! */ if (res.ResolvedTypesOrMethods != null) { res.ResolvedTypesOrMethods = DResolver.StripAliasSymbols(res.ResolvedTypesOrMethods); } return(res); }
public static INode[] TryFindingSelectedIdImportIndependently(IEditorData ed, out bool importRequired, bool tryResolveNormally = true) { importRequired = false; var l = new List <INode>(); var ctxt = new ResolverContextStack(ed.ParseCache, new ResolverContext()) { ContextIndependentOptions = ResolutionOptions.ReturnMethodReferencesOnly | ResolutionOptions.DontResolveBaseTypes | ResolutionOptions.DontResolveAliases | ResolutionOptions.NoTemplateParameterDeduction }; ctxt.ScopedBlock = DResolver.SearchBlockAt(ed.SyntaxTree, ed.CaretLocation, out ctxt.CurrentContext.ScopedStatement); // Get scoped object. var o = DResolver.GetScopedCodeObject(ed, ctxt, DResolver.AstReparseOptions.AlsoParseBeyondCaret); if (o == null) { throw new Exception("No identifier selected"); } // Try to resolve it using the usual (strictly filtered) way. if (tryResolveNormally) { AbstractType[] t = null; if (o is IExpression) { t = new[] { Evaluation.EvaluateType((IExpression)o, ctxt) } } ; else if (o is ITypeDeclaration) { t = TypeDeclarationResolver.Resolve((ITypeDeclaration)o, ctxt); } if (t != null && t.Length != 0 && t[0] != null) { foreach (var at in t) { if (at is DSymbol) { l.Add(((DSymbol)at).Definition); } } return(l.ToArray()); } } // If no results: // Extract a concrete id from that syntax object. (If access expression/nested decl, use the inner-most one) string id = null; chkAgain: if (o is ITypeDeclaration) { var td = ((ITypeDeclaration)o).InnerMost; if (td is IdentifierDeclaration) { id = ((IdentifierDeclaration)td).Id; } else if (td is TemplateInstanceExpression) { id = ((TemplateInstanceExpression)td).TemplateIdentifier.Id; } } else if (o is IExpression) { var x = (IExpression)o; while (x is PostfixExpression) { x = ((PostfixExpression)x).PostfixForeExpression; } if (x is IdentifierExpression && ((IdentifierExpression)x).IsIdentifier) { id = (string)((IdentifierExpression)x).Value; } else if (x is TemplateInstanceExpression) { id = ((TemplateInstanceExpression)x).TemplateIdentifier.Id; } else if (x is NewExpression) { o = ((NewExpression)x).Type; goto chkAgain; } } if (string.IsNullOrEmpty(id)) { throw new Exception("No extractable identifier found"); } // Rawly scan through all modules' roots of the parse cache to find that id. foreach (var pc in ed.ParseCache) { foreach (var mod in pc) { if (mod.Name == id) { l.Add(mod); } var ch = mod[id]; if (ch != null) { foreach (var c in ch) { var dn = c as DNode; if (dn == null || !dn.ContainsAttribute(DTokens.Package, DTokens.Private, DTokens.Protected)) { l.Add(c); } } } //TODO: Mixins } } importRequired = true; return(l.ToArray()); }
private void UpdatePath(object sender, Mono.TextEditor.DocumentLocationEventArgs e) { var SyntaxTree = Document.GetDAst(); if (SyntaxTree == null) { return; } // Resolve the hovered piece of code var loc = new CodeLocation(Document.Editor.Caret.Location.Column, Document.Editor.Caret.Location.Line); var currentblock = DResolver.SearchBlockAt(SyntaxTree, loc); //could be an enum value, which is not IBlockNode if (currentblock is DEnum) { foreach (INode nd in (currentblock as DEnum).Children) { if ((nd is DEnumValue) && ((nd.Location <= loc) && (nd.EndLocation >= loc))) { currentblock = nd as IBlockNode; break; } } } List <PathEntry> result = new List <PathEntry>(); INode node = currentblock; PathEntry entry; while ((node != null) && ((node is IBlockNode) || (node is DEnumValue))) { var icon = DIcons.GetNodeIcon(node as DNode); entry = new PathEntry(icon.IsNull?null: ImageService.GetIcon(icon.Name, IconSize.Menu), node.Name + DParameterDataProvider.GetNodeParamString(node)); entry.Position = EntryPosition.Left; entry.Tag = node; //do not include the module in the path bar if ((node.Parent != null) && !((node is DNode) && (node as DNode).IsAnonymous)) { result.Insert(0, entry); } node = node.Parent; } if (!((currentblock is DMethod) || (currentblock is DEnumValue))) { PathEntry noSelection = new PathEntry(GettextCatalog.GetString("No Selection")) { Tag = new NoSelectionCustomNode(currentblock) }; result.Add(noSelection); } entry = GetRegionEntry(Document.GetDDocument(), Document.Editor.Caret.Location); if (entry != null) { result.Add(entry); } var prev = CurrentPath; CurrentPath = result.ToArray(); OnPathChanged(new DocumentPathChangedEventArgs(prev)); }
//INode typeNode; //IEnumerable<IAbstractSyntaxTree> moduleCache; public DDebugSymbolWrapper(DebugScopedSymbol sym, DDebugSupport support) : base(sym) { this.supp = support; try { /*var ci=CoreManager.DebugManagement.Engine.Symbols.GetPointerTarget(sym.Offset); * object mo = null; * IntPtr moPtr = new IntPtr(); * var raw = CoreManager.DebugManagement.Engine.Memory.ReadVirtual(ci, 4); * Marshal.StructureToPtr(raw, moPtr, false); * mo = Marshal.PtrToStructure(moPtr, typeof(DObject));*/ } catch { } // Search currently scoped module string file = ""; uint line = 0; CoreManager.DebugManagement.Engine.Symbols.GetLineByOffset(CoreManager.DebugManagement.Engine.CurrentInstructionOffset, out file, out line); codeLine = (int)line; if (string.IsNullOrWhiteSpace(file)) { return; } // If file name found, get syntax tree, as far as possible DProject ownerPrj = null; module = DLanguageBinding.GetFileSyntaxTree(file, out ownerPrj); // If syntax tree built, search the variable location if (module != null) { IStatement stmt = null; var block = DResolver.SearchBlockAt(module, new CodeLocation(0, codeLine), out stmt); var ctxt = ResolutionContext.Create(null, null, block); var res = TypeDeclarationResolver.ResolveIdentifier(Symbol.Name, ctxt, null); if (res != null && res.Length > 0 && res[0] is DSymbol) { variableNode = ((DSymbol)res[0]).Definition; //moduleCache = DCodeCompletionSupport.Instance.EnumAvailableModules(ownerPrj); } } // Set type string _typeString = base.TypeString; if (variableNode != null) { var t = variableNode.Type; if (t != null) { _typeString = t.ToString(); } } // Set value string if (_typeString.StartsWith("class ")) { _valueString = base.ValueString; //CodeInjection.WriteObjectVariable(supp.hProcess, supp.varAddr, (uint)sym.Offset); //_valueString = CodeInjection.EvaluateObjectString(supp.hProcess, supp.toStringFunc, supp.varAddr, (uint)sym.Offset); /* * var th = CodeInjection.BeginExecuteMethod(supp.hProcess, supp.toStringFunc); * * CoreManager.DebugManagement.Engine.Execute("~2 g"); * CoreManager.DebugManagement.Engine.WaitForEvent(); * * CodeInjection.WaitForExecutionEnd(th); */ //_valueString = CodeInjection.ReadDString(supp.hProcess, supp.varAddr); } else { _valueString = base.ValueString; if (variableNode != null) { ITypeDeclaration curValueType = variableNode.Type; if (curValueType != null) { if (!IsBasicType(curValueType)) { if (TypeString == "string") //TODO: Replace this by searching the alias definition in the cache { curValueType = new ArrayDecl() { InnerDeclaration = new DTokenDeclaration(DTokens.Char) } } ; else if (TypeString == "wstring") { curValueType = new ArrayDecl() { InnerDeclaration = new DTokenDeclaration(DTokens.Wchar) } } ; else if (TypeString == "dstring") { curValueType = new ArrayDecl() { InnerDeclaration = new DTokenDeclaration(DTokens.Dchar) } } ; if (IsArray(curValueType)) { var clampDecl = curValueType as ArrayDecl; var valueType = clampDecl.InnerDeclaration; if (valueType is DTokenDeclaration) { bool IsString = false; uint elsz = 0; var realType = DetermineArrayType((valueType as DTokenDeclaration).Token, out elsz, out IsString); var arr = CoreManager.DebugManagement.Engine.Symbols.ReadArray(sym.Offset, realType, elsz); if (arr != null) { _valueString = BuildArrayContentString(arr, IsString); } } } else { //TODO: call an object's toString method somehow to obtain its representing string manually } } } } } }
void UpdateOutlineSelection(object sender, Mono.TextEditor.DocumentLocationEventArgs e) { if (clickedOnOutlineItem || SyntaxTree == null || TreeStore == null) { return; } var caretLocation = Document.Editor.Caret.Location; var caretLocationD = new CodeLocation(caretLocation.Column, caretLocation.Line); var currentblock = DResolver.SearchBlockAt(SyntaxTree, caretLocationD); INode selectedASTNode = null; if (currentblock == null) { return; } foreach (var n in currentblock) { if (caretLocationD >= n.Location && caretLocationD <= n.EndLocation) { selectedASTNode = n; break; } } // Select parameter node if needed if (selectedASTNode == null && currentblock is DMethod) { foreach (var n in (currentblock as DMethod).Parameters) { if (caretLocationD >= n.Location && caretLocationD <= n.EndLocation) { selectedASTNode = n; break; } } } if (selectedASTNode == null) { selectedASTNode = currentblock; } if (selectedASTNode == null) { return; } TreeStore.Foreach((TreeModel model, TreePath path, TreeIter iter) => { var n = model.GetValue(iter, 0); if (n == selectedASTNode) { dontJumpToDeclaration = true; //var parentPath = path.Copy().Up(); TreeView.ExpandToPath(path); TreeView.Selection.SelectIter(iter); dontJumpToDeclaration = false; return(true); } return(false); }); }
static ResolveResult[] HandleIdDeclaration(IdentifierDeclaration typeId, ResolverContext lastResCtxt, IAbstractSyntaxTree SyntaxTree, CodeScanResult csr, Dictionary <string, ResolveResult> compDict) { var typeString = typeId.ToString(); bool WasAlreadyResolved = false; ResolveResult[] allCurrentResults = null; ResolveResult rr = null; /* * string,wstring,dstring are highlighted by the editor's syntax definition automatically.. * Anyway, allow to resolve e.g. "object.string" */ if (typeString == "" || typeString == "string" || typeString == "wstring" || typeString == "dstring") { return(null); } lastResCtxt.ScopedBlock = DResolver.SearchBlockAt(SyntaxTree, typeId.Location, out lastResCtxt.ScopedStatement); if (typeString == "th" && typeId.Location.Line == 114) { } if (!(WasAlreadyResolved = compDict.TryGetValue(typeString, out rr))) { allCurrentResults = DResolver.ResolveType(typeId, lastResCtxt); if (allCurrentResults != null && allCurrentResults.Length > 0) { rr = allCurrentResults[0]; } } if (rr == null) { if (typeId is IdentifierDeclaration) { csr.UnresolvedIdentifiers.Add(typeId as IdentifierDeclaration); } } else { /* * Note: It is of course possible to highlight more than one type in one type declaration! * So, we scan down the result hierarchy for TypeResults and highlight all of them later. */ var curRes = rr; /* * Note: Since we want to use results multiple times, * we at least have to 'update' their type declarations * to ensure that the second, third, fourth etc. occurence of this result * are also highlit (and won't(!) cause an Already-Added-Exception of our finalDict-Array) */ var curTypeDeclBase = typeId as ITypeDeclaration; while (curRes != null) { if (curRes is MemberResult) { var mr = curRes as MemberResult; // If curRes is an alias or a template parameter, highlight it if (mr.ResolvedMember is TemplateParameterNode || (mr.ResolvedMember is DVariable && (mr.ResolvedMember as DVariable).IsAlias)) { try { csr.ResolvedIdentifiers.Add(curTypeDeclBase as IdentifierDeclaration, curRes); } catch { } // See performance reasons //if (curRes != rr && !WasAlreadyResolved && !) compDict.Add(curTypeDeclBase.ToString(), curRes); } } else if (curRes is TypeResult) { // Yeah, in quite all cases we do identify a class via its name ;-) if (curTypeDeclBase is IdentifierDeclaration && !(curTypeDeclBase is DTokenDeclaration) && !csr.ResolvedIdentifiers.ContainsKey(curTypeDeclBase as IdentifierDeclaration)) { csr.ResolvedIdentifiers.Add(curTypeDeclBase as IdentifierDeclaration, curRes); // See performance reasons //if (curRes != rr && !WasAlreadyResolved) compDict.Add(curTypeDeclBase.ToString(), curRes); } } else if (curRes is ModuleResult) { if (curTypeDeclBase is IdentifierDeclaration && !csr.ResolvedIdentifiers.ContainsKey(curTypeDeclBase as IdentifierDeclaration)) { csr.ResolvedIdentifiers.Add(curTypeDeclBase as IdentifierDeclaration, curRes); } } curRes = curRes.ResultBase; curTypeDeclBase = curTypeDeclBase.InnerDeclaration; } } return(allCurrentResults); }