in src/Parsing/Impl/Parser.cs [1869:1980]
private FunctionDefinition ParseFuncDef(bool isCoroutine) {
string preWhitespace = null, afterAsyncWhitespace = null;
var start = isCoroutine ? GetStart() : 0;
if (isCoroutine) {
preWhitespace = _tokenWhiteSpace;
}
Eat(TokenKind.KeywordDef);
var keywordEnd = GetEnd();
if (isCoroutine) {
afterAsyncWhitespace = _tokenWhiteSpace;
} else {
preWhitespace = _tokenWhiteSpace;
start = GetStart();
}
var name = ReadName();
var nameExpr = MakeName(name);
var nameWhiteSpace = _tokenWhiteSpace;
var ateLeftParen = name.HasName && Eat(TokenKind.LeftParenthesis);
var parenWhiteSpace = _tokenWhiteSpace;
var lStart = GetStart();
var lEnd = GetEndForStatement();
var grouping = _tokenizer.GroupingLevel;
List<string> commaWhiteSpace = null;
var ateTerminator = false;
var parameters = ateLeftParen ? ParseVarArgsList(TokenKind.RightParenthesis, true, out commaWhiteSpace, out ateTerminator) : null;
var closeParenWhiteSpace = ateTerminator || PeekToken(TokenKind.EndOfFile) ? _tokenWhiteSpace : null;
FunctionDefinition ret;
if (parameters == null) {
// error in parameters
ret = new FunctionDefinition(nameExpr, new Parameter[0]) { IsCoroutine = isCoroutine };
if (_verbatim) {
AddVerbatimName(name, ret);
AddPreceedingWhiteSpace(ret, preWhitespace);
if (afterAsyncWhitespace != null) {
GetNodeAttributes(ret)[FunctionDefinition.WhitespaceAfterAsync] = afterAsyncWhitespace;
}
AddSecondPreceedingWhiteSpace(ret, nameWhiteSpace);
AddThirdPreceedingWhiteSpace(ret, parenWhiteSpace);
AddFourthPreceedingWhiteSpace(ret, closeParenWhiteSpace);
if (!ateTerminator) {
AddErrorMissingCloseGrouping(ret);
}
if (!ateLeftParen) {
AddErrorIsIncompleteNode(ret);
}
}
ret.SetLoc(start, lEnd);
ret.DefIndex = start;
ret.SetKeywordEndIndex(keywordEnd);
return ret;
}
string arrowWhiteSpace = null;
Expression returnAnnotation = null;
if (ateTerminator && MaybeEat(TokenKind.Arrow)) {
arrowWhiteSpace = _tokenWhiteSpace;
var arrStart = GetStart();
returnAnnotation = ParseExpression();
if (!_stubFile && _langVersion.Is2x()) {
ReportSyntaxError(arrStart, returnAnnotation.EndIndex, Resources.ReturnAnnotationsRequire3dotXErrorMsg);//invalid syntax, return annotations require 3.x
}
}
var rStart = GetStart();
var mid = _lookahead.Span.Start;
ret = new FunctionDefinition(nameExpr, parameters);
AddVerbatimName(name, ret);
PushFunction(ret);
// set IsCoroutine before parsing the body to enable use of 'await'
ret.IsCoroutine = isCoroutine;
var body = ParseClassOrFuncBody();
var ret2 = PopFunction();
System.Diagnostics.Debug.Assert(ret == ret2);
ret.SetBody(body);
ret.ReturnAnnotation = returnAnnotation;
// StartIndex may be adjusted later, but we want to keep the def (or
// async) index.
ret.DefIndex = start;
ret.HeaderIndex = mid;
ret.SetKeywordEndIndex(keywordEnd);
if (_verbatim) {
AddPreceedingWhiteSpace(ret, preWhitespace);
if (afterAsyncWhitespace != null) {
GetNodeAttributes(ret)[FunctionDefinition.WhitespaceAfterAsync] = afterAsyncWhitespace;
}
AddSecondPreceedingWhiteSpace(ret, nameWhiteSpace);
AddThirdPreceedingWhiteSpace(ret, parenWhiteSpace);
AddFourthPreceedingWhiteSpace(ret, closeParenWhiteSpace);
AddListWhiteSpace(ret, commaWhiteSpace.ToArray());
if (arrowWhiteSpace != null) {
AddFifthPreceedingWhiteSpace(ret, arrowWhiteSpace);
}
if (!ateTerminator) {
AddErrorMissingCloseGrouping(ret);
}
}
ret.SetLoc(start, body.EndIndex);
return ret;
}