/// <summary> /// Helper method getting parameter type. /// </summary> /// <param name="typeCtx">Routine type context.</param> /// <param name="paramTag">PHPDoc param tag if available.</param> /// <param name="signature">Call signature.</param> /// <param name="call">Call information if called specifically with given context.</param> /// <param name="paramIndex">Parameter index.</param> /// <returns>Expected type of parameter. Cannot be uninitialized.</returns> private static TypeRefMask GetParamType(TypeRefContext /*!*/ typeCtx, PHPDocBlock.ParamTag paramTag, FormalParam syntax, CallInfo call, int paramIndex) { Contract.ThrowIfNull(typeCtx); Debug.Assert(paramIndex >= 0); TypeRefMask result = 0; bool isvariadic = false; bool isalias = false; // lookup actual type hint if (syntax != null) { isvariadic = syntax.IsVariadic; isalias = syntax.PassedByRef || syntax.IsOut; var hint = syntax.TypeHint; if (hint != null) { result = typeCtx.GetTypeMaskFromTypeHint(syntax.TypeHint); if (isvariadic) // PHP 5.6 variadic parameter (...) // TypeHint -> TypeHint[] { result = typeCtx.GetArrayTypeMask(result); } } } if (result.IsUninitialized) { // lookup callInfo result = call.GetParamType(typeCtx, paramIndex); if (result.IsUninitialized) { // lookup PHPDoc if (paramTag != null && paramTag.TypeNamesArray.Length != 0) { result = PHPDoc.GetTypeMask(typeCtx, paramTag.TypeNamesArray); } if (result.IsUninitialized) { // NOTE: if still unknown, we can use type of the FormalParam.InitValue as Hint result = TypeRefMask.AnyType; } } // PHP 5.6, variadic parameter (...) is always of type array, // if specified else, user meant type of its elements if (isvariadic && !typeCtx.IsArray(result)) { result = typeCtx.GetArrayTypeMask(result); // hint -> hint[] } } // result.IsRef = isalias; // Debug.Assert(!result.IsUninitialized); return(result); }