public virtual bool TryFormatValue(object v, ResolvedTypeInfo type, out string returnvalue) { TypeReference valueType = type.Reference; if (v == null) { returnvalue = "null"; return(true); } if (valueType.FullName == "System.Type") { var vTypeRef = v as TypeReference; if (vTypeRef != null) { returnvalue = "typeof(" + NativeTypeManager.GetTranslatedName(vTypeRef) + ")"; // TODO: drop NS handling } else { returnvalue = "typeof(" + v.ToString() + ")"; } return(true); } if (valueType.FullName == "System.String") { returnvalue = "\"" + FilterSpecialChars(v.ToString()) + "\""; return(true); } if (valueType.FullName == "System.Char") { returnvalue = "'" + FilterSpecialChars(v.ToString()) + "'"; return(true); } if (v is Boolean) { returnvalue = (bool)v ? "true" : "false"; return(true); } TypeDefinition valueDef = type.Definition; if (valueDef == null || !valueDef.IsEnum) { returnvalue = v.ToString(); return(true); } string typename = MDocUpdater.GetDocTypeFullName(valueType); var values = GetEnumerationValues(valueDef); long c = ToInt64(v); if (values.ContainsKey(c)) { returnvalue = typename + "." + values[c]; return(true); } returnvalue = null; return(false); }
public static MemberReference GetMember(TypeDefinition type, DocumentationMember member) { string membertype = member.MemberType; string returntype = member.ReturnType; string docName = member.MemberName; string[] docTypeParams = GetTypeParameters(docName, member.TypeParameters); // If we're using 'magic types', then we might get false positives ... in those cases, we keep searching MemberReference likelyCandidate = null; // Loop through all members in this type with the same name var reflectedMembers = GetReflectionMembers(type, docName, membertype).ToArray(); foreach (MemberReference mi in reflectedMembers) { bool matchedMagicType = false; if (mi is TypeDefinition) { continue; } if (MDocUpdater.GetMemberType(mi) != membertype) { continue; } if (MDocUpdater.IsPrivate(mi)) { continue; } IList <ParameterDefinition> pis = null; string[] typeParams = null; if (mi is MethodDefinition) { MethodDefinition mb = (MethodDefinition)mi; pis = mb.Parameters; if (mb.IsGenericMethod()) { IList <GenericParameter> args = mb.GenericParameters; typeParams = args.Select(p => p.Name).ToArray(); } } else if (mi is PropertyDefinition) { pis = ((PropertyDefinition)mi).Parameters; } // check type parameters int methodTcount = member.TypeParameters == null ? 0 : member.TypeParameters.Count; int reflectionTcount = typeParams == null ? 0 : typeParams.Length; if (methodTcount != reflectionTcount) { continue; } // check member parameters int mcount = member.Parameters == null ? 0 : member.Parameters.Count; int pcount = pis == null ? 0 : pis.Count; if (mcount != pcount) { continue; } MethodDefinition mDef = mi as MethodDefinition; if (mDef != null && !mDef.IsConstructor && (mDef.Name.StartsWith("op_Explicit", StringComparison.Ordinal) || mDef.Name.StartsWith("op_Implicit", StringComparison.Ordinal))) { // Casting operators can overload based on return type. string rtype = GetReplacedString( MDocUpdater.GetDocTypeFullName(((MethodDefinition)mi).ReturnType), typeParams, docTypeParams); string originalRType = rtype; if (MDocUpdater.SwitchingToMagicTypes) { rtype = NativeTypeManager.ConvertFromNativeType(rtype); } if ((returntype != rtype && originalRType == rtype) || (MDocUpdater.SwitchingToMagicTypes && returntype != originalRType && returntype != rtype && originalRType != rtype)) { continue; } if (originalRType != rtype) { matchedMagicType = true; } } if (pcount == 0) { return(mi); } bool isExtensionMethod = DocUtils.IsExtensionMethod(mDef); bool good = true; for (int i = 0; i < pis.Count; i++) { bool isRefType = pis[i].ParameterType is ByReferenceType; if (i == 0 && !isRefType && isExtensionMethod) { isRefType = true; // this will be the case for generic parameter types } string paramType = GetReplacedString( MDocUpdater.GetDocParameterType(pis[i].ParameterType), typeParams, docTypeParams); // if magictypes, replace paramType to "classic value" ... so the comparison works string originalParamType = paramType; if (MDocUpdater.SwitchingToMagicTypes) { paramType = NativeTypeManager.ConvertFromNativeType(paramType); } string xmlMemberType = member.Parameters[i]; // TODO: take into account extension method reftype bool xmlIsRefType = xmlMemberType.Contains('&'); bool refTypesMatch = isRefType == xmlIsRefType; if (!refTypesMatch) { good = false; break; } xmlMemberType = xmlIsRefType ? xmlMemberType.Substring(0, xmlMemberType.Length - 1) : xmlMemberType; if ((!paramType.Equals(xmlMemberType) && paramType.Equals(originalParamType)) || (MDocUpdater.SwitchingToMagicTypes && !originalParamType.Equals(xmlMemberType) && !paramType.Equals(xmlMemberType) && !paramType.Equals(originalParamType))) { // did not match ... if we're dropping the namespace, and the paramType has the dropped // namespace, we should see if it matches when added bool stillDoesntMatch = true; if (MDocUpdater.HasDroppedNamespace(type) && paramType.StartsWith(MDocUpdater.droppedNamespace)) { string withDroppedNs = string.Format("{0}.{1}", MDocUpdater.droppedNamespace, xmlMemberType); stillDoesntMatch = withDroppedNs != paramType; } if (stillDoesntMatch) { good = false; break; } } if (originalParamType != paramType) { matchedMagicType = true; } } if (!good) { continue; } if (MDocUpdater.SwitchingToMagicTypes && likelyCandidate == null && matchedMagicType) { // we matched this on a magic type conversion ... let's keep going to see if there's another one we should look at that matches more closely likelyCandidate = mi; continue; } return(mi); } return(likelyCandidate); }
void RewriteCrefsIfNecessary(XDocument doc, string path) { // we also have to rewrite crefs var sees = doc.Descendants().Where(d => d.Name.LocalName == "see").ToArray(); foreach (var see in sees) { var cref = see.Attribute("cref"); if (cref == null) { continue; } EcmaUrlParser parser = new EcmaUrlParser(); EcmaDesc reference; if (!parser.TryParse(cref.Value, out reference)) { continue; } if ((new EcmaDesc.Kind[] { EcmaDesc.Kind.Constructor, EcmaDesc.Kind.Method }).Any(k => k == reference.DescKind)) { string ns = reference.Namespace; string type = reference.TypeName; string memberName = reference.MemberName; if (reference.MemberArguments != null) { XDocument refDoc = FindReferenceDoc(path, doc, ns, type); if (refDoc == null) { continue; } // look in the refDoc for the memberName, and match on parameters and # of type parameters var overloads = refDoc.XPathSelectElements("//Member[@MemberName='" + memberName + "']").ToArray(); // Do some initial filtering to find members that could potentially match (based on parameter and typeparam counts) var members = overloads.Where(e => reference.MemberArgumentsCount == e.XPathSelectElements("Parameters/Parameter[not(@apistyle) or @apistyle='classic']").Count() && reference.GenericMemberArgumentsCount == e.XPathSelectElements("TypeParameters/TypeParameter[not(@apistyle) or @apistyle='classic']").Count()).Select(m => new { Node = m, AllParameters = m.XPathSelectElements("Parameters/Parameter").ToArray(), Parameters = m.XPathSelectElements("Parameters/Parameter[not(@apistyle) or @apistyle='classic']").ToArray(), NewParameters = m.XPathSelectElements("Parameters/Parameter[@apistyle='unified']").ToArray() }).ToArray(); // now find the member that matches on types var member = members.FirstOrDefault(m => reference.MemberArguments.All(r => m.Parameters.Any(mp => mp.Attribute("Type").Value.Contains(r.TypeName)))); if (member == null || member.NewParameters.Length == 0) { continue; } foreach (var arg in reference.MemberArguments) { // find the "classic" parameter var oldParam = member.Parameters.First(p => p.Attribute("Type").Value.Contains(arg.TypeName)); var newParam = member.NewParameters.FirstOrDefault(p => oldParam.Attribute("Name").Value == p.Attribute("Name").Value); if (newParam != null) { // this means there was a change made, and we should try to convert this cref arg.TypeName = NativeTypeManager.ConvertToNativeType(arg.TypeName); } } var rewrittenReference = reference.ToEcmaCref(); Console.WriteLine("From {0} to {1}", cref.Value, rewrittenReference); cref.Value = rewrittenReference; } } } }