SourceChangeList ConstructSourceChangeList() { SourceChangeList result = new SourceChangeList(); int lastPos = 0; do { int beforeLine = this.lineCounter; string beforeText = this.ReadString(); if (this.inputLine != "after") { throw new MalformedSuiteException("Line " + this.lineCounter + ": Expected an 'after' line"); } string afterText = this.ReadString(); SourceChange sc = new SourceChange(); sc.ChangedText = afterText; sc.SourceContext = this.compilationUnit.SourceContext; int beforePos = this.currentDocument.Text.Source.IndexOf(beforeText, lastPos); if (beforePos < 0) { throw new MalformedSuiteException("Line " + beforeLine + ": before text not found"); } sc.SourceContext.StartPos = beforePos; sc.SourceContext.EndPos = lastPos = beforePos + beforeText.Length; result.Add(sc); }while (this.inputLine == "before"); return(result); }
void PerformIncrementalUpdate() { SourceChangeList changes = this.ConstructSourceChangeList(); string expectedOutput = this.GetExpectedOutput(); //perform update Document originalDocument = this.compilationUnit.SourceContext.Document; Document changedDocument = this.currentDocument = this.GetChangedDocument(this.currentDocument, changes); lock (this){ //prevent asynchronous symbol table update event handler from producing output until after CheckUpdatedCompilation has run Compilation updatedCompilation = this.compiler.UpdateSymbolTable(this.compilation, originalDocument, changedDocument, changes, this.errors); this.CheckUpdatedCompilation(this.compilation, updatedCompilation); this.compilation = updatedCompilation; } //Give asynchronous symbol table update events time to complete Thread.Sleep(20); //Get actual output and compare with expected output string actualOutput = this.output.ToString(); if (expectedOutput != actualOutput) { Console.SetOut(this.savedConsoleOut); Console.WriteLine("Test {0} line {1} failed", this.testName, this.lineCounter - 1); Console.WriteLine("Actual output:"); Console.Write(actualOutput); Console.WriteLine("Expected output:"); Console.Write(expectedOutput); this.failures++; } Console.SetOut(new StringWriter(this.output = new StringBuilder())); System.Diagnostics.Debug.Listeners.Remove(this.traceListener); this.traceListener = new System.Diagnostics.TextWriterTraceListener(System.Console.Out); System.Diagnostics.Debug.Listeners.Add(this.traceListener); }
Document GetChangedDocument(Document originalDocument, SourceChangeList changes) { string originalString = originalDocument.Text.Source; StringBuilder sb = new StringBuilder(); int lastPos = 0; for (int i = 0, n = changes.Count; i < n; i++) { SourceChange sc = changes[i]; sb.Append(originalString, lastPos, sc.SourceContext.StartPos - lastPos); sb.Append(sc.ChangedText); lastPos = sc.SourceContext.EndPos; } sb.Append(originalString, lastPos, originalString.Length - lastPos); return(this.compiler.CreateDocument(this.compilationUnit.SourceContext.Document.Name, 1, sb.ToString())); }
Document GetChangedDocument(Document originalDocument, SourceChangeList changes){ string originalString = originalDocument.Text.Source; StringBuilder sb = new StringBuilder(); int lastPos = 0; for (int i = 0, n = changes.Count; i < n; i++){ SourceChange sc = changes[i]; sb.Append(originalString, lastPos, sc.SourceContext.StartPos-lastPos); sb.Append(sc.ChangedText); lastPos = sc.SourceContext.EndPos; } sb.Append(originalString, lastPos, originalString.Length-lastPos); return this.compiler.CreateDocument(this.compilationUnit.SourceContext.Document.Name, 1, sb.ToString()); }
SourceChangeList ConstructSourceChangeList(){ SourceChangeList result = new SourceChangeList(); int lastPos = 0; do{ int beforeLine = this.lineCounter; string beforeText = this.ReadString(); if (this.inputLine != "after") throw new MalformedSuiteException("Line "+this.lineCounter+": Expected an 'after' line"); string afterText = this.ReadString(); SourceChange sc = new SourceChange(); sc.ChangedText = afterText; sc.SourceContext = this.compilationUnit.SourceContext; int beforePos = this.currentDocument.Text.Source.IndexOf(beforeText, lastPos); if (beforePos < 0) throw new MalformedSuiteException("Line "+beforeLine+": before text not found"); sc.SourceContext.StartPos = beforePos; sc.SourceContext.EndPos = lastPos = beforePos + beforeText.Length; result.Add(sc); }while (this.inputLine == "before"); return result; }
/// <summary> /// Updates the specified symbol table, substituting changedDocument for originalDocument. /// Fires the OnSymbolTableUpdate event before returning (provided that changes occurred to member signatures). /// </summary> /// <param name="symbolTable">The symbol table to update or replace.</param> /// <param name="originalDocument">The document of a CompilationUnit instance in compilation.</param> /// <param name="changedDocument">A new version of originalDocument.</param> /// <param name="changes">A list of the changes made to orignalDocument in order to derive changedDocument.</param> /// <param name="errors">A list to which errors detected during the update must be added.</param> /// <returns>The given symbol table instance, suitably updated, or a new symbol table that replaces the given table.</returns> public virtual Compilation UpdateSymbolTable(Compilation symbolTable, Document originalDocument, Document changedDocument, SourceChangeList changes, ErrorNodeList errors){ if (symbolTable == null || symbolTable.TargetModule == null || originalDocument == null || changedDocument == null || changes == null){ Debug.Assert(false); return null; } int changeInLength; SourceContext spanningContextForChanges = this.GetSpanningContext(changes, out changeInLength); CompilationUnitSnippet compilationUnit = null; for (int i = 0, n = symbolTable.CompilationUnits == null ? 0 : symbolTable.CompilationUnits.Count; i < n; i++){ CompilationUnitSnippet cu = symbolTable.CompilationUnits[i] as CompilationUnitSnippet; if (cu != null && cu.SourceContext.Document == originalDocument){ compilationUnit = cu; break; } } if (compilationUnit == null){Debug.Assert(false); return null;} Method meth = compilationUnit.ChangedMethod; if (meth != null){ if (meth.Body != null && meth.Body.SourceContext.Encloses(spanningContextForChanges)){ SourceContext newCtx = this.GetMethodBodyContextInNewDocument(changedDocument, meth.Body.SourceContext, spanningContextForChanges, changeInLength); //Now update the original document so that all nodes that follow method in the source will report their source lines relative to the changedDocument int oldNumLines = meth.Body.SourceContext.EndLine - meth.Body.SourceContext.StartLine; int newNumLines = newCtx.EndLine - newCtx.StartLine; compilationUnit.SourceContext.Document.InsertOrDeleteLines(compilationUnit.OriginalEndPosOfChangedMethod, newNumLines-oldNumLines); //Replace the method body context with the new context meth.Body.SourceContext = newCtx; //Get rid of the body statements (if present) that was constructed from the old context meth.Body.Statements = null; return symbolTable; } return this.FullSymbolTableUpdate(symbolTable, originalDocument, changedDocument, errors); } MemberFinder memFinder = this.CreateMemberFinder(spanningContextForChanges); memFinder.Visit(compilationUnit); meth = memFinder.Member as Method; if (meth != null && meth.Body != null && meth.Body.SourceContext.Encloses(spanningContextForChanges)) return this.IncrementalSymbolTableUpdate(symbolTable, compilationUnit, changedDocument, meth, spanningContextForChanges, changeInLength); else return this.FullSymbolTableUpdate(symbolTable, originalDocument, changedDocument, errors); }
public virtual SourceContext GetSpanningContext(SourceChangeList changes, out int changedLength){ changedLength = 0; int startPos = int.MaxValue; int endPos = int.MinValue; SourceContext result = new SourceContext(); if (changes == null || changes.Count == 0) return result; result = changes[0].SourceContext; for (int i = 0, n = changes.Count; i < n; i++){ SourceContext ctx = changes[i].SourceContext; if (ctx.StartPos < startPos) startPos = ctx.StartPos; if (ctx.EndPos > endPos) endPos = ctx.EndPos; int originalLength = ctx.EndPos - ctx.StartPos; int newLength = changes[i].ChangedText == null ? 0 : changes[i].ChangedText.Length; changedLength += newLength - originalLength; } result.StartPos = startPos; result.EndPos = endPos; return result; }