/// <summary> /// Adds an <see cref="ILSLReadOnlyCodeStatement" /> to the <see cref="LSLCodeSegment" /> object. /// </summary> /// <param name="statement">The <see cref="ILSLReadOnlyCodeStatement" /> to add.</param> /// <exception cref="ArgumentNullException"><paramref name="statement"/> is <c>null</c>.</exception> public virtual void AddStatement(ILSLReadOnlyCodeStatement statement) { if (statement == null) { throw new ArgumentNullException("statement"); } EndNode = statement; if (StartNode == null) { StartNode = statement; if (statement.SourceRangesAvailable) { SourceRange = new LSLSourceCodeRange(statement); SourceRangeAvailable = true; } else { SourceRangeAvailable = false; } _statementNodes.Add(statement); } else { _statementNodes.Add(statement); if (SourceRangeAvailable) { SourceRange = new LSLSourceCodeRange(SourceRange, EndNode.SourceRange); } } }
/// <summary> /// Create an <see cref="LSLExpressionListNode" /> by cloning from another. /// </summary> /// <param name="other">The other node to clone from.</param> /// <exception cref="ArgumentNullException"><paramref name="other" /> is <c>null</c>.</exception> private LSLExpressionListNode(LSLExpressionListNode other) { if (other == null) { throw new ArgumentNullException("other"); } ListType = other.ListType; foreach (var expr in other._expressions) { Add(expr.Clone()); } SourceRangesAvailable = other.SourceRangesAvailable; if (SourceRangesAvailable) { SourceRange = other.SourceRange; foreach (var commaRange in other.SourceRangeCommaList) { _sourceRangeCommaList.Add(commaRange); } } HasErrors = other.HasErrors; }
/// <summary> /// Creates a reference to VariableNode by cloning and setting its <see cref="LSLVariableNode.SourceRange" /> /// to that of <paramref name="referenceToken" /> /// </summary> /// <param name="referenceToken">The variable reference token from the parser</param> /// <returns>VariableNode cloned, with its <see cref="LSLVariableNode.SourceRange" /> set</returns> /// <exception cref="ArgumentNullException"><paramref name="referenceToken" /> is <c>null</c>.</exception> internal LSLVariableNode CreateReference(IToken referenceToken) { if (referenceToken == null) { throw new ArgumentNullException("referenceToken"); } var v = VariableNode.Clone(); v.SourceRange = new LSLSourceCodeRange(referenceToken); _references.Add(v); return(v); }
static void Main() { Console.WriteLine("Enter length"); int length = int.Parse(Console.ReadLine()); GenericArray<string> sentence = new GenericArray<string>(length); //GenericArray<int> array = new GenericArray<int>(length); Console.WriteLine("Elements of GenericArray\r\n{0}", sentence.ToString()); Console.WriteLine("Enter element to add"); sentence.Add(Console.ReadLine()); Console.WriteLine("Elements of GenericArray\r\n{0}", sentence.ToString()); Console.WriteLine("Enter element to insert"); string insertElement = Console.ReadLine(); Console.WriteLine("Enter position"); int insertIndex = int.Parse(Console.ReadLine()); sentence.Insert(insertIndex, insertElement); Console.WriteLine("Elements of GenericArray\r\n{0}", sentence.ToString()); Console.WriteLine("Enter element position to be removed"); int removeIndex = int.Parse(Console.ReadLine()); sentence.Remove(removeIndex); Console.WriteLine("Elements of GenericArray\r\n{0}", sentence.ToString()); Console.WriteLine("Enter element to find"); string findElement = Console.ReadLine(); Console.WriteLine("This element is on position {0}", sentence.Find(findElement)); Console.WriteLine("Enter element position to be printed"); int printIndex = int.Parse(Console.ReadLine()); Console.WriteLine("The element is {0}", sentence[printIndex]); sentence.Clear(); Console.WriteLine("Elements of GenericArray.Clear()\r\n{0}", sentence.ToString()); }
/// <summary> /// Add a new parameter to the function signature object /// </summary> /// <param name="parameterSignature">The <see cref="LSLParameterSignature" /> object to add to the signature.</param> /// <exception cref="ArgumentException">Thrown if more than one variadic parameter is added to the function signature.</exception> /// <exception cref="ArgumentNullException"><paramref name="parameterSignature"/> is <c>null</c>.</exception> public void AddParameter(LSLParameterSignature parameterSignature) { if (parameterSignature == null) { throw new ArgumentNullException("parameterSignature"); } if (parameterSignature.Variadic) { if (!HasVariadicParameter) { HasVariadicParameter = true; VariadicParameterIndex = _parameters.Count; } else { throw new ArgumentException( GetType().FullName + ": Signature already has a variadic parameter, cannot add another", "parameterSignature"); } } _parameters.Add(new LSLParameterSignature(parameterSignature, _parameters.Count)); }
private static GenericArray <ScriptLibrary> OpenFirestormScriptLibrarys() { var firestormScriptLibraries = new GenericArray <ScriptLibrary>(); while ( MessageBox.Show( "Select additional firestorm scriptlibrary_* data to draw documentation from or click no to continue.", "Select Firestorm Library Data", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes) { var dialog = new OpenFileDialog { Filter = "Firestorm Highlight File (*.xml) | *.xml", CheckFileExists = true, Multiselect = true }; dialog.ShowDialog(); var xmlReaderSettings = new XmlReaderSettings { CloseInput = true }; foreach (var filename in dialog.FileNames) { using (var reader = XmlReader.Create(File.OpenRead(filename), xmlReaderSettings)) { firestormScriptLibraries.Add(ScriptLibrary.Read(reader)); } } } return(firestormScriptLibraries); }
/// <summary> /// Adds an <see cref="LSLEventHandlerNode" /> as a child of this state scope node. /// </summary> /// <param name="node">The event handler node to add.</param> /// <exception cref="ArgumentNullException"></exception> public void Add(LSLEventHandlerNode node) { if (node == null) { throw new ArgumentNullException("node"); } node.Parent = this; _eventHandlers.Add(node); }
private void BlockComment_action(RuleContext _localctx, int actionIndex) { switch (actionIndex) { case 0: var lineData = CountStringLines(this.TokenStartColumn, this.Text); _comments.Add(new LSLComment( this.Text, LSLCommentType.Block, new LSLSourceCodeRange( this.TokenStartLine, this.TokenStartColumn, this.TokenStartLine + lineData.Lines, lineData.EndColumn, this.TokenStartCharIndex, this.Text.Length + this.TokenStartCharIndex) )); break; } }
/// <summary> /// Adds a new expression to the expression list node. /// </summary> /// <param name="node">The expression node to add to the expression list.</param> /// <exception cref="ArgumentNullException">Thrown if the 'node' parameter is <c>null</c>.</exception> public void Add(ILSLExprNode node) { if (node == null) { throw new ArgumentNullException("node"); } node.Parent = this; _expressions.Add(node); }
/// <summary> /// Add a state declaration node to this compilation unit node. /// </summary> /// <param name="declaration">The state declaration node to add.</param> /// <exception cref="ArgumentNullException">Thrown if the 'declaration' parameter is <c>null</c>.</exception> public void Add(LSLStateScopeNode declaration) { if (declaration == null) { throw new ArgumentNullException("declaration"); } declaration.Parent = this; _addCounter++; _stateDeclarations.Add(declaration); }
/// <summary> /// Add an <see cref="LSLParameterSignature" /> object to this event signatures /// </summary> /// <param name="parameterSignature">The <see cref="LSLParameterSignature" /> object to add.</param> /// <exception cref="ArgumentException">Thrown if the added parameter is a variadic parameter.</exception> /// <exception cref="ArgumentNullException"><paramref name="parameterSignature"/> is <c>null</c>.</exception> public void AddParameter(LSLParameterSignature parameterSignature) { if (parameterSignature == null) { throw new ArgumentNullException("parameterSignature"); } if (parameterSignature.Variadic) { throw new ArgumentException( GetType().FullName + ": Cannot add variadic parameters to an event signature", "parameterSignature"); } _parameters.Add(new LSLParameterSignature(parameterSignature, _parameters.Count)); }
/// <summary> /// Add a function declaration node to this compilation unit node. /// </summary> /// <param name="declaration">The function declaration node to add.</param> /// <exception cref="ArgumentNullException">Thrown if the 'declaration' parameter is <c>null</c>.</exception> public void Add(LSLFunctionDeclarationNode declaration) { if (declaration == null) { throw new ArgumentNullException("declaration"); } declaration.Parent = this; if (_globalVariableDeclarations.Count > 0) { _globalVariableDeclarations.Last().IsLastStatementInScope = false; } _addCounter++; _functionDeclarations.Add(declaration); }
/// <summary> /// Adds a <see cref="JumpsToHere" /> reference from a given <see cref="LSLJumpStatementNode" /> /// </summary> /// <param name="jump"></param> public void AddJumpToHere(LSLJumpStatementNode jump) { _jumpsToHere.Add(jump); }
/// <summary> /// Validates the specified constructor signature string. /// It expects a constructor signature string which starts at the first parenthesis after the constructor's name /// identifier. /// </summary> /// <param name="input">The constructor signature string.</param> /// <param name="validateTypeCallback"> /// The validate type callback, used for additional custom validation of parameter types /// in the constructor signature. /// </param> /// <returns>A parse/validation results object. <see cref="CSharpConstructorSignatureValidationResult" /></returns> /// <exception cref="System.ArgumentNullException">Thrown if <paramref name="input" /> is <c>null</c>.</exception> public static CSharpConstructorSignatureValidationResult Validate(string input, CSharpParsedTypeValidateTypeCallback validateTypeCallback = null) { if (input == null) { throw new ArgumentNullException("input", "Constructor signature string cannot be null!"); } var result = new CSharpConstructorSignatureValidationResult { Success = true, ParameterForwarding = CSharpConstructorParameterForwarding.None }; if (string.IsNullOrWhiteSpace(input)) { result.Success = false; result.ErrorDescription = "Constructor signature cannot be whitespace."; return(result); } States state = States.Start; string accum = ""; var parameterTypes = new GenericArray <CSharpClassNameValidationResult>(); var parameterNames = new HashSet <string>(); var forwardedParameters = new GenericArray <string>(); int unclosedGenericsBrackets = 0; //weeeeeeeeeeeeeeee! for (int index = 0; index < input.Length; index++) { var c = input[index]; accum += c; if (c == '(') { switch (state) { case States.Start: state = States.WaitingForParamType; accum = ""; continue; case States.AccumulatingForwardingKeyword: switch (accum) { case "base(": result.ParameterForwarding = CSharpConstructorParameterForwarding.Base; break; case "this(": result.ParameterForwarding = CSharpConstructorParameterForwarding.This; break; default: result.Success = false; result.ErrorDescription = "Constructor forwarding keyword must be 'base' or 'this'."; result.ErrorIndex = index - 5; return(result); } accum = ""; state = States.WaitingForForwardedParam; continue; case States.AfterForwardingKeyword: state = States.WaitingForForwardedParam; accum = ""; continue; default: result.Success = false; result.ErrorDescription = "Unexpected opening parenthesis."; result.ErrorIndex = index; return(result); } } if (c == ':') { if (state == States.EndOfBasicSignature) { accum = ""; state = States.WaitingForForwardingKeyword; continue; } result.Success = false; result.ErrorDescription = "CSharpIDValidator.IsValidIdentifier:' character."; result.ErrorIndex = index; return(result); } if (c == '<') { if (state == States.AccumulatingParamType) { unclosedGenericsBrackets++; state = States.AccumulatingGenericType; continue; } if (state == States.AccumulatingGenericType) { unclosedGenericsBrackets++; continue; } result.Success = false; result.ErrorDescription = "CSharpIDValidator.IsValidIdentifier<' character."; result.ErrorIndex = index; return(result); } if (c == '>') { if (state == States.AccumulatingGenericType) { unclosedGenericsBrackets--; if (unclosedGenericsBrackets == 0) { state = States.AccumulatingParamType; } continue; } result.Success = false; result.ErrorDescription = "CSharpIDValidator.IsValidIdentifier>' character."; result.ErrorIndex = index; return(result); } if (c == ',' || c == ')') { switch (state) { case States.WaitingForParamType: if (parameterTypes.Count > 0 || (parameterTypes.Count == 0 && c == ',')) { result.Success = false; result.ErrorDescription = "Missing parameter declaration."; result.ErrorIndex = index - 1; return(result); } accum = ""; state = States.EndOfBasicSignature; continue; case States.WaitingForForwardedParam: if (forwardedParameters.Count > 0 || (forwardedParameters.Count == 0 && c == ',')) { result.Success = false; result.ErrorDescription = "Missing forwarded argument declaration."; result.ErrorIndex = index; return(result); } accum = ""; state = States.EndOfForwardingSignature; continue; case States.AccumulatingParamType: result.Success = false; result.ErrorDescription = "Missing parameter name."; result.ErrorIndex = index; return(result); case States.AccumulatingParamName: { var pname = accum.TrimEnd(',', ')').Trim(); if (!CSharpIDValidator.IsValidIdentifier(pname)) { result.Success = false; result.ErrorDescription = string.Format("Invalid parameter name '{0}'.", pname); result.ErrorIndex = index - accum.Length; return(result); } if (!parameterNames.Contains(pname)) { parameterNames.Add(pname); } else { result.Success = false; result.ErrorDescription = string.Format("Parameter name '{0}' used more than once.", pname); result.ErrorIndex = index - accum.Length; return(result); } accum = ""; state = c == ',' ? States.WaitingForParamType : States.EndOfBasicSignature; continue; } case States.AccumulatingForwardedParam: { var pname = accum.TrimEnd(',', ')').Trim(); if (!CSharpIDValidator.IsValidIdentifier(pname)) { result.Success = false; result.ErrorDescription = string.Format( "Invalid forwarded parameter '{0}', invalid identifier syntax.", pname); result.ErrorIndex = index - accum.Length; return(result); } if (!parameterNames.Contains(pname)) { result.Success = false; result.ErrorDescription = string.Format( "Invalid forwarded parameter '{0}', name was not previously declared.", pname); result.ErrorIndex = index - accum.Length; return(result); } forwardedParameters.Add(pname); accum = ""; state = c == ',' ? States.WaitingForForwardedParam : States.EndOfForwardingSignature; continue; } default: if (c == ',' && state == States.AccumulatingGenericType) { continue; } result.Success = false; result.ErrorDescription = string.Format( "CSharpIDValidator.IsValidIdentifier{0}' character.", c); result.ErrorIndex = index; return(result); } } if (!char.IsWhiteSpace(c)) { switch (state) { case States.EndOfBasicSignature: case States.EndOfForwardingSignature: result.Success = false; result.ErrorDescription = string.Format("Unexpected character '{0}' after signature.", c); result.ErrorIndex = index; return(result); case States.Start: result.Success = false; result.ErrorDescription = string.Format("Unexpected character '{0}', was expecting '('.", c); result.ErrorIndex = index; return(result); case States.WaitingForParamType: state = States.AccumulatingParamType; accum = "" + c; continue; case States.WaitingForParameterName: state = States.AccumulatingParamName; accum = "" + c; continue; case States.WaitingForForwardingKeyword: state = States.AccumulatingForwardingKeyword; accum = "" + c; continue; case States.WaitingForForwardedParam: state = States.AccumulatingForwardedParam; accum = "" + c; continue; } } if (char.IsWhiteSpace(c)) { switch (state) { case States.WaitingForParamType: case States.WaitingForParameterName: case States.EndOfBasicSignature: case States.WaitingForForwardingKeyword: case States.AfterForwardingKeyword: case States.WaitingForForwardedParam: accum = ""; continue; case States.AccumulatingForwardingKeyword: switch (accum) { case "base ": result.ParameterForwarding = CSharpConstructorParameterForwarding.Base; break; case "this ": result.ParameterForwarding = CSharpConstructorParameterForwarding.This; break; default: result.Success = false; result.ErrorDescription = "Constructor forwarding keyword must be 'base' or 'this'."; result.ErrorIndex = index - 5; return(result); } accum = ""; state = States.AfterForwardingKeyword; continue; case States.AccumulatingParamType: var ptype = accum.TrimEnd(); var validateParameter = CSharpClassNameValidator.ValidateInitialization(accum.TrimEnd(), true, validateTypeCallback); if (!validateParameter.Success) { result.Success = false; result.ErrorDescription = string.Format("Invalid parameter type '{0}': {1}", ptype, validateParameter.ErrorDescription); result.ErrorIndex = (index - accum.Length) + validateParameter.ErrorIndex + 1; return(result); } parameterTypes.Add(validateParameter); state = States.WaitingForParameterName; accum = ""; continue; } } } if (state != States.EndOfBasicSignature && state != States.EndOfForwardingSignature) { result.Success = false; result.ErrorDescription = "Incomplete constructor signature."; result.ErrorIndex = input.Length - 1; return(result); } result.ParameterTypes = parameterTypes; result.ParameterNames = parameterNames.ToGenericArray(); result.ForwardedParameters = forwardedParameters; return(result); }
private IEnumerable <LSLLibraryFunctionSignature> ModuleMethods(Type containerType) { const BindingFlags bindingFlags = BindingFlags.Default | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic; if (ScriptModuleConstantAttribute == null) { yield break; } var methods = containerType.GetMethods(bindingFlags) .Where(x => x.GetCustomAttributes(ScriptModuleFunctionAttribute, true).Any()); var subsets = _subsetsMap[containerType]; foreach (var v in methods) { var returnType = LslTypeFromCsharpType(v.ReturnType); var pTypes = new GenericArray <LSLParameterSignature>(); foreach (var p in v.GetParameters().Skip(2)) { var isVariadic = IsParams(p); if (p.ParameterType == (typeof(object[])) && isVariadic) { pTypes.Add(new LSLParameterSignature(LSLType.Void, p.Name, true)); goto omitRestOfParameters; } if (isVariadic) { Log.WriteLineWithHeader("[OpenSimLibraryDataReflector]: ", "Optional script module function {0} of type {1}, variadic parameter {2} is an un-recognized data type ({3}), function omitted", v.Name, containerType.Name, p.Name, p.ParameterType.Name); goto omitFunction; } var type = LslTypeFromCsharpParameterType(p.ParameterType); if (type != null) { pTypes.Add(new LSLParameterSignature(type.Value, p.Name, false)); } else { Log.WriteLineWithHeader("[OpenSimLibraryDataReflector]: ", "Optional script module function {0} of type {1}, parameter {2} is an un-recognized data type ({3}), function omitted", v.Name, containerType.Name, p.Name, p.ParameterType.Name); goto omitFunction; } } omitRestOfParameters: if (returnType != null) { var f = new LSLLibraryFunctionSignature(returnType.Value, v.Name, pTypes); f.DocumentationString = _documentationProvider.DocumentFunction(f); f.Subsets.SetSubsets(subsets); f.ModInvoke = true; yield return(f); } else { Log.WriteLineWithHeader("[OpenSimLibraryDataReflector]: ", "Optional script module {0} of type {1} return type is an un-recognized data type ({2})", v.Name, containerType.Name, v.ReturnType.Name); } omitFunction: ; } }
public void AddProvider(IDocumentationProvider p) { _providers.Add(p); }
public void AddProvider(ILibraryData p) { _providers.Add(p); }
static void Main(string[] args) { try { #region TestUsageOfOperatorOverload Rettangolo A = new Rettangolo(3, 4); Rettangolo B = new Rettangolo(5, 5); Rettangolo C = A + B; Console.WriteLine("Area rettangolo A ({0}x{1}): {2}\nArea rettangolo B ({3}x{4}): {5}\nArea A+B ({6}x{7}): {8}", A.L, A.H, A.GetArea(), B.L, B.H, B.GetArea(), C.L, C.H, C.GetArea()); #endregion #region TestOfUsageOfDelegateFunction Utility.Separatore(); Console.WriteLine("Test di utilizzo di una funzione delegata:"); NumberChanger NC1 = new NumberChanger(TestDelegate.AddNum); NumberChanger NC2 = new NumberChanger(TestDelegate.MultNum); Console.WriteLine("- valore iniziale: {0}", TestDelegate.GetNum()); int plus = 25; NC1(plus); Console.WriteLine("- dopo aggiunta di {0}: {1}", plus, TestDelegate.GetNum()); int multi = 5; NC2(multi); Console.WriteLine("- dopo moltiplicazione per {0}: {1}", multi, TestDelegate.GetNum()); /* resetto il numero */ NC2(0); Console.WriteLine("- dopo aver resettato il numero: {0}", TestDelegate.GetNum()); NumberChanger NC; NC = NC1 + NC2; NC(5); Console.WriteLine("- dopo multicasting (NC = NC1 + NC2): {0}", TestDelegate.GetNum()); Console.WriteLine(); Console.WriteLine("Altro test di utilizzo di un delegato:"); string SDel = "Logga questo"; PrintString PSO = new PrintString(TestDelegateLog.VideoOutput); PrintString PSF = new PrintString(TestDelegateLog.FileOutput); PrintString Log = PSO + PSF; Log(SDel); Console.WriteLine("(la stringa qui sopra è stata mostrata a video e loggata in un file simultaneamente attraverso l'utilizzo di un delegato multicast)"); NumberPrinter NP = delegate(int n) { Console.WriteLine("Altro test: il numero {0} è stato scritto con un delegato anonimo!", n); }; NP(0); NP(1); NP(2); #endregion #region TestOfUsageOfEvents Utility.Separatore(); Console.WriteLine("Test di utilizzo di eventi (con delegati):"); EventTest EV = new EventTest(); EV.OnPrint += EventTest_OnPrint; EV.Print("Uallabalooza"); #endregion #region TestOfUsageOfGenerics Utility.Separatore(); GenericArray <string> SArr = new GenericArray <string>(5); Console.WriteLine("Test di utilizzo dei GENERICS di tipo \"{0}\":", SArr.TypeOf()); SArr.Add(0, "Ualla"); SArr.Add(1, "Balooza"); SArr.Add(2, "In"); SArr.Add(3, "The"); SArr.Add(4, "Sky"); for (var i = 0; i < SArr.Size; i++) { Console.WriteLine("- indice {0}: \"{1}\"", i, SArr.Get(i)); } #endregion #region TestOfUsageOfUnsafeCode /* i puntatori vanno usati solo nei blocchi di codice "unsafe"; * puoi dichiarare unsafe anche una funzione o un metodo, se deve usare puntatori; * occorre permettere la compilazione di codice unsafe dalle impostazioni del progetto */ unsafe { Utility.Separatore(); Console.WriteLine("Test di utilizzo di puntatori in codice UNSAFE:"); int SUns = 12345; int *pSUns = &SUns; Console.WriteLine("- valore: {0}", SUns); Console.WriteLine("- valore da puntatore: {0}", pSUns->ToString()); Console.WriteLine("- indirizzo della variabile: {0}", (int)pSUns); Console.WriteLine(); int SUns2 = 54321; int *pSUns2 = &SUns2; Console.WriteLine("Prima dello SWAP dei due puntatori: {0} - {1}", SUns, SUns2); Swap(pSUns, pSUns2); Console.WriteLine("Dopo lo SWAP dei due puntatori: {0} - {1}", SUns, SUns2); Console.WriteLine(); Console.WriteLine("Test di accesso array con puntatori:"); int[] Arr = new int[] { 10, 20, 30 }; fixed(int *pArr = Arr) for (int i = 0; i < Arr.Length; i++) { Console.WriteLine("- Indirizzo di Arr[{0}]: {1}; Valore di Arr[{0}]: {2}", i, (int)(pArr + i), *(pArr + i)); } } #endregion #region TestOfUsageOfThreads Utility.Separatore(); Console.WriteLine("Test di utilizzo dei THREAD"); Thread TH = Thread.CurrentThread; TH.Name = "ThreadMain"; Console.WriteLine("Nome del thread corrente: {0}", TH.Name); ThreadStart TS = new ThreadStart(ThreadSingolo); Console.WriteLine("Creazione in corso di un thread figlio..."); Thread Child = new Thread(TS); Child.Start(); int SleepTime = 5000; Console.WriteLine("Metto in pausa per {0} secondi...", SleepTime / 1000); Thread.Sleep(SleepTime); Console.WriteLine("Riprendo l'esecuzione!"); /*Console.WriteLine("Esco dall'esecuzione del thread (metodo Abort())..."); * Child.Abort();*/ /* non usare Child.Abort! usa Child.Interrupt quando è in stato di sleep-wait-join */ #endregion } #region catch /*catch(ThreadAbortException e) * { * Console.WriteLine("Thread distrutto! (metodo Abort())"); * }*/ catch (Exception e) { Utility.MostraEccezione <Exception>(e); } #endregion Console.ReadKey(); }
/// <summary> /// Parses and validates a string as a CSharp method call. /// </summary> /// <param name="signature">The method call signature, without a semi-colon at the end.</param> /// <returns>A parse/validation results object. <see cref="CSharpFunctionCallValidationResult" /></returns> /// <exception cref="ArgumentNullException"><paramref name="signature"/> is <c>null</c>.</exception> public static CSharpFunctionCallValidationResult Validate(string signature) { if (signature == null) { throw new ArgumentNullException("signature"); } var result = new CSharpFunctionCallValidationResult { Success = true }; var explicitGenericParameters = new GenericArray <CSharpClassNameValidationResult>(); var parameters = new GenericArray <CSharpParameterSignature>(); var lastModifier = CSharpParameterModifier.None; var state = States.WaitingForFirstCharacter; var stateBeforeBrackets = new Stack <States>(); var stateBeforeGenericTypePart = new Stack <States>(); var stateBeforeParenthesis = new Stack <States>(); var stateBeforeCurlyBraces = new Stack <States>(); string accum = ""; int unmatchedGenericBrackets = 0; int unmatchedParenthesis = 0; int unmatchedCurlyBraces = 0; int unmatchedBrackets = 0; string methodName = ""; for (int index = 0; index < signature.Length; index++) { var c = signature[index]; accum += c; if (c == 'o' || c == 'r' || c == 'n') { int wordBoundry = index + 2; int ahead = wordBoundry + 1; if (wordBoundry >= signature.Length) { goto afterRefOutChecks; } var lookAhead = signature.Substring(index, 3); var lookAheadAssertion = lookAhead == "out" || lookAhead == "ref" || lookAhead == "new"; if (ahead < signature.Length && !char.IsWhiteSpace(signature[ahead])) { goto afterRefOutChecks; } if (lookAheadAssertion && state == States.WaitingForParameterName && lastModifier == CSharpParameterModifier.None) { lastModifier = lookAhead == "out" ? CSharpParameterModifier.Out : (lookAhead == "ref" ? CSharpParameterModifier.Ref : CSharpParameterModifier.New); accum = ""; index = wordBoundry; state = States.WaitingForParameterName; continue; } } afterRefOutChecks: if (c == '[') { if (state == States.AccumulatingParameter || state == States.WaitingForParameterName) { stateBeforeBrackets.Push(States.AccumulatingParameter); state = States.InBracketExpression; unmatchedBrackets++; continue; } if (state == States.InBracketExpression || state == States.InCurlyBraceExpression || state == States.InParenthesizedExpression) { unmatchedBrackets++; continue; } } if (c == ']') { if (state == States.InBracketExpression || state == States.InCurlyBraceExpression || state == States.InParenthesizedExpression) { unmatchedBrackets--; if (unmatchedBrackets < 0) { result.Success = false; result.ErrorDescription = "Unexpected closing bracket."; result.ErrorIndex = index; return(result); } if (unmatchedBrackets == 0) { if (stateBeforeBrackets.Count > 0) { state = stateBeforeBrackets.Pop(); } else if (state == States.InBracketExpression) { goto unexpectedBracket; } } continue; unexpectedBracket: result.Success = false; result.ErrorDescription = "Unexpected closing bracket."; result.ErrorIndex = index; return(result); } } if (c == '{') { if (state == States.AccumulatingParameter || state == States.WaitingForParameterName) { stateBeforeCurlyBraces.Push(States.AccumulatingParameter); state = States.InCurlyBraceExpression; unmatchedCurlyBraces++; continue; } if (state == States.InBracketExpression || state == States.InCurlyBraceExpression || state == States.InParenthesizedExpression) { unmatchedCurlyBraces++; continue; } } if (c == '}') { if (state == States.InBracketExpression || state == States.InCurlyBraceExpression || state == States.InParenthesizedExpression) { unmatchedCurlyBraces--; if (unmatchedCurlyBraces < 0) { result.Success = false; result.ErrorDescription = "Unexpected closing brace."; result.ErrorIndex = index; return(result); } if (unmatchedCurlyBraces == 0) { if (stateBeforeCurlyBraces.Count > 0) { state = stateBeforeCurlyBraces.Pop(); } else if (state == States.InCurlyBraceExpression) { goto unexpectedCurlyBrace; } } continue; } unexpectedCurlyBrace: result.Success = false; result.ErrorDescription = "Unexpected closing brace."; result.ErrorIndex = index; return(result); } if (c == ')') { if (state == States.WaitingForParameterName && parameters.Count == 0) { if (lastModifier == CSharpParameterModifier.None) { state = States.AfterSignature; accum = ""; } //otherwise the signature is incomplete continue; } if (state == States.InBracketExpression || state == States.InCurlyBraceExpression || state == States.InParenthesizedExpression) { unmatchedParenthesis--; if (unmatchedParenthesis < 0) { result.Success = false; result.ErrorDescription = "Unexpected closing parenthesis."; result.ErrorIndex = index; return(result); } if (unmatchedParenthesis == 0) { if (stateBeforeParenthesis.Count > 0) { state = stateBeforeParenthesis.Pop(); } else if (state == States.InParenthesizedExpression) { goto unexpectedParenth; } } continue; } if (state == States.AccumulatingParameter) { var param = accum.Substring(0, accum.Length - 1).Trim(); if (!CSharpIDValidator.IsValidIdentifier(param) && (lastModifier == CSharpParameterModifier.Ref || lastModifier == CSharpParameterModifier.Out)) { result.Success = false; result.ErrorDescription = "'ref' and 'out' can only be used with a direct variable reference."; result.ErrorIndex = index - (accum.Length - 1); return(result); } string err; int errIndex; if (lastModifier == CSharpParameterModifier.New && !IsValidNewParameter(param, index - (accum.Length - 1), out err, out errIndex)) { result.Success = false; result.ErrorDescription = err; result.ErrorIndex = errIndex; return(result); } if (lastModifier == CSharpParameterModifier.None && !IsValidPlainParameter(param, index - (accum.Length - 1), out err, out errIndex)) { result.Success = false; result.ErrorDescription = err; result.ErrorIndex = errIndex; return(result); } parameters.Add(new CSharpParameterSignature(param, lastModifier)); accum = ""; lastModifier = CSharpParameterModifier.None; state = States.AfterSignature; continue; } unexpectedParenth: result.Success = false; result.ErrorDescription = "Unexpected closing parenthesis."; result.ErrorIndex = index; return(result); } if (c == '(') { if (state == States.AccumulatingParameter || state == States.WaitingForParameterName) { stateBeforeParenthesis.Push(States.AccumulatingParameter); state = States.InParenthesizedExpression; unmatchedParenthesis++; continue; } if (state == States.AfterExplicitGenericMethodParameters) { accum = ""; state = States.WaitingForParameterName; continue; } if (state == States.AccumulatingMethodNamePart) { methodName = accum.TrimEnd('(').Trim(); accum = ""; state = States.WaitingForParameterName; continue; } if (state == States.InBracketExpression || state == States.InCurlyBraceExpression || state == States.InParenthesizedExpression) { unmatchedParenthesis++; continue; } result.Success = false; result.ErrorDescription = "Unexpected opening parenthesis."; result.ErrorIndex = index; return(result); } if (c == ',') { if (state == States.InBracketExpression || state == States.InCurlyBraceExpression || state == States.InParenthesizedExpression) { continue; } if (state == States.AccumulatingExplicitGenericMethodParameters) { var param = accum.TrimEnd(',').Trim(); var validate = CSharpClassNameValidator.ValidateInitialization(param, true); if (!validate.Success) { result.Success = false; result.ErrorDescription = validate.ErrorDescription; result.ErrorIndex = (index - (accum.Length - 1)) + validate.ErrorIndex; return(result); } explicitGenericParameters.Add(validate); accum = ""; continue; } if (state == States.AccumulatingParameter) { var param = accum.TrimEnd(',').Trim(); if (!CSharpIDValidator.IsValidIdentifier(param) && (lastModifier == CSharpParameterModifier.Ref || lastModifier == CSharpParameterModifier.Out)) { result.Success = false; result.ErrorDescription = "'ref' and 'out' can only be used with a direct variable reference."; result.ErrorIndex = index - (accum.Length - 1); return(result); } string err; int errIndex; if (lastModifier == CSharpParameterModifier.New && !IsValidNewParameter(param, index - (accum.Length - 1), out err, out errIndex)) { result.Success = false; result.ErrorDescription = err; result.ErrorIndex = errIndex; return(result); } if (lastModifier == CSharpParameterModifier.None && !IsValidPlainParameter(param, index - (accum.Length - 1), out err, out errIndex)) { result.Success = false; result.ErrorDescription = err; result.ErrorIndex = errIndex; return(result); } state = States.WaitingForParameterName; parameters.Add(new CSharpParameterSignature(param, lastModifier)); lastModifier = CSharpParameterModifier.None; accum = ""; continue; } result.Success = false; result.ErrorDescription = "Unexpected ',' character."; result.ErrorIndex = index; return(result); } if (c == '<') { if (state == States.AccumulatingParameter || state == States.InCurlyBraceExpression || state == States.InParenthesizedExpression || state == States.InBracketExpression) { continue; } if (state == States.AccumulatingMethodNamePart) { methodName = accum.TrimEnd('<').Trim(); accum = ""; state = States.AccumulatingExplicitGenericMethodParameters; continue; } if (state == States.AccumulatingExplicitGenericMethodParameters) { unmatchedGenericBrackets++; stateBeforeGenericTypePart.Push(state); state = States.AccumulatingGenericTypePart; continue; } if (state == States.AccumulatingGenericTypePart) { unmatchedGenericBrackets++; continue; } result.Success = false; result.ErrorDescription = "Unexpected '<' character."; result.ErrorIndex = index; return(result); } if (c == '>') { if (state == States.AccumulatingParameter || state == States.InCurlyBraceExpression || state == States.InParenthesizedExpression || state == States.InBracketExpression) { continue; } if (state == States.AccumulatingGenericTypePart) { unmatchedGenericBrackets--; if (unmatchedGenericBrackets == 0) { state = stateBeforeGenericTypePart.Pop(); } continue; } if (state == States.AccumulatingExplicitGenericMethodParameters) { var param = accum.Substring(0, accum.Length > 0 ? accum.Length - 1 : 0).Trim(); var validate = CSharpClassNameValidator.ValidateInitialization(param, true); if (!validate.Success) { result.Success = false; result.ErrorDescription = validate.ErrorDescription; result.ErrorIndex = (index - (accum.Length - 1)) + validate.ErrorIndex; return(result); } explicitGenericParameters.Add(validate); accum = ""; state = States.AfterExplicitGenericMethodParameters; continue; } result.Success = false; result.ErrorDescription = "Unexpected '>' character."; result.ErrorIndex = index; return(result); } if (!char.IsWhiteSpace(c)) { if (state == States.AccumulatingParameter || state == States.AccumulatingExplicitGenericMethodParameters || state == States.AccumulatingMethodNamePart || state == States.AccumulatingGenericTypePart || state == States.InCurlyBraceExpression || state == States.InBracketExpression || state == States.InParenthesizedExpression) { continue; } if (state == States.WaitingForParameterName) { accum = "" + c; state = States.AccumulatingParameter; continue; } if (state == States.WaitingForFirstCharacter) { accum = "" + c; state = States.AccumulatingMethodNamePart; continue; } result.Success = false; result.ErrorDescription = string.Format("Unexpected '{0}' character.", c); result.ErrorIndex = index; return(result); } } if (state != States.AfterSignature) { result.Success = false; result.ErrorDescription = "Call signature incomplete."; result.ErrorIndex = signature.Length - 1; return(result); } result.MethodName = methodName; result.Parameters = parameters; result.ExplicitGenericParameters = explicitGenericParameters; return(result); }
/// <summary> /// Validates/parses the specified CSharp inheritance list given in <paramref name="input" />. /// The parser supports 'where' type constraints on generic parameters. /// The signature given should be the source content immediately after a classes declared name, without the separating /// colon if there is one. /// </summary> /// <param name="input">The inheritance list signature to parse.</param> /// <returns>A parse/validation results object. <see cref="CSharpInheritanceListValidationResult" /></returns> /// <exception cref="ArgumentNullException"><paramref name="input"/> is <c>null</c>.</exception> public static CSharpInheritanceListValidationResult Validate(string input) { if (input == null) { throw new ArgumentNullException("input"); } var result = new CSharpInheritanceListValidationResult(); var compareValidatedType = new EquateValidatedTypes(); var inheritedTypes = new HashSet <CSharpClassNameValidationResult>(compareValidatedType); var constrainedTypeParameters = new HashSet <string>(); var typeConstraints = new GenericArray <HashSet <CSharpTypeConstraintValidationResult> >(); result.Success = true; States state = States.WaitingForFirstWord; States stateBeforeGenericPart = 0; string accum = ""; int unmatchedGenericBraces = 0; for (int index = 0; index < input.Length; index++) { var c = input[index]; bool end = index == input.Length - 1; accum += c; if (end) { if (state == States.AccumulatingInheritedType || state == States.AfterFirstInheritedType || state == States.AccumulatingFirstWord || state == States.WaitingForFirstWord || (state == States.AccumulatingGenericPart && (stateBeforeGenericPart == States.AccumulatingInheritedType || stateBeforeGenericPart == States.AccumulatingFirstWord))) { var word = accum.Trim(); CSharpClassNameValidationResult init; string err; if (!IsValidInheritedType(word, out err, out init)) { result.ErrorDescription = err; result.ErrorIndex = (index - (accum.Length - 1)) + (init == null ? 0 : init.ErrorIndex); result.Success = false; return(result); } if (!inheritedTypes.Add(init)) { result.ErrorDescription = string.Format("Type '{0}' cannot be inherited more than once.", init.FullSignature); result.ErrorIndex = (index - (accum.Length - 1)) + (init.ErrorIndex); result.Success = false; return(result); } state = States.EndOfListWithoutWhereClauses; continue; } if (state == States.AccumulatingTypeConstraint || state == States.AfterConstraintColon || (state == States.AccumulatingGenericPart && (stateBeforeGenericPart == States.AccumulatingTypeConstraint))) { var word = accum.Trim(); string err; CSharpTypeConstraintValidationResult init; if (!IsValidTypeConstraint(word, out err, out init)) { result.ErrorDescription = err; result.ErrorIndex = (index - (accum.Length - 1)); result.Success = false; return(result); } if (!typeConstraints.Last().Add(init)) { result.ErrorDescription = string.Format( "Type constraint '{0}' cannot be used more than once for generic parameter '{1}'.", init.ConstraintString, constrainedTypeParameters.Last()); result.ErrorIndex = (index - (accum.Length - 1)); result.Success = false; return(result); } state = States.EndOfListWithWhereClauses; continue; } } if (c == '<') { if (state == States.AccumulatingFirstWord || state == States.AccumulatingTypeConstraint || state == States.AccumulatingInheritedType) { stateBeforeGenericPart = state; state = States.AccumulatingGenericPart; unmatchedGenericBraces++; continue; } if (state == States.AccumulatingGenericPart) { unmatchedGenericBraces++; continue; } result.ErrorDescription = string.Format("Unexpected character '{0}'.", c); result.ErrorIndex = index; result.Success = false; return(result); } if (c == '>') { if (state == States.AccumulatingGenericPart) { unmatchedGenericBraces--; if (unmatchedGenericBraces == 0) { state = stateBeforeGenericPart; } continue; } result.ErrorDescription = string.Format("Unexpected character '{0}'.", c); result.ErrorIndex = index; result.Success = false; return(result); } if (c == ',') { if ((state == States.AfterWhereKeyword && inheritedTypes.Count > 0) || state == States.AccumulatingConstraintParam) { result.ErrorDescription = string.Format("Unexpected character '{0}'.", c); result.ErrorIndex = index; result.Success = false; return(result); } if (state == States.AccumulatingTypeConstraint) { var word = accum.TrimEnd(',').Trim(); string err; CSharpTypeConstraintValidationResult init; if (!IsValidTypeConstraint(word, out err, out init)) { result.ErrorDescription = err; result.ErrorIndex = (index - (accum.Length - 1)); result.Success = false; return(result); } if (!typeConstraints.Last().Add(init)) { result.ErrorDescription = string.Format( "Type constraint '{0}' cannot be used more than once for generic parameter '{1}'.", init.ConstraintString, constrainedTypeParameters.Last()); result.ErrorIndex = (index - (accum.Length - 1)); result.Success = false; return(result); } accum = ""; continue; } if (state == States.AccumulatingInheritedType || state == States.AccumulatingFirstWord || (state == States.AfterWhereKeyword && inheritedTypes.Count == 0)) { var type = accum.TrimEnd(',').Trim(); CSharpClassNameValidationResult init; string err; if (!IsValidInheritedType(type, out err, out init)) { result.ErrorDescription = err; result.ErrorIndex = (index - (accum.Length - 1)); result.Success = false; return(result); } if (!inheritedTypes.Add(init)) { result.ErrorDescription = string.Format( "Type '{0}' cannot be inherited more than once.", init.FullSignature); result.ErrorIndex = (index - (accum.Length - 1)); result.Success = false; return(result); } accum = ""; state = States.AfterFirstInheritedType; continue; } } if (c == 'w') { var ahead = index + 5; if (ahead > input.Length) { goto pastWhereCheck; } var lookAheadAsertion = input.Substring(index, 5) == "where"; var lookBehindsertion = index == 0 || char.IsWhiteSpace(input[index - 1]); if (lookAheadAsertion && lookBehindsertion) { if (ahead < input.Length && !char.IsWhiteSpace(input[ahead]) && input[ahead] != ',') { goto pastWhereCheck; } if (state == States.WaitingForFirstWord) { accum = ""; index += 4; state = States.AfterWhereKeyword; //there is an ambiguous case here because you can inherit a class named where, before a where clause occurs if (index + 1 == input.Length) { inheritedTypes.Add(CSharpClassNameValidator.ValidateInitialization("where", false)); state = States.EndOfListWithoutWhereClauses; continue; } bool haveWhitespace = false; for (int i = index + 1; i < input.Length; i++) { var cr = input[i]; if (char.IsWhiteSpace(cr)) { haveWhitespace = true; if (i == input.Length - 1) { inheritedTypes.Add(CSharpClassNameValidator.ValidateInitialization("where", false)); state = States.EndOfListWithoutWhereClauses; break; } continue; } if (cr == 'w' && haveWhitespace) { ahead = i + 5; if (ahead > input.Length) { continue; } lookAheadAsertion = input.Substring(i, 5) == "where"; if (lookAheadAsertion) { if (ahead < input.Length && !char.IsWhiteSpace(input[ahead]) && input[ahead] != ',') { continue; } inheritedTypes.Add(CSharpClassNameValidator.ValidateInitialization("where", false)); index = i + 4; state = States.AfterWhereKeyword; break; } } if (cr == ',') { inheritedTypes.Add(CSharpClassNameValidator.ValidateInitialization("where", false)); index = i; state = States.AccumulatingInheritedType; } break; } continue; } if (state == States.AccumulatingTypeConstraint) { var word = accum.TrimEnd('w').Trim(); string err; CSharpTypeConstraintValidationResult init; if (!IsValidTypeConstraint(word, out err, out init)) { result.ErrorDescription = err; result.ErrorIndex = (index - (accum.Length - 1)); result.Success = false; return(result); } if (!typeConstraints.Last().Add(init)) { result.ErrorDescription = string.Format( "Type constraint '{0}' cannot be used more than once for generic parameter '{1}'.", init.ConstraintString, constrainedTypeParameters.Last()); result.ErrorIndex = (index - (accum.Length - 1)); result.Success = false; return(result); } accum = ""; index += 4; state = States.AfterWhereKeyword; continue; } if (state == States.AccumulatingInheritedType || state == States.AccumulatingFirstWord) { var word = accum.TrimEnd('w').Trim(); CSharpClassNameValidationResult init; string err; if (!IsValidInheritedType(word, out err, out init)) { result.ErrorDescription = err; result.ErrorIndex = (index - (accum.Length - 1)) + (init == null ? 0 : init.ErrorIndex); result.Success = false; return(result); } if (!inheritedTypes.Add(init)) { result.ErrorDescription = string.Format("Type '{0}' cannot be inherited more than once.", init.FullSignature); result.ErrorIndex = (index - (accum.Length - 1)) + (init.ErrorIndex); result.Success = false; return(result); } state = States.AfterWhereKeyword; accum = ""; index += 4; continue; } } } pastWhereCheck: if (c == ':') { if (state == States.AfterWhereKeyword) { result.ErrorDescription = string.Format("Unexpected character '{0}'.", c); result.ErrorIndex = index; result.Success = false; return(result); } if (state == States.AccumulatingConstraintParam) { var constrainedType = accum.TrimEnd(':').Trim(); if (!CSharpIDValidator.IsValidIdentifier(constrainedType)) { result.ErrorDescription = string.Format("Invalid generic type constraint name '{0}'.", constrainedType); result.ErrorIndex = (index - (accum.Length - 1)); result.Success = false; return(result); } if (!constrainedTypeParameters.Add(constrainedType)) { result.ErrorDescription = string.Format( "Generic parameter '{0}' cannot have more than one type constraint list.", constrainedType); result.ErrorIndex = (index - (accum.Length - 1)); result.Success = false; return(result); } typeConstraints.Add(new HashSet <CSharpTypeConstraintValidationResult>()); accum = ""; state = States.AfterConstraintColon; continue; } } if (!char.IsWhiteSpace(c)) { switch (state) { case States.AfterWhereKeyword: accum = "" + c; state = States.AccumulatingConstraintParam; continue; case States.WaitingForFirstWord: accum = "" + c; state = States.AccumulatingFirstWord; continue; case States.AfterFirstInheritedType: accum = "" + c; state = States.AccumulatingInheritedType; continue; case States.AfterConstraintColon: accum = "" + c; state = States.AccumulatingTypeConstraint; continue; } } if (!char.IsWhiteSpace(c)) { continue; } switch (state) { case States.AfterConstraintColon: accum = ""; continue; case States.WaitingForFirstWord: accum = ""; continue; case States.AfterFirstInheritedType: accum = ""; continue; case States.AfterWhereKeyword: accum = ""; break; } } if (state != States.EndOfListWithoutWhereClauses && state != States.EndOfListWithWhereClauses && state != States.WaitingForFirstWord) { result.Success = false; result.ErrorDescription = "Class inheritance list is incomplete."; result.ErrorIndex = input.Length; return(result); } result.ConstrainedTypeParameters = constrainedTypeParameters.ToGenericArray(); result.InheritedTypes = inheritedTypes.ToGenericArray(); result.ParameterConstraints = typeConstraints.Select(x => x.ToGenericArray()).ToGenericArray(); result.Fullsignature = ""; if (result.InheritedTypes.Count > 0) { result.Fullsignature += string.Join(", ", result.InheritedTypes.Select(x => x.FullSignature)); if (result.ConstrainedTypeParameters.Count > 0) { result.Fullsignature += " "; } } result.Fullsignature += string.Join(" ", result.ConstrainedTypeParameters.Select( (x, i) => "where " + result.ConstrainedTypeParameters[i] + " : " + string.Join(", ", result.ParameterConstraints[i].Select(c => c.ConstraintString)))); return(result); }
private IEnumerable <LSLLibraryFunctionSignature> InterfaceMethods(Type containerType) { foreach (var v in containerType.GetMethods()) { var subsets = _subsetsMap[containerType]; var returnType = LslTypeFromCsharpType(v.ReturnType); var pTypes = new GenericArray <LSLParameterSignature>(); foreach (var p in v.GetParameters()) { var isVariadic = IsParams(p); if (p.ParameterType == (typeof(object[])) && isVariadic) { pTypes.Add(new LSLParameterSignature(LSLType.Void, p.Name, true)); goto omitRestOfParameters; } if (isVariadic) { Log.WriteLineWithHeader("[OpenSimLibraryDataReflector]: ", "Interface function {0} of type {1}, variadic parameter {2} is an un-recognized data type ({3}), function omitted", v.Name, containerType.Name, p.Name, p.ParameterType.Name); goto omitFunction; } var type = LslTypeFromCsharpParameterType(p.ParameterType); if (type != null) { pTypes.Add(new LSLParameterSignature(type.Value, p.Name, false)); } else { Log.WriteLineWithHeader("[OpenSimLibraryDataReflector]: ", "Interface function {0} of type {1}, parameter {2} is an un-recognized data type ({3}), function omitted", v.Name, containerType.Name, p.Name, p.ParameterType.Name); goto omitFunction; } } omitRestOfParameters: if (returnType != null) { var f = new LSLLibraryFunctionSignature(returnType.Value, v.Name, pTypes); f.DocumentationString = _documentationProvider.DocumentFunction(f); f.Subsets.SetSubsets(subsets); yield return(f); } else { Log.WriteLineWithHeader("[OpenSimLibraryDataReflector]: ", "function {0} of type {1} return type is an un-recognized data type ({2})", v.Name, containerType.Name, v.ReturnType.Name); } omitFunction: ; } }
internal void AddReference(LSLFunctionCallNode reference) { _references.Add(reference); }
private static CSharpClassNameValidationResult _Validate(string input, ClassSigType signatureType, bool allowBuiltinAliases, CSharpParsedTypeValidateTypeCallback validateTypeCallback, int index) { if (input == null) { throw new ArgumentNullException("input", "Class name/signature string cannot be null!"); } if (string.IsNullOrWhiteSpace(input)) { return(new CSharpClassNameValidationResult { Success = false, ErrorDescription = "Class name/signature cannot be whitespace.", ErrorIndex = index, }); } string fullyQualifiedName = ""; var genericArgs = new GenericArray <CSharpClassNameValidationResult>(); var qualifications = new GenericArray <Qualification>() { new Qualification(new StringBuilder(), index) }; string genericPart = ""; bool isGeneric = false; int genericBrackets = 0; foreach (var c in input) { //enter generic arguments if (c == '<') { isGeneric = true; genericBrackets++; } //check if we have gotten to the generic part of the type signature yet (if any) if (!isGeneric) { if (c == '.') { //qualifier operator is not allowed anywhere in declaration signatures because //they only consist of a raw type name and generic argument specifications if (signatureType == ClassSigType.Declaration) { return(new CSharpClassNameValidationResult { Success = false, ErrorDescription = string.Format( "'.' name qualifier operator is not valid in a class declaration/generic " + "type placeholder name."), ErrorIndex = index, }); } //detect a missing qualifier section that's terminated with a dot. if (string.IsNullOrWhiteSpace(qualifications.Last().ToString())) { return(new CSharpClassNameValidationResult { Success = false, ErrorDescription = "\'..\' is an invalid use of the qualification operator.", ErrorIndex = index, }); } qualifications.Add(new Qualification(new StringBuilder(), index + 1)); } else { qualifications.Last().Builder.Append(c); } } if (genericBrackets == 0 && !isGeneric) { //accumulate to our fully qualified name fullyQualifiedName += c; } else if (genericBrackets == 0 && isGeneric) { //we have exited even pairs of brackets and are on the //other side of the generic arguments at the end of the signature //there should not be anything here return(new CSharpClassNameValidationResult { Success = false, ErrorDescription = "extra content found after generic argument list.", ErrorIndex = index }); } else if (!(genericBrackets == 1 && c == '<')) { //passed the start of the first < in the signature by 1 if ((c == ',' || c == '>') && genericBrackets == 1) { //we have accumulated a type argument suitable for recursive decent //validate it recursively var validateGenericArgument = _Validate(genericPart.Trim(), signatureType, allowBuiltinAliases, validateTypeCallback, index - genericPart.Length); //return immediately on failure if (!validateGenericArgument.Success) { return(validateGenericArgument); } //add the validated 'tree' genericArgs.Add(validateGenericArgument); //reset the accumulator genericPart = ""; } else { //accumulate until we hit a comma or the > character genericPart += c; } } if (c == '>') { //exit a generic type scope genericBrackets--; } index++; } if (genericBrackets > 0) { //something is amiss with bracket matching return(new CSharpClassNameValidationResult { Success = false, ErrorDescription = "mismatched generic type brackets.", ErrorIndex = index }); } //there may be only one qualification, in which case //the base name is also the fully qualified name. var baseName = qualifications.Last(); if (qualifications.Count > 1) { //uses qualified names, this is definitely an initialization signature //because the qualifier '.' operator returns an error in declaration signatures //above the recursive call to validate foreach (var name in qualifications) { if (string.IsNullOrWhiteSpace(name.Builder.ToString())) { return(new CSharpClassNameValidationResult { Success = false, ErrorDescription = string.Format("qualified type name '{0}' is incomplete.", fullyQualifiedName), ErrorIndex = name.StartIndex }); } } foreach (var name in qualifications) { //check for syntax errors in the qualified name pieces, they need to be valid ID's and not keywords //IsValidIdentifier takes care of both these criteria if (!CSharpIDValidator.IsValidIdentifier(name.Builder.ToString())) { //sound something funky return(new CSharpClassNameValidationResult { Success = false, ErrorDescription = string.Format( "'{0}' is not valid in the given qualified type name '{1}'.", name.Builder, fullyQualifiedName), ErrorIndex = name.StartIndex }); } } } else { var shortName = baseName.Builder.ToString(); //single type argument to a generic type if (string.IsNullOrWhiteSpace(shortName)) { return(new CSharpClassNameValidationResult { Success = false, ErrorDescription = string.Format("missing generic {0} name.", signatureType == ClassSigType.Initialization ? "type argument" : "placeholder type"), ErrorIndex = baseName.StartIndex, }); } bool aliasInitialization = allowBuiltinAliases && CSharpKeywords.BuiltInTypeMap.ContainsKey(shortName) && signatureType == ClassSigType.Initialization; if (!aliasInitialization && !CSharpIDValidator.IsValidIdentifier(baseName.Builder.ToString())) { return(new CSharpClassNameValidationResult { Success = false, ErrorDescription = string.Format("'{0}' is not an allowed CSharp identifier.", baseName.Builder), ErrorIndex = baseName.StartIndex }); } } var baseNameString = baseName.Builder.ToString(); if (isGeneric && CSharpKeywords.IsTypeAliasKeyword(fullyQualifiedName)) { return(new CSharpClassNameValidationResult { Success = false, ErrorDescription = string.Format("Built in type alias '{0}' is not a generic type.", baseName.Builder), ErrorIndex = baseName.StartIndex }); } //success var classDescription = new CSharpClassNameValidationResult() { QualifiedName = fullyQualifiedName, BaseName = baseNameString, GenericArguments = genericArgs, IsGeneric = isGeneric, Success = true }; if (isGeneric) { classDescription.FullSignature = fullyQualifiedName + "<" + string.Join(", ", classDescription.GenericArguments.Select(x => x.FullSignature)) + ">"; } else { classDescription.FullSignature = fullyQualifiedName; } if (validateTypeCallback == null || signatureType != ClassSigType.Initialization) { return(classDescription); } var typeCheckResult = validateTypeCallback(classDescription); if (typeCheckResult.IsValid) { return(classDescription); } classDescription.FullSignature = null; classDescription.ErrorIndex = qualifications.First().StartIndex; classDescription.ErrorDescription = typeCheckResult.ErrorMessage; classDescription.Success = false; return(classDescription); }