private bool GetValue <T>(MessageContext ctxt, CCI.AttributeList attributes, CCI.TypeNode attrType, IProperty <T> property, ref T value) { var found = 0; foreach (var attribute in attributes) { if (IsAttribute(attribute, attrType)) { var thisValue = default(T); if (GetValue(ctxt, attribute, attrType, property, ref thisValue)) { if (found++ == 0) { value = thisValue; } else { if (!thisValue.Equals(value)) { env.Log(new InvalidInteropMessage (RewriterMsgContext.AttributeProperty(ctxt, attribute, property.Name), "duplicate inconsistent bindings")); throw new DefinitionException(); } } } } } return(found > 0); }
private void PopulateTypeNamesPositionsAndGlyphs() { Cci.TypeNodeList types = this.scTypeAndMemberDropdownBars.sortedDropDownTypes; Cci.AuthoringHelper helper = this.scTypeAndMemberDropdownBars.languageService.GetAuthoringHelper(); int n = types == null ? 0 : types.Count; string[] typeNames = new string[n]; int[] startColumns = new int[n]; int[] startLines = new int[n]; int[] glyphs = new int[n]; for (int i = 0; i < n; i++) { Cci.TypeNode type = types[i]; if (type == null || type.Name == null) { Debug.Assert(false); continue; } typeNames[i] = helper.GetFullTypeName(type); startColumns[i] = type.Name.SourceContext.StartColumn - 1; startLines[i] = type.Name.SourceContext.StartLine - 1; glyphs[i] = this.glyphProvider.GetGlyph(type); } this.dropDownTypeNames = typeNames; this.dropDownTypeStartColumns = startColumns; this.dropDownTypeStartLines = startLines; this.dropDownTypeGlyphs = glyphs; }
public bool IsPrimitiveType(CCI.TypeNode type) { if (type.NodeType == CCI.NodeType.EnumNode) { return(true); } else { switch (type.TypeCode) { case TypeCode.String: case TypeCode.Char: case TypeCode.Double: case TypeCode.Single: case TypeCode.Decimal: case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Boolean: return(true); default: return(false); } } }
public T GetValue <T>(MessageContext ctxt, CCI.Node node, CCI.TypeNode attrType, IProperty <T> property, bool inheritable) { var res = default(T); if (!GetValue(ctxt, node, attrType, property, inheritable, ref res)) { res = property.Default; } return(res); }
public bool HasAttribute(CCI.AttributeList attributes, CCI.TypeNode attrType) { foreach (var attr in attributes) { if (IsAttribute(attr, attrType)) { return(true); } } return(false); }
public static MessageContext Type(MessageContext parent, CCI.TypeNode type) { var loc = default(Location); if (type.SourceContext.Document != null) { loc = type.SourceContext.ToLocation(); } else if (type.Name != null && type.Name.SourceContext.Document != null) { loc = type.Name.SourceContext.ToLocation(); } return(new MessageContext (parent, loc, sb => { sb.Append("Type "); sb.Append(type.FullName); })); }
public bool GetValue <T>(MessageContext ctxt, CCI.AttributeNode attribute, CCI.TypeNode attrType, IProperty <T> property, ref T value) { var expr = default(CCI.Literal); if (property.Position >= 0) { expr = attribute.GetPositionalArgument(property.Position) as CCI.Literal; } if (expr == null) { expr = attribute.GetNamedArgument(CCI.Identifier.For(property.Name)) as CCI.Literal; } if (expr != null) { value = property.Value(RewriterMsgContext.AttributeProperty(ctxt, attribute, property.Name), expr.Value); return(true); } else { return(false); } }
private void CheckTypeDefn(CCI.AssemblyNode expectedContainingAssembly, CCI.TypeNode typeDefn) { if (typeDefn.DeclaringModule == null || typeDefn.DeclaringModule.ContainingAssembly == null || typeDefn.DeclaringModule.ContainingAssembly != expectedContainingAssembly || typeDefn.Name == null) { var refName = expectedContainingAssembly.StrongName; var refInfo = default(Info); var refFilename = "<unknown>"; if (strongNameToInfo.TryGetValue(refName, out refInfo)) { refFilename = refInfo.FileName; } env.Log(new UnresolvableReferenceMessage(refName, refFilename, "<unknown>")); throw new ExitException(); } foreach (var member in typeDefn.Members) { var nestedTypeDefn = member as CCI.TypeNode; if (nestedTypeDefn != null) { CheckTypeDefn(expectedContainingAssembly, nestedTypeDefn); } } }
public bool GetValue <T>(MessageContext ctxt, CCI.Node node, CCI.TypeNode attrType, IProperty <T> property, bool inheritable, ref T value) { var assembly = node as CCI.AssemblyNode; if (assembly != null) { // Assembly has no parent return(GetValue (RewriterMsgContext.Assembly(ctxt, assembly), assembly.Attributes, attrType, property, ref value)); } var member = node as CCI.Member; if (member == null) { return(false); } if (GetValue(RewriterMsgContext.Member(ctxt, member), member.Attributes, attrType, property, ref value)) { return(true); } if (inheritable) { var type = node as CCI.TypeNode; if (type != null) { // Suppress inheritance for compiler-generated types, such as delegate environments if (!HasAttribute(member.Attributes, env.CompilerGeneratedAttributeType)) { if (type.DeclaringType != null) { // Parent of nested type is declaring type return(GetValue (RewriterMsgContext.Type(ctxt, type), type.DeclaringType, attrType, property, true, ref value)); } else { // Parent of type is assembly return(GetValue (ctxt, type.DeclaringModule.ContainingAssembly, attrType, property, true, ref value)); } } } var prop = node as CCI.Property; if (prop != null) { // Parent of property is type return(GetValue(ctxt, prop.DeclaringType, attrType, property, true, ref value)); } var evnt = node as CCI.Event; if (evnt != null) { // Parent of event is type return(GetValue(ctxt, evnt.DeclaringType, attrType, property, true, ref value)); } var method = node as CCI.Method; if (method != null) { if (method.DeclaringMember != null) { // Parent of getter/setter/adder/remover is declaring member return(GetValue(ctxt, method.DeclaringMember, attrType, property, true, ref value)); } #if false if (method.IsVirtual && method.OverriddenMethod != null) { var origDefn = method; // Parent of virtual is virtual which introduced slot, unless it is from Object do { origDefn = origDefn.OverriddenMethod; }while (origDefn.IsVirtual && origDefn.OverriddenMethod != null); if (origDefn.DeclaringType != env.ObjectType) { return(GetValue(ctxt, origDefn, attrType, property, true, ref value)); } } #endif // Parent of ordinary method is type return(GetValue(ctxt, method.DeclaringType, attrType, property, true, ref value)); } } return(false); }
public bool HasAttribute(CCI.Node nodeDefn, CCI.TypeNode attrType, bool inheritable) { var assembly = nodeDefn as CCI.AssemblyNode; if (assembly != null) { // Assembly has no parent return(HasAttribute(assembly.Attributes, attrType)); } var member = nodeDefn as CCI.Member; if (member == null) { return(false); } if (HasAttribute(member.Attributes, attrType)) { return(true); } if (inheritable) { var typeDefn = nodeDefn as CCI.TypeNode; if (typeDefn != null) { // Suppress inheritance for compiler-generated types, such as delegate environments if (!HasAttribute(member.Attributes, env.CompilerGeneratedAttributeType)) { if (typeDefn.DeclaringType != null) { // Parent of nested type is outer type return(HasAttribute(typeDefn.DeclaringType, attrType, true)); } else { // Parent of type is assembly return(HasAttribute(typeDefn.DeclaringModule, attrType, true)); } } } var propDefn = nodeDefn as CCI.Property; if (propDefn != null) { // Parent of property is type return(HasAttribute(propDefn.DeclaringType, attrType, true)); } var evntDefn = nodeDefn as CCI.Event; if (evntDefn != null) { // Parent of event is type return(HasAttribute(evntDefn.DeclaringType, attrType, true)); } var methodDefn = nodeDefn as CCI.Method; if (methodDefn != null) { if (methodDefn.DeclaringMember != null) { // Parent of getter/setter/adder/remover is property/event return(HasAttribute(methodDefn.DeclaringMember, attrType, true)); } #if false if (methodDefn.IsVirtual && methodDefn.OverriddenMethod != null) { var origDefn = methodDefn; // Overridding methods have two parents: the virtual which introduced slot, and declaring type do { origDefn = origDefn.OverriddenMethod; }while (origDefn.IsVirtual && origDefn.OverriddenMethod != null); if (origDefn.DeclaringType != env.ObjectType && HasAttribute(origDefn, attrType, true)) { return(true); } } #endif // Parent of ordinary method is type return(HasAttribute(methodDefn.DeclaringType, attrType, true)); } } return(false); }
// ---------------------------------------------------------------------- // Finding attributes and properties // ---------------------------------------------------------------------- public bool IsAttribute(CCI.AttributeNode attr, CCI.TypeNode attrType) { return(attr.Type.IsAssignableTo(attrType)); }
// ---------------------------------------------------------------------- // Framework type helpers // ---------------------------------------------------------------------- public bool IsNullableType(CCI.TypeNode type) { return(type.Template != null && type.TemplateArguments != null && type.TemplateArguments.Count == 1 && type.Template == env.NullableTypeConstructor); }
public T GetValue <T>(MessageContext ctxt, CCI.Node node, CCI.TypeNode attrType, IProperty <T> property) { return(GetValue <T>(ctxt, node, attrType, property, true)); }
public static MessageContext Type(CCI.TypeNode type) { return(Type(null, type)); }
public Global Load() { if (global != null) throw new InvalidOperationException("CCILoader::Load() should be invoked only once"); var strongNameToInfo = new Dictionary<StrongAssemblyName, AssemblyInfo>(); var fileNameToStrongName = new Dictionary<string, StrongAssemblyName>(); // Entry for (referencor strong name, referencee strong name) for references know to be unresolvable var knownBad = new HashSet<string>(); // ---------------------------------------- // The assembly resolver invoked by CCI as needed // ---------------------------------------- CCI.Module.AssemblyReferenceResolver resolver = (target, source) => { var targetinfo = default(AssemblyInfo); var targetsn = StrongAssemblyNameFromCCIReference(target); if (strongNameToInfo.TryGetValue(targetsn, out targetinfo)) return targetinfo.Assembly; else { var sourceInfo = default(AssemblyInfo); var sourceFileName = "<unknown>"; var sourcesn = StrongAssemblyNameFromCCIAssembly(source.ContainingAssembly); if (strongNameToInfo.TryGetValue(sourcesn, out sourceInfo)) sourceFileName = sourceInfo.FileName; var key = "(" + sourcesn + "," + targetsn + ")"; if (!knownBad.Contains(key)) { knownBad.Add(key); log (new UnresolvableReferenceMessage (source.ContainingAssembly.StrongName, sourceFileName, target.StrongName)); } throw new ExitException(); // turns out CCI will happily swallow this exception and replay it later... } }; // ---------------------------------------- // Which assembly should we use for mscorlib? // ---------------------------------------- var mscorlibCanonicalName = default(string); foreach (var fileName in fileNames) { var canonicalFileName = CanonicalFileName(fileName); if (fileNameToStrongName.ContainsKey(canonicalFileName)) { log(new DuplicateAssemblyFileNameMessage(fileName, canonicalFileName)); throw new ExitException(); } fileNameToStrongName.Add(canonicalFileName, null); var baseName = Path.GetFileNameWithoutExtension(canonicalFileName); if (baseName.Equals("mscorlib", StringComparison.OrdinalIgnoreCase)) { if (mscorlibCanonicalName != null) { log(new DuplicateSpecialAssemblyMessage("mscorlib", mscorlibCanonicalName, canonicalFileName)); throw new ExitException(); } mscorlibCanonicalName = canonicalFileName; } } if (mscorlibCanonicalName == null) { log(new MissingSpecialAssemblyMessage("mscorlib")); throw new ExitException(); } // ---------------------------------------- // Initialize CCI, which will implicitly load mscorlib // ---------------------------------------- var frameworkDir = Path.GetDirectoryName(mscorlibCanonicalName); if (!Directory.Exists(frameworkDir)) { log(new UnloadableMSCorLibMessage(frameworkDir)); throw new ExitException(); } // These special CCI assemblies, and mscorlib, will be picked up from the framework directory CCI.SystemDataAssemblyLocation.Location = null; CCI.SystemXmlAssemblyLocation.Location = null; CCI.TargetPlatform.SetToV2(frameworkDir); // At this point we could "fixup" CCI's hard-wired system assembly references: // // foreach (var asmRefs in CCI.TargetPlatform.AssemblyReferenceFor.GetEnumerator()) // { // var asmRef = (CCI.AssemblyReference)asmRefs.Value; // asmRef.Location = <the right place>; // } // SystemAssemblyLocation.Location = <the right place>; // SystemXmlAssemblyLocation.Location = <the right place>; // // But so far that doesn't seem necessary CCI.SystemTypes.Initialize(false, true, resolver); // ---------------------------------------- // Account for mscorlib being loaded // ---------------------------------------- var mscorlib = CCI.SystemTypes.SystemAssembly; if (mscorlib == null || mscorlib.Directory == null) { log(new UnloadableMSCorLibMessage(frameworkDir)); throw new ExitException(); } var mscorlibName = StrongAssemblyNameFromCCIAssembly(mscorlib); fileNameToStrongName[mscorlibCanonicalName] = mscorlibName; strongNameToInfo.Add(mscorlibName, new AssemblyInfo { Assembly = mscorlib, FileName = mscorlibCanonicalName }); log(new LoadedAssemblyMessage(mscorlib.StrongName, mscorlibCanonicalName)); Void = ResolveCCIType(mscorlib, "System", "Void"); ValueType = ResolveCCIType(mscorlib, "System", "ValueType"); Enum = ResolveCCIType(mscorlib, "System", "Enum"); global = new Global(mscorlibName); // The global environment is now ready for use... // ---------------------------------------- // Load the remaining registered assemblies // ---------------------------------------- var pending = new List<string>(); foreach (var kv in fileNameToStrongName) { if (kv.Value == null) pending.Add(kv.Key); // else: must have been mscorlib, which we loaded above } foreach (var canonicalFileName in pending) { var assembly = CCI.AssemblyNode.GetAssembly(canonicalFileName, null, false, true, true); if (assembly == null) { log(new UnloadableAssemblyMessage(canonicalFileName)); throw new ExitException(); } var sn = StrongAssemblyNameFromCCIAssembly(assembly); var info = default(AssemblyInfo); if (strongNameToInfo.TryGetValue(sn, out info)) { log(new DuplicateAssemblyStrongNameMessage(canonicalFileName, sn.ToString(), info.FileName)); throw new ExitException(); } log(new LoadedAssemblyMessage(sn.ToString(), canonicalFileName)); fileNameToStrongName[canonicalFileName] = sn; strongNameToInfo.Add(sn, new AssemblyInfo { Assembly = assembly, FileName = canonicalFileName }); assembly.AssemblyReferenceResolution += resolver; } // ---------------------------------------- // Convert all assemblies. Since we visit all assemblies and types this will also check that // all assembly references resolved to valid assemblies. // ---------------------------------------- // We use the global environment for the first time here... var assemblies = new List<AssemblyDef>(); foreach (var kv in strongNameToInfo) { try { assemblies.Add(AssemblyDefFromCCIAssembly(kv.Value.Assembly)); log(new ResolvedAssemblyMessage(kv.Key.ToString(), kv.Value.FileName)); } catch (InvalidOperationException) { log(new UnresolvableAssemblyMessage(kv.Key.ToString(), kv.Value.FileName)); throw new ExitException(); } } global.AddAssemblies(assemblies); // ---------------------------------------- // Teardown CCI // ---------------------------------------- cciQualifiedTypeNameCache.Clear(); foreach (var kv in strongNameToInfo) kv.Value.Assembly.Dispose(); strongNameToInfo.Clear(); CCI.TargetPlatform.Clear(); return global; }