in vsintegration/src/FSharp.LanguageService.Base/ExpansionProvider.cs [319:392]
public virtual IVsExpansionFunction GetExpansionFunction(XmlElement xmlFunctionNode, string fieldName) {
string functionName = null;
ArrayList rgFuncParams = new ArrayList();
// first off, get the function string from the node
string function = xmlFunctionNode.InnerText;
if (function == null || function.Length == 0)
return null;
bool inIdent = false;
bool inParams = false;
int token = 0;
// initialize the vars needed for our super-complex function parser :-)
for (int i = 0, n = function.Length; i < n; i++) {
char ch = function[i];
// ignore and skip whitespace
if (!Char.IsWhiteSpace(ch)) {
switch (ch) {
case ',':
if (!inIdent || !inParams)
i = n; // terminate loop
else {
// we've hit a comma, so end this param and move on...
string name = function.Substring(token, i - token);
rgFuncParams.Add(name);
inIdent = false;
}
break;
case '(':
if (!inIdent || inParams)
i = n; // terminate loop
else {
// we've hit the (, so we know the token before this is the name of the function
functionName = function.Substring(token, i - token);
inIdent = false;
inParams = true;
}
break;
case ')':
if (!inParams)
i = n; // terminate loop
else {
if (inIdent) {
// save last param and stop
string name = function.Substring(token, i - token);
rgFuncParams.Add(name);
inIdent = false;
}
i = n; // terminate loop
}
break;
default:
if (!inIdent) {
inIdent = true;
token = i;
}
break;
}
}
}
if (functionName != null && functionName.Length > 0) {
ExpansionFunction func = this.source.LanguageService.CreateExpansionFunction(this, functionName);
if (func != null) {
func.FieldName = fieldName;
func.Arguments = (string[])rgFuncParams.ToArray(typeof(string));
return func;
}
}
return null;
}