public static DBlockNode UpdateBlockPartly(this DBlockNode bn, string code, int caretOffset, CodeLocation caretLocation, out bool isInsideNonCodeSegment) { isInsideNonCodeSegment = false; // Get the end location of the declaration that appears before the caret. var startLoc = bn.BlockStartLocation; int startDeclIndex; for(startDeclIndex = bn.Children.Count-1; startDeclIndex >= 0; startDeclIndex--) { var n = bn.Children [startDeclIndex]; if (n.EndLocation.Line > 0 && n.EndLocation.Line < caretLocation.Line) { startLoc = --startDeclIndex == -1 ? bn.BlockStartLocation : bn.Children [startDeclIndex].EndLocation; break; } } var startOff = startLoc.Line > 1 ? DocumentHelper.GetOffsetByRelativeLocation (code, caretLocation, caretOffset, startLoc) : 0; // Immediately break to waste no time if there's nothing to parse if (startOff >= caretOffset) return null; // Get meta block stack so they can be registered while parsing //var metaDecls = bn.GetMetaBlockStack (startLoc, true, false); // Parse region from start until caret for maximum efficiency var tempBlock = bn is DEnum ? new DEnum() : new DBlockNode(); tempBlock.BlockStartLocation = startLoc; try{ using (var sv = new StringView (code, startOff, caretOffset - startOff)) using (var p = DParser.Create(sv)) { p.Lexer.SetInitialLocation (startLoc); p.Step (); if(p.laKind == DTokens.OpenCurlyBrace) p.Step(); // Enum bodies if(bn is DEnum) { do { if(p.laKind == DTokens.Comma) p.Step(); var laBackup = p.la; p.EnumValue(tempBlock as DEnum); if(p.la == laBackup) break; } while(!p.IsEOF); } else // Normal class/module bodies { if(p.laKind == DTokens.Module && bn is DModule) tempBlock.Add(p.ModuleDeclaration()); while (!p.IsEOF) { // if (p.laKind == DTokens.CloseCurlyBrace) { p.Step (); /*if (metaDecls.Count > 0) metaDecls.RemoveAt (metaDecls.Count - 1);*/ continue; } p.DeclDef (tempBlock); } } // Update the actual tempBlock as well as methods/other blocks' end location that just appeared while parsing the code incrementally, // so they are transparent to SearchBlockAt var block = tempBlock as IBlockNode; while(block != null && (block.EndLocation.Line < 1 || block.EndLocation == p.la.Location)){ block.EndLocation = new CodeLocation(p.la.Column+1,p.la.Line); if(block.Children.Count == 0) break; block = block.Children[block.Count-1] as IBlockNode; } if(isInsideNonCodeSegment = p.Lexer.endedWhileBeingInNonCodeSequence) return null; tempBlock.EndLocation = new CodeLocation(p.la.Column + 1, p.la.Line); } }catch(Exception ex) { Console.WriteLine (ex.Message); } DoubleDeclarationSilencer.RemoveDoubles(bn, tempBlock); tempBlock.Parent = bn; return tempBlock; }
public static IBlockNode UpdateBlockPartly(this BlockStatement bs, string code, int caretOffset, CodeLocation caretLocation, out bool isInsideNonCodeSegment) { isInsideNonCodeSegment = false; var finalParentMethod = bs.ParentNode as DMethod; var finalStmtsList = bs._Statements; var startLoc = bs.Location; int startStmtIndex; for(startStmtIndex = finalStmtsList.Count-1; startStmtIndex >= 0; startStmtIndex--) { var n = finalStmtsList [startStmtIndex]; if (n.EndLocation.Line > 0 && n.EndLocation.Line < caretLocation.Line) { startLoc = --startStmtIndex == -1 ? bs.Location : finalStmtsList [startStmtIndex].EndLocation; break; } } var startOff = startLoc.Line > 1 ? DocumentHelper.GetOffsetByRelativeLocation (code, caretLocation, caretOffset, startLoc) : 0; if (startOff >= caretOffset) return null; var tempParentBlock = new DMethod();//new DBlockNode(); var tempBlockStmt = new BlockStatement { ParentNode = tempParentBlock }; tempParentBlock.Body = tempBlockStmt; tempBlockStmt.Location = startLoc; tempParentBlock.Location = startLoc; using (var sv = new StringView (code, startOff, caretOffset - startOff)) using (var p = DParser.Create(sv)) { p.Lexer.SetInitialLocation (startLoc); p.Step (); if(p.laKind == DTokens.OpenCurlyBrace) p.Step(); while (!p.IsEOF) { if (p.laKind == DTokens.CloseCurlyBrace) { p.Step (); /*if (metaDecls.Count > 0) metaDecls.RemoveAt (metaDecls.Count - 1);*/ continue; } var stmt = p.Statement (true, false, tempParentBlock, tempBlockStmt); if (stmt != null) tempBlockStmt.Add(stmt); else p.Step(); } tempBlockStmt.EndLocation = new CodeLocation(p.la.Column+1,p.la.Line); tempParentBlock.EndLocation = tempBlockStmt.EndLocation; if(isInsideNonCodeSegment = p.Lexer.endedWhileBeingInNonCodeSequence) return null; } DoubleDeclarationSilencer.RemoveDoubles(finalParentMethod, tempParentBlock); tempParentBlock.Parent = finalParentMethod; //tempParentBlock.Add(new PseudoStaticStmt { Block = tempBlockStmt, ParentNode = tempParentBlock, Location = tempBlockStmt.Location, EndLocation = tempBlockStmt.EndLocation }); return tempParentBlock; }
public static void UpdateBlockPartly(this BlockStatement bs, string code, int caretOffset, CodeLocation caretLocation, out bool isInsideNonCodeSegment) { isInsideNonCodeSegment = false; var finalParentMethod = bs.ParentNode as DMethod; var finalStmtsList = bs._Statements; var startLoc = bs.Location; int startStmtIndex; for(startStmtIndex = finalStmtsList.Count-1; startStmtIndex >= 0; startStmtIndex--) { var n = finalStmtsList [startStmtIndex]; if (n.EndLocation.Line > 0 && n.EndLocation.Line < caretLocation.Line) { startLoc = --startStmtIndex == -1 ? bs.Location : finalStmtsList [startStmtIndex].EndLocation; break; } } var startOff = startLoc.Line > 1 ? DocumentHelper.GetOffsetByRelativeLocation (code, caretLocation, caretOffset, startLoc) : 0; if (startOff >= caretOffset) return; var tempParentBlock = new DMethod (); var tempBlockStmt = new BlockStatement { ParentNode = tempParentBlock }; try{ using (var sv = new StringView (code, startOff, caretOffset - startOff)) using (var p = DParser.Create(sv)) { p.Lexer.SetInitialLocation (startLoc); p.Step (); if(p.laKind == DTokens.OpenCurlyBrace) p.Step(); while (!p.IsEOF) { if (p.laKind == DTokens.CloseCurlyBrace) { p.Step (); /*if (metaDecls.Count > 0) metaDecls.RemoveAt (metaDecls.Count - 1);*/ continue; } var stmt = p.Statement (true, true, tempParentBlock, tempBlockStmt); if(stmt != null) tempBlockStmt.Add(stmt); } tempBlockStmt.EndLocation = new CodeLocation(p.la.Column+1,p.la.Line); if(isInsideNonCodeSegment = p.Lexer.endedWhileBeingInNonCodeSequence) return; } }catch(Exception ex) { Console.WriteLine (ex.Message); } // Remove old statements from startLoc until caretLocation int i = startStmtIndex + 1; while (i < finalStmtsList.Count && finalStmtsList [i].Location < caretLocation) finalStmtsList.RemoveAt (i); // Insert new statements if (tempBlockStmt.EndLocation > bs.EndLocation) bs.EndLocation = tempBlockStmt.EndLocation; foreach (var stmt in tempBlockStmt._Statements) { stmt.ParentNode = finalParentMethod; stmt.Parent = bs; } AssignInStatementDeclarationsToNewParentNode(tempBlockStmt, finalParentMethod); finalStmtsList.InsertRange(startStmtIndex+1, tempBlockStmt._Statements); if (finalParentMethod != null) { var finalParentChildren = finalParentMethod.AdditionalChildren; // Remove old parent block children int startDeclIndex; for(startDeclIndex = finalParentChildren.Count-1; startDeclIndex >= 0; startDeclIndex--) { var n = finalParentChildren [startDeclIndex]; if (n == null) { finalParentChildren.RemoveAt (startDeclIndex); continue; } if (n.Location < startLoc) break; if (n.Location < caretLocation) finalParentChildren.RemoveAt(startDeclIndex); } // Insert new special declarations foreach (var decl in tempParentBlock) decl.Parent = finalParentMethod; finalParentChildren.InsertRange(startDeclIndex+1, tempParentBlock); finalParentMethod.UpdateChildrenArray (); if (bs.EndLocation > finalParentMethod.EndLocation) finalParentMethod.EndLocation = bs.EndLocation; } //TODO: Handle DBlockNode parents? }