//private bool IsPossibleClassLiteralExpression(bool contextRequiresVariable) //{ // var tk = this.CurrentToken.Kind; // if (tk == SyntaxKind.IdentifierName // && this.PeekToken(1).Kind == SyntaxKind.DotToken // && this.PeekToken(2).Kind == SyntaxKind.ClassKeyword) // { // return true; // } // var resetPoint = this.GetResetPoint(); // try // { // SyntaxToken lastTokenOfType; // ScanTypeFlags st = this.ScanType(out lastTokenOfType); // if (st == ScanTypeFlags.ClassKeywordSuffix) // { // return true; // } // return false; // } // finally // { // this.Reset(ref resetPoint); // this.Release(ref resetPoint); // } //} //private bool IsPossibleQualifiedThisExpression(bool contextRequiresVariable) //{ // var tk = this.CurrentToken.Kind; // if (tk == SyntaxKind.IdentifierName // && this.PeekToken(1).Kind == SyntaxKind.DotToken // && this.PeekToken(1).Kind == SyntaxKind.ClassKeyword) // { // return true; // } // var resetPoint = this.GetResetPoint(); // try // { // SyntaxToken lastTokenOfType; // ScanTypeFlags st = this.ScanType(out lastTokenOfType); // if (st == ScanTypeFlags.ClassKeywordSuffix) // { // return true; // } // return false; // } // finally // { // this.Reset(ref resetPoint); // this.Release(ref resetPoint); // } //} private bool IsPossibleDeclarationExpression(bool contextRequiresVariable) { var tk = this.CurrentToken.Kind; if (SyntaxKindFacts.IsPredefinedType(tk) && tk != SyntaxKind.VoidKeyword && this.PeekToken(1).Kind != SyntaxKind.DotToken) { return(true); } var resetPoint = this.GetResetPoint(); try { SyntaxToken lastTokenOfType; ScanTypeFlags st = this.ScanType(out lastTokenOfType); if (st == ScanTypeFlags.NotType || !this.IsTrueIdentifier()) { return(false); } if (contextRequiresVariable) { // Unless we parse this as a declaration expression, // we'll get binding errors later on. return(true); } switch (st) { case ScanTypeFlags.GenericTypeOrExpression: case ScanTypeFlags.PointerOrMultiplication: int position = 0; SyntaxKind afterIdentifierTokenKind; do { position++; afterIdentifierTokenKind = this.PeekToken(position).Kind; }while (afterIdentifierTokenKind == SyntaxKind.CloseParenToken); // If we have something that looks like a pointer or generic type, followed by an identifier, followed by '[)...][+-*...]=' tokens. // This cannot be a valid non-declaration expression. return(SyntaxKindFacts.IsAssignmentExpressionOperatorToken(afterIdentifierTokenKind)); case ScanTypeFlags.NullableType: // This can be a part of a ConditionalExpression. var resetPoint2 = this.GetResetPoint(); try { var nullCoalescingPrecedence = 2u; //GetPrecedence(SyntaxKind.CoalesceExpression); var colonLeft = this.ParseSubExpression(nullCoalescingPrecedence - 1); if (colonLeft.Kind != SyntaxKind.DeclarationExpression && this.CurrentToken.Kind == SyntaxKind.ColonToken) { return(false); } } finally { this.Reset(ref resetPoint2); this.Release(ref resetPoint2); } break; } // Let's specially handle some error cases. // For example: // Colors? d = Co // Colors c = Colors.Blue; // // We don't want this erroneous code to be parsed as a single statement equivalent to // Colors? d = Co Colors c = Colors.Blue; // Where "Co Colors" is parsed as a Declaration Expression. This would have negative // effect on editing experience. Debug.Assert(this.IsTrueIdentifier()); if (lastTokenOfType.TrailingTrivia.Any(SyntaxKind.EndOfLineTrivia)) { // We have a line break between something that looks like a type and the following identifier. // Can that identifier be a beginning of a local declaration? ScanTypeFlags st2 = this.ScanType(); if (st2 != ScanTypeFlags.NotType && this.IsTrueIdentifier()) { return(false); } } return(true); } finally { this.Reset(ref resetPoint); this.Release(ref resetPoint); } }