/// <summary> /// Creates a temporary snapshot which contains element before the cross check phase /// Usefull to create a program symboltable without checking nodes. /// For instance : it's used to load all the symbols from every dependencies before running the cross check phase to resolve symbols. /// <param name="useAntlrProgramParsing">Shall ANTLR be used to parse TypeCobol Program, otherwise it will be CUP</param> /// </summary> public void ProduceTemporarySemanticDocument() { lock (lockObjectForTemporarySemanticDocument) { // Capture previous snapshot at one point in time CodeElementsDocument codeElementsDocument = CodeElementsDocumentSnapshot; if (CodeElementsDocumentSnapshot != null && (TemporaryProgramClassDocumentSnapshot == null || TemporaryProgramClassDocumentSnapshot.PreviousStepSnapshot.CurrentVersion != CodeElementsDocumentSnapshot.CurrentVersion)) { // Start perf measurement var perfStatsForParserInvocation = PerfStatsForTemporarySemantic.OnStartRefreshParsingStep(); // Program and Class parsing is not incremental : the objects are rebuilt each time this method is called SourceFile root; List <Diagnostic> newDiagnostics; Dictionary <CodeElement, Node> nodeCodeElementLinkers = new Dictionary <CodeElement, Node>(); //TODO cast to ImmutableList<CodeElementsLine> sometimes fails here ProgramClassParserStep.CupParseProgramOrClass(TextSourceInfo, ((ImmutableList <CodeElementsLine>)codeElementsDocument.Lines), CompilerOptions, CustomSymbols, perfStatsForParserInvocation, out root, out newDiagnostics, out nodeCodeElementLinkers); // Capture the produced results TemporaryProgramClassDocumentSnapshot = new TemporarySemanticDocument(codeElementsDocument, new DocumentVersion <ICodeElementsLine>(this), codeElementsDocument.Lines, root, newDiagnostics, nodeCodeElementLinkers); // Stop perf measurement PerfStatsForTemporarySemantic.OnStopRefreshParsingStep(); } } }
public ProgramClassDocument(CodeElementsDocument previousStepSnapshot, int programClassVersion, Program program, Class classObj, IList<ParserDiagnostic> diagnostics) { TextSourceInfo = previousStepSnapshot.TextSourceInfo; PreviousStepSnapshot = previousStepSnapshot; CurrentVersion = programClassVersion; Program = program; Class = classObj; Diagnostics = diagnostics; }
/// <summary> /// Creates a new snapshot of the document viewed as complete Cobol Program or Class. /// (if the code elements lines changed since the last time this method was called) /// Thread-safe : this method can be called from any thread. /// </summary> public void RefreshProgramClassDocumentSnapshot() { // Make sure two threads don't try to update this snapshot at the same time bool snapshotWasUpdated = false; lock (lockObjectForProgramClassDocumentSnapshot) { // Capture previous snapshot at one point in time CodeElementsDocument codeElementsDocument = CodeElementsDocumentSnapshot; // Check if an update is necessary and compute changes to apply since last version if ((CodeElementsDocumentSnapshot != null) && (ProgramClassDocumentSnapshot == null || ProgramClassDocumentSnapshot.PreviousStepSnapshot.CurrentVersion != codeElementsDocument.CurrentVersion)) { // Start perf measurement var perfStatsForParserInvocation = PerfStatsForProgramClassParser.OnStartRefreshParsingStep(); // Program and Class parsing is not incremental : the objects are rebuilt each time this method is called SourceFile root; IList <ParserDiagnostic> newDiagnostics; Dictionary <CodeElement, Node> nodeCodeElementLinkers = new Dictionary <CodeElement, Node>(); //TODO cast to ImmutableList<CodeElementsLine> sometimes fails here ProgramClassParserStep.ParseProgramOrClass(TextSourceInfo, ((ImmutableList <CodeElementsLine>)codeElementsDocument.Lines), CompilerOptions, CustomSymbols, perfStatsForParserInvocation, out root, out newDiagnostics, out nodeCodeElementLinkers); // Capture the result of the parse in a new snapshot ProgramClassDocumentSnapshot = new ProgramClassDocument( codeElementsDocument, ProgramClassDocumentSnapshot == null ? 0 : ProgramClassDocumentSnapshot.CurrentVersion + 1, root, newDiagnostics, nodeCodeElementLinkers); snapshotWasUpdated = true; // Stop perf measurement PerfStatsForProgramClassParser.OnStopRefreshParsingStep(); } } // Send events to all listeners EventHandler <ProgramClassEvent> programClassChanged = ProgramClassChanged; // avoid race condition EventHandler <ProgramClassEvent> programClassNotChanged = ProgramClassNotChanged; if (snapshotWasUpdated && programClassChanged != null) { programClassChanged(this, new ProgramClassEvent() { Version = ProgramClassDocumentSnapshot.CurrentVersion }); } else if (!snapshotWasUpdated && programClassNotChanged != null) { programClassNotChanged(this, new ProgramClassEvent() { Version = ProgramClassDocumentSnapshot.CurrentVersion }); } }
/// <summary> /// Parse a text that match exactly one code element. /// The type of the code element is compared to the parsed one. /// </summary> /// <param name="compilationUnit"></param> /// <param name="textToParse"></param> /// <param name="correctSyntax"></param> public static Tuple <CodeElementsDocument, T> ParseOneCodeElement <T>(string textToParse, bool correctSyntax = true) where T : CodeElement { CompilationUnit compilationUnit = ParserUtils.ParseCobolString(textToParse); CodeElementsDocument codeElementsDocument = compilationUnit.CodeElementsDocumentSnapshot; Assert.IsTrue(codeElementsDocument.CodeElements.Any()); var firstCodeElement = codeElementsDocument.CodeElements.First(); Assert.IsTrue(firstCodeElement.GetType() == typeof(T)); bool codeElementOk = firstCodeElement.Diagnostics == null || !firstCodeElement.Diagnostics.Any(); bool codeElementDocumentOk = codeElementsDocument.ParserDiagnostics == null || !codeElementsDocument.ParserDiagnostics.Any(); //Do not test compilationUnit.ProgramClassDocumentSnapshot.Diagnostics here because we are just parsing a single line //the semantic phase will produce errors. Assert.IsTrue((codeElementOk && codeElementDocumentOk) == correctSyntax); return(new Tuple <CodeElementsDocument, T>(codeElementsDocument, (T)codeElementsDocument.CodeElements.First())); }
/// <summary> /// Creates a new snapshot of the document viewed as CodeElement objects after parsing. /// (if the processed tokens lines changed since the last time this method was called) /// Thread-safe : this method can be called from any thread. /// </summary> public void RefreshCodeElementsDocumentSnapshot() { // Make sure two threads don't try to update this snapshot at the same time lock (lockObjectForCodeElementsDocumentSnapshot) { // Capture previous snapshots at one point in time ProcessedTokensDocument processedTokensDocument = ProcessedTokensDocumentSnapshot; CodeElementsDocument previousCodeElementsDocument = CodeElementsDocumentSnapshot; // Check if an update is necessary and compute changes to apply since last version bool scanAllDocumentLines = false; IList <DocumentChange <IProcessedTokensLine> > processedTokensLineChanges = null; if (previousCodeElementsDocument == null) { scanAllDocumentLines = true; } else if (processedTokensDocument.CurrentVersion == previousCodeElementsDocument.PreviousStepSnapshot.CurrentVersion) { // Processed tokens lines did not change since last update => nothing to do return; } else { DocumentVersion <IProcessedTokensLine> previousProcessedTokensDocumentVersion = previousCodeElementsDocument.PreviousStepSnapshot.CurrentVersion; processedTokensLineChanges = previousProcessedTokensDocumentVersion.GetReducedAndOrderedChangesInNewerVersion(processedTokensDocument.CurrentVersion); } // Start perf measurement var perfStatsForParserInvocation = PerfStatsForCodeElementsParser.OnStartRefreshParsingStep(); // Track all changes applied to the document while updating this snapshot DocumentChangedEvent <ICodeElementsLine> documentChangedEvent = null; // Apply text changes to the compilation document if (scanAllDocumentLines) { if (processedTokensDocument != null) { // Parse the whole document for the first time CodeElementsParserStep.ParseDocument(TextSourceInfo, ((ImmutableList <CodeElementsLine>)processedTokensDocument.Lines), CompilerOptions, perfStatsForParserInvocation); // Create the first code elements document snapshot CodeElementsDocumentSnapshot = new CodeElementsDocument(processedTokensDocument, new DocumentVersion <ICodeElementsLine>(this), ((ImmutableList <CodeElementsLine>)processedTokensDocument.Lines)); } } else { ImmutableList <CodeElementsLine> .Builder codeElementsDocumentLines = ((ImmutableList <CodeElementsLine>)processedTokensDocument.Lines).ToBuilder(); IList <DocumentChange <ICodeElementsLine> > documentChanges = CodeElementsParserStep.ParseProcessedTokensLinesChanges(TextSourceInfo, codeElementsDocumentLines, processedTokensLineChanges, PrepareDocumentLineForUpdate, CompilerOptions, perfStatsForParserInvocation); // Create a new version of the document to track these changes DocumentVersion <ICodeElementsLine> currentCodeElementsLinesVersion = previousCodeElementsDocument.CurrentVersion; currentCodeElementsLinesVersion.changes = documentChanges; currentCodeElementsLinesVersion.next = new DocumentVersion <ICodeElementsLine>(currentCodeElementsLinesVersion); // Prepare an event to signal document change to all listeners documentChangedEvent = new DocumentChangedEvent <ICodeElementsLine>(currentCodeElementsLinesVersion, currentCodeElementsLinesVersion.next); currentCodeElementsLinesVersion = currentCodeElementsLinesVersion.next; // Update the code elements document snapshot CodeElementsDocumentSnapshot = new CodeElementsDocument(processedTokensDocument, currentCodeElementsLinesVersion, codeElementsDocumentLines.ToImmutable()); } // Stop perf measurement PerfStatsForCodeElementsParser.OnStopRefreshParsingStep(); // Send events to all listeners EventHandler <DocumentChangedEvent <ICodeElementsLine> > codeElementsLinesChanged = CodeElementsLinesChanged; // avoid race condition if (documentChangedEvent != null && codeElementsLinesChanged != null) { codeElementsLinesChanged(this, documentChangedEvent); } } }
public static string DumpCodeElements(CodeElementsDocument result) { return(DumpResult(result.CodeElements, result.ParserDiagnostics)); }
/// <summary> /// Creates a new snapshot of the document viewed as CodeElement objects after parsing. /// (if the processed tokens lines changed since the last time this method was called) /// Thread-safe : this method can be called from any thread. /// </summary> public void RefreshCodeElementsDocumentSnapshot() { // Make sure two threads don't try to update this snapshot at the same time lock (lockObjectForCodeElementsDocumentSnapshot) { // Capture previous snapshots at one point in time ProcessedTokensDocument processedTokensDocument = ProcessedTokensDocumentSnapshot; CodeElementsDocument previousCodeElementsDocument = CodeElementsDocumentSnapshot; // Check if an update is necessary and compute changes to apply since last version bool scanAllDocumentLines = false; IList<DocumentChange<IProcessedTokensLine>> processedTokensLineChanges = null; if (previousCodeElementsDocument == null) { scanAllDocumentLines = true; } else if (processedTokensDocument.CurrentVersion == previousCodeElementsDocument.PreviousStepSnapshot.CurrentVersion) { // Processed tokens lines did not change since last update => nothing to do return; } else { DocumentVersion<IProcessedTokensLine> previousProcessedTokensDocumentVersion = previousCodeElementsDocument.PreviousStepSnapshot.CurrentVersion; processedTokensLineChanges = previousProcessedTokensDocumentVersion.GetReducedAndOrderedChangesInNewerVersion(processedTokensDocument.CurrentVersion); } // Start perf measurement PerfStatsForCodeElementsParser.OnStartRefresh(); // Track all changes applied to the document while updating this snapshot DocumentChangedEvent<ICodeElementsLine> documentChangedEvent = null; // Apply text changes to the compilation document if (scanAllDocumentLines) { // Parse the whole document for the first time CodeElementsParserStep.ParseDocument(TextSourceInfo, ((ImmutableList<CodeElementsLine>)processedTokensDocument.Lines), CompilerOptions); // Create the first code elements document snapshot CodeElementsDocumentSnapshot = new CodeElementsDocument(processedTokensDocument, new DocumentVersion<ICodeElementsLine>(this), ((ImmutableList<CodeElementsLine>)processedTokensDocument.Lines)); } else { ImmutableList<CodeElementsLine>.Builder codeElementsDocumentLines = ((ImmutableList<CodeElementsLine>)processedTokensDocument.Lines).ToBuilder(); IList<DocumentChange<ICodeElementsLine>> documentChanges = CodeElementsParserStep.ParseProcessedTokensLinesChanges(TextSourceInfo, codeElementsDocumentLines, processedTokensLineChanges, PrepareDocumentLineForUpdate, CompilerOptions); // Create a new version of the document to track these changes DocumentVersion<ICodeElementsLine> currentCodeElementsLinesVersion = previousCodeElementsDocument.CurrentVersion; currentCodeElementsLinesVersion.changes = documentChanges; currentCodeElementsLinesVersion.next = new DocumentVersion<ICodeElementsLine>(currentCodeElementsLinesVersion); // Prepare an event to signal document change to all listeners documentChangedEvent = new DocumentChangedEvent<ICodeElementsLine>(currentCodeElementsLinesVersion, currentCodeElementsLinesVersion.next); currentCodeElementsLinesVersion = currentCodeElementsLinesVersion.next; // Update the code elements document snapshot CodeElementsDocumentSnapshot = new CodeElementsDocument(processedTokensDocument, currentCodeElementsLinesVersion, codeElementsDocumentLines.ToImmutable()); } // Stop perf measurement PerfStatsForCodeElementsParser.OnStopRefresh(); // Send events to all listeners EventHandler<DocumentChangedEvent<ICodeElementsLine>> codeElementsLinesChanged = CodeElementsLinesChanged; // avoid race condition if (documentChangedEvent != null && codeElementsLinesChanged != null) { codeElementsLinesChanged(this, documentChangedEvent); } } }