/// <summary> /// Writes an interface member reference to the output. /// </summary> public void WriteInterfaceMemberToOutput( JavascriptFormatter output, Compiler.Extensibility.IAstEmitter astEmitter, JSFunctionExpression enclosingFunction, JSMethod jsMethod, JSExpression method, TypeReferenceContext referenceContext ) { int index; CachedInterfaceMemberRecord record; GenericParameter[] rewrittenGenericParameters = null; if (LocalCachingEnabled && PreferLocalCacheForGenericInterfaceMethodSignatures) { record = new CachedInterfaceMemberRecord(jsMethod.Reference.DeclaringType, jsMethod.Identifier); } else { var rewritten = GenericTypesRewriter.Normalized(jsMethod.Reference.DeclaringType); record = new CachedInterfaceMemberRecord(rewritten.CacheRecord, jsMethod.Identifier, rewritten.RewritedGenericParameters.Length); rewrittenGenericParameters = rewritten.RewritedGenericParameters; } if (enclosingFunction.Method != null && enclosingFunction.Method.Method != null) { var functionIdentifier = enclosingFunction.Method.Method.Identifier; CacheSet localSignatureSet; if (LocalCachedSets.TryGetValue(functionIdentifier, out localSignatureSet)) { if (localSignatureSet.InterfaceMembers.TryGetValue(record, out index)) { output.WriteRaw("$im{0:X2}", index); return; } } } if (!Global.InterfaceMembers.TryGetValue(record, out index)) { output.Identifier(jsMethod.Reference.DeclaringType, referenceContext, false); output.Dot(); astEmitter.Emit(method); } else { output.WriteRaw("$IM{0:X2}", index); output.LPar(); if (rewrittenGenericParameters != null) { output.CommaSeparatedList(rewrittenGenericParameters, referenceContext); } output.RPar(); } }
/// <summary> /// Writes a method signature to the output. /// </summary> public void WriteSignatureToOutput( JavascriptFormatter output, JSFunctionExpression enclosingFunction, MethodReference methodReference, MethodSignature methodSignature, TypeReferenceContext referenceContext, bool forConstructor ) { int index; CachedSignatureRecord cacheRecord; GenericParameter[] rewrittenGenericParameters = null; if (LocalCachingEnabled && PreferLocalCacheForGenericMethodSignatures) { cacheRecord = new CachedSignatureRecord(methodReference, GenericTypesRewriter.NormalizedConstructorSignature(methodReference, methodSignature, forConstructor), forConstructor); } else { RewritedCacheRecord <MethodSignature> rewritten = GenericTypesRewriter.Normalized(methodReference, methodSignature, forConstructor); cacheRecord = new CachedSignatureRecord(methodReference, rewritten.CacheRecord, forConstructor, rewritten.RewritedGenericParameters.Length); rewrittenGenericParameters = rewritten.RewritedGenericParameters; } if ((enclosingFunction.Method != null) && (enclosingFunction.Method.Method != null)) { var functionIdentifier = enclosingFunction.Method.Method.Identifier; CacheSet localSignatureSet; if (LocalCachedSets.TryGetValue(functionIdentifier, out localSignatureSet)) { if (localSignatureSet.Signatures.TryGetValue(cacheRecord, out index)) { output.WriteRaw("$s{0:X2}", index); return; } } } if (!Global.Signatures.TryGetValue(cacheRecord, out index)) { output.Signature(methodReference, methodSignature, referenceContext, forConstructor, true); } else { output.WriteRaw("$S{0:X2}", index); output.LPar(); if (rewrittenGenericParameters != null) { output.CommaSeparatedList(rewrittenGenericParameters, referenceContext); } output.RPar(); } }
public static RewritedCacheRecord <TypeReference> Normalized(TypeReference declaringType) { var targetMappings = new Dictionary <GenericParameter, int>(new GenericParameterComparer()); var resolvedType = GenericTypesRewriter.ResolveTypeReference( declaringType, (tr, resolutionStack) => { if (tr is GenericParameter) { var gp = (GenericParameter)tr; return(GenericTypesRewriter.ReplaceWithGenericArgument(gp, targetMappings)); } return(tr); }, null); var mappings = targetMappings.OrderBy(item => item.Value).Select(item => item.Key).ToArray(); return(new RewritedCacheRecord <TypeReference>(resolvedType, mappings)); }
private static TypeReference ResolveTypeReference(MethodReference method, TypeReference typeReference, Dictionary <GenericParameter, int> mappings) { var resolvedMethod = method.Resolve(); return(GenericTypesRewriter.ResolveTypeReference( typeReference, (tr, resolutionStack) => { if (tr is GenericParameter) { var gp = (GenericParameter)tr; if (resolutionStack.Count(typeInStack => TypeUtil.TypesAreEqual(typeInStack, gp)) > 1) { return GenericTypesRewriter.ReplaceWithGenericArgument(gp, mappings); } var result = MethodSignature.ResolveGenericParameter(gp, method.DeclaringType); if (result is GenericParameter) { gp = (GenericParameter)result; result = null; } if (result == null) { if (gp.Owner is MethodReference) { var mr = (MethodReference)gp.Owner; if (mr.Resolve() == resolvedMethod) { return gp; } } return GenericTypesRewriter.ReplaceWithGenericArgument(gp, mappings); } return result; } return tr; }, null)); }
private void CacheInterfaceMember(TypeReference declaringType, string memberName) { var cacheLocally = false; var originalType = declaringType; var unexpandedType = declaringType; if (!TypeUtil.ExpandPositionalGenericParameters(unexpandedType, out declaringType)) { declaringType = unexpandedType; } CachedInterfaceMemberRecord record; if (LocalCachingEnabled && PreferLocalCacheForGenericInterfaceMethodSignatures) { if (TypeUtil.IsOpenType(declaringType)) { cacheLocally = true; } record = new CachedInterfaceMemberRecord(declaringType, memberName); } else { var rewritten = GenericTypesRewriter.Normalized(declaringType); record = new CachedInterfaceMemberRecord(rewritten.CacheRecord, memberName, rewritten.RewritedGenericParameters.Length); } var set = GetCacheSet(cacheLocally); if (!set.InterfaceMembers.ContainsKey(record)) { set.InterfaceMembers.Add(record, set.InterfaceMembers.Count); } }
private void CacheSignature(MethodReference method, MethodSignature signature, bool isConstructor) { bool cacheLocally; CachedSignatureRecord record; if (LocalCachingEnabled && PreferLocalCacheForGenericMethodSignatures) { record = new CachedSignatureRecord(method, GenericTypesRewriter.NormalizedConstructorSignature(method, signature, isConstructor), isConstructor); signature = record.Signature; Func <GenericParameter, bool> filter = (gp) => { // If the generic parameter can be expanded given the type that declared the method, don't cache locally. var resolved = MethodSignature.ResolveGenericParameter(gp, method.DeclaringType); // Note that we have to ensure the resolved type is not generic either. A generic parameter can resolve to a // *different* generic parameter, and that is still correct - i.e. SomeMethod<A> calls SomeMethod<B>, // in that case resolving B will yield A. if ((resolved != gp) && (resolved != null) && !TypeUtil.IsOpenType(resolved)) { return(false); } var ownerMethod = gp.Owner as MethodReference; if (ownerMethod == null) { return(true); } if (ownerMethod == method) { return(false); } // FIXME: Nulls? else if (ownerMethod.Resolve() == method.Resolve()) { return(false); } else { return(true); } }; cacheLocally = false; if (TypeUtil.IsOpenType(signature.ReturnType, filter)) { cacheLocally = true; } else if (signature.ParameterTypes.Any((gp) => TypeUtil.IsOpenType(gp, filter))) { cacheLocally = true; } else if (isConstructor && TypeUtil.IsOpenType(method.DeclaringType, filter)) { cacheLocally = true; } } else { cacheLocally = false; var rewritenInfo = GenericTypesRewriter.Normalized(method, signature, isConstructor); record = new CachedSignatureRecord( method, rewritenInfo.CacheRecord, isConstructor, rewritenInfo.RewritedGenericParameters.Length); } var set = GetCacheSet(cacheLocally); if (!set.Signatures.ContainsKey(record)) { set.Signatures.Add(record, set.Signatures.Count); } }