/// <returns>Either CurrentScope, a BlockStatement object that is associated with the parent method or a complete new DModule object</returns> public static object FindCurrentCaretContext(string code, IBlockNode CurrentScope, int caretOffset, CodeLocation caretLocation, out ParserTrackerVariables TrackerVariables) { bool ParseDecl = false; int blockStart = 0; var blockStartLocation = CurrentScope.BlockStartLocation; if (CurrentScope is DMethod) { var block = (CurrentScope as DMethod).GetSubBlockAt(caretLocation); if (block != null) blockStart = DocumentHelper.LocationToOffset(code, blockStartLocation = block.Location); else return FindCurrentCaretContext(code, CurrentScope.Parent as IBlockNode, caretOffset, caretLocation, out TrackerVariables); } else if (CurrentScope != null) { if (CurrentScope.BlockStartLocation.IsEmpty || caretLocation < CurrentScope.BlockStartLocation && caretLocation > CurrentScope.Location) { ParseDecl = true; blockStart = DocumentHelper.LocationToOffset(code, blockStartLocation = CurrentScope.Location); } else blockStart = DocumentHelper.LocationToOffset(code, CurrentScope.BlockStartLocation); } if (blockStart >= 0 && caretOffset - blockStart > 0) { var codeToParse = code.Substring(blockStart, caretOffset - blockStart); var sr = new StringReader(codeToParse); 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); object ret = null; if (CurrentScope == null || CurrentScope is IAbstractSyntaxTree) ret = psr.Parse(); else if (CurrentScope is DMethod) { psr.Step(); ret = psr.BlockStatement(CurrentScope); } 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 { DBlockNode bn = null; if (CurrentScope is DClassLike) { var t = new DClassLike((CurrentScope as DClassLike).ClassType); t.AssignFrom(CurrentScope); bn = t; } else if (CurrentScope is DEnum) { var t = new DEnum(); t.AssignFrom(CurrentScope); bn = t; } bn.Clear(); psr.ClassBody(bn); ret = bn; } } TrackerVariables = psr.TrackerVariables; sr.Close(); return ret; } TrackerVariables = null; return null; }
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; }