private void AddSkippedNamespaceText( ref CompilationUnitBodyBuilder body, ref SyntaxListBuilder initialBadNodes, CSharpSyntaxNode skippedSyntax) { if (body.Members.Count > 0) { body.Members[body.Members.Count - 1] = AddTrailingSkippedSyntax(body.Members[body.Members.Count - 1], skippedSyntax); } else if (body.Imports.Count > 0) { body.Imports[body.Imports.Count - 1] = AddTrailingSkippedSyntax(body.Imports[body.Imports.Count - 1], skippedSyntax); } else if (body.Package != null) { body.Package = AddTrailingSkippedSyntax(body.Package, skippedSyntax); } else if (body.Annotations.Count > 0) { body.Annotations[body.Annotations.Count - 1] = AddTrailingSkippedSyntax(body.Annotations[body.Annotations.Count - 1], skippedSyntax); } else { if (initialBadNodes == null) { initialBadNodes = this._pool.Allocate(); } initialBadNodes.AddRange(skippedSyntax); } }
internal CompilationUnitSyntax ParseCompilationUnit() { SyntaxListBuilder initialBadNodes = null; var body = new CompilationUnitBodyBuilder(this._pool); try { this.ParseCompilationUnitBody(ref body, ref initialBadNodes, SyntaxKind.CompilationUnit); var eof = this.EatToken(SyntaxKind.EndOfFileToken); var result = _syntaxFactory.CompilationUnit(body.Package, body.Imports, body.Members, eof); if (initialBadNodes != null) { // attach initial bad nodes as leading trivia on first token result = AddLeadingSkippedSyntax(result, initialBadNodes.ToListNode()); this._pool.Free(initialBadNodes); } return(result); } finally { body.Free(this._pool); } }
private static void AddIncompleteMembers(ref SyntaxListBuilder <MemberDeclarationSyntax> incompleteMembers, ref CompilationUnitBodyBuilder body) { if (incompleteMembers.Count > 0) { body.Members.AddRange(incompleteMembers); incompleteMembers.Clear(); } }
private void ReduceIncompleteMembers(ref SyntaxListBuilder <MemberDeclarationSyntax> incompleteMembers, ref CompilationUnitBodyBuilder body, ref SyntaxListBuilder initialBadNodes) { for (int i = 0; i < incompleteMembers.Count; i++) { this.AddSkippedNamespaceText(ref body, ref initialBadNodes, incompleteMembers[i]); } incompleteMembers.Clear(); }
private void ParseCompilationUnitBody(ref CompilationUnitBodyBuilder body, ref SyntaxListBuilder initialBadNodes, SyntaxKind parentKind) { var saveTerm = this._termState; this._termState |= TerminatorState.IsPackageMemberStartOrStop; PackageParts seen = PackageParts.None; bool reportUnexpectedToken = true; var pendingIncompleteMembers = _pool.Allocate <MemberDeclarationSyntax>(); var pendingAnnotations = _pool.Allocate <AnnotationSyntax>(); try { while (true) { switch (this.CurrentToken.Kind) { case SyntaxKind.AtToken: if (this.IsPossibleJavaPackageAnnotations()) { // incomplete members must be processed before we add any nodes to the body: ReduceIncompleteMembers(ref pendingIncompleteMembers, ref body, ref initialBadNodes); this.ParseAnnotationDeclarations(pendingAnnotations); reportUnexpectedToken = true; break; } goto default; case SyntaxKind.PackageKeyword: // incomplete members must be processed before we add any nodes to the body: ReduceIncompleteMembers(ref pendingIncompleteMembers, ref body, ref initialBadNodes); var package = this.ParsePackageDeclaration(ref pendingAnnotations); pendingAnnotations.Clear(); if (seen > PackageParts.Package) { package = this.AddError(package, ErrorCode.ERR_UsingAfterElements); //package 必须在所有using之前 this.AddSkippedNamespaceText(ref body, ref initialBadNodes, package); } else if (seen == PackageParts.Package) { //package 重复 package = this.AddError(package, ErrorCode.ERR_NamespaceUnexpected); this.AddSkippedNamespaceText(ref body, ref initialBadNodes, package); } else { body.Package = package; seen = PackageParts.Package; } reportUnexpectedToken = true; break; case SyntaxKind.ImportKeyword: // incomplete members must be processed before we add any nodes to the body: ReduceIncompleteMembers(ref pendingIncompleteMembers, ref body, ref initialBadNodes); var import = this.ParseJavaImportDeclaration(); if (seen > PackageParts.Imports) { import = this.AddError(import, ErrorCode.ERR_UsingAfterElements); this.AddSkippedNamespaceText(ref body, ref initialBadNodes, import); } else { body.Imports.Add(import); seen = PackageParts.Imports; } reportUnexpectedToken = true; break; case SyntaxKind.EndOfFileToken: // This token marks the end of a namespace body return; default: var memberDeclaration = this.ParseMemberDeclaration(parentKind); if (memberDeclaration == null) { // incomplete members must be processed before we add any nodes to the body: ReduceIncompleteMembers(ref pendingIncompleteMembers, ref body, ref initialBadNodes); // eat one token and try to parse declaration or statement again: var skippedToken = EatToken(); if (reportUnexpectedToken && !skippedToken.ContainsDiagnostics) { skippedToken = this.AddError(skippedToken, ErrorCode.ERR_EOFExpected); // do not report the error multiple times for subsequent tokens: reportUnexpectedToken = false; } this.AddSkippedNamespaceText(ref body, ref initialBadNodes, skippedToken); } else if (memberDeclaration.Kind == SyntaxKind.IncompleteMember && seen < PackageParts.Members) { pendingIncompleteMembers.Add(memberDeclaration); reportUnexpectedToken = true; } else { // incomplete members must be processed before we add any nodes to the body: AddIncompleteMembers(ref pendingIncompleteMembers, ref body); body.Members.Add(memberDeclaration); seen = PackageParts.Members; reportUnexpectedToken = true; } break; } } } finally { this._termState = saveTerm; // adds pending incomplete nodes: AddIncompleteMembers(ref pendingIncompleteMembers, ref body); _pool.Free(pendingIncompleteMembers); _pool.Free(pendingAnnotations); } }