static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos, IEntity entity) { if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '`') { // type parameter reference pos++; if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '`') { // method type parameter reference pos++; int index = ReadTypeParameterCount(reflectionTypeName, ref pos); IMethod method = entity as IMethod; if (method != null && index >= 0 && index < method.TypeParameters.Count) { return(method.TypeParameters[index]); } else { return(SharedTypes.UnknownType); } } else { // class type parameter reference int index = ReadTypeParameterCount(reflectionTypeName, ref pos); ITypeDefinition c = (entity as ITypeDefinition) ?? (entity != null ? entity.DeclaringTypeDefinition : null); if (c != null && index >= 0 && index < c.TypeParameters.Count) { return(c.TypeParameters[index]); } else { return(SharedTypes.UnknownType); } } } // not a type parameter reference: read the actual type name int tpc; string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); ITypeReference reference = new GetClassTypeReference(typeName, tpc); // read type suffixes while (pos < reflectionTypeName.Length) { switch (reflectionTypeName[pos++]) { case '+': typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); reference = new NestedTypeReference(reference, typeName, tpc); break; case '*': reference = new PointerTypeReference(reference); break; case '&': reference = new ByReferenceTypeReference(reference); break; case '[': // this might be an array or a generic type if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '[') { // it's a generic type List <ITypeReference> typeArguments = new List <ITypeReference>(tpc); pos++; typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected end of type argument"); } while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { pos++; if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected another type argument"); } typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected end of type argument"); } } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; reference = new ParameterizedTypeReference(reference, typeArguments); } else { throw new ReflectionNameParseException(pos, "Expected end of generic type"); } } else { // it's an array int dimensions = 1; while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { dimensions++; pos++; } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; // end of array reference = new ArrayTypeReference(reference, dimensions); } else { throw new ReflectionNameParseException(pos, "Invalid array modifier"); } } break; case ',': // assembly qualified name, ignore everything up to the end/next ']' while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']') { pos++; } break; default: pos--; // reset pos to the character we couldn't read if (reflectionTypeName[pos] == ']') { return(reference); // return from a nested generic } else { throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'"); } } } return(reference); }
IEnumerable<ICompletionData> CreateTypeCompletionData(IType hintType) { var wrapper = new CompletionDataWrapper(this); var state = GetState(); Func<IType, IType> pred = null; Action<ICompletionData, IType> typeCallback = null; var inferredTypesCategory = new Category("Inferred Types", null); var derivedTypesCategory = new Category("Derived Types", null); if (hintType != null) { if (hintType.Kind != TypeKind.Unknown) { var lookup = new MemberLookup( ctx.CurrentTypeDefinition, Compilation.MainAssembly ); typeCallback = (data, t) => { //check if type is in inheritance tree. if (hintType.GetDefinition() != null && t.GetDefinition() != null && t.GetDefinition().IsDerivedFrom(hintType.GetDefinition())) { data.CompletionCategory = derivedTypesCategory; } }; pred = t => { if (t.Kind == TypeKind.Interface && hintType.Kind != TypeKind.Array) { return null; } // check for valid constructors if (t.GetConstructors().Count() > 0) { bool isProtectedAllowed = currentType != null ? currentType.Resolve(ctx).GetDefinition().IsDerivedFrom(t.GetDefinition()) : false; if (!t.GetConstructors().Any(m => lookup.IsAccessible( m, isProtectedAllowed ) )) { return null; } } var typeInference = new TypeInference(Compilation); typeInference.Algorithm = TypeInferenceAlgorithm.ImprovedReturnAllResults; var inferedType = typeInference.FindTypeInBounds( new [] { t }, new [] { hintType } ); if (inferedType != SpecialType.UnknownType) { var newType = wrapper.AddType(inferedType, amb.ConvertType(inferedType)); if (newType != null) { newType.CompletionCategory = inferredTypesCategory; } return null; } return t; }; if (!(hintType.Kind == TypeKind.Interface && hintType.Kind != TypeKind.Array)) { DefaultCompletionString = GetShortType(hintType, GetState()); var hint = wrapper.AddType(hintType, DefaultCompletionString); if (hint != null) { hint.CompletionCategory = derivedTypesCategory; } } if (hintType is ParameterizedType && hintType.TypeParameterCount == 1 && hintType.FullName == "System.Collections.Generic.IEnumerable") { var arg = ((ParameterizedType)hintType).TypeArguments.FirstOrDefault(); var array = new ArrayTypeReference(arg.ToTypeReference(), 1).Resolve(ctx); wrapper.AddType(array, amb.ConvertType(array)); } } else { var hint = wrapper.AddType(hintType, DefaultCompletionString); if (hint != null) { DefaultCompletionString = hint.DisplayText; hint.CompletionCategory = derivedTypesCategory; } } } AddTypesAndNamespaces(wrapper, state, null, pred, m => false, typeCallback); if (hintType == null || hintType == SpecialType.UnknownType) { AddKeywords(wrapper, primitiveTypesKeywords.Where(k => k != "void")); } CloseOnSquareBrackets = true; AutoCompleteEmptyMatch = true; return wrapper.Result; }
static ITypeReference ParseTypeName(string typeName, ref int pos) { string reflectionTypeName = typeName; if (pos == typeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); ITypeReference result; if (reflectionTypeName[pos] == '`') { // type parameter reference pos++; if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); if (reflectionTypeName[pos] == '`') { // method type parameter reference pos++; int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos); result = TypeParameterReference.Create(SymbolKind.Method, index); } else { // class type parameter reference int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos); result = TypeParameterReference.Create(SymbolKind.TypeDefinition, index); } } else { // not a type parameter reference: read the actual type name List<ITypeReference> typeArguments = new List<ITypeReference>(); int typeParameterCount; string typeNameWithoutSuffix = ReadTypeName(typeName, ref pos, true, out typeParameterCount, typeArguments); result = new GetPotentiallyNestedClassTypeReference(typeNameWithoutSuffix, typeParameterCount); while (pos < typeName.Length && typeName[pos] == '.') { pos++; string nestedTypeName = ReadTypeName(typeName, ref pos, false, out typeParameterCount, typeArguments); result = new NestedTypeReference(result, nestedTypeName, typeParameterCount); } if (typeArguments.Count > 0) { result = new ParameterizedTypeReference(result, typeArguments); } } while (pos < typeName.Length) { switch (typeName[pos]) { case '[': int dimensions = 1; do { pos++; if (pos == typeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); if (typeName[pos] == ',') dimensions++; } while (typeName[pos] != ']'); result = new ArrayTypeReference(result, dimensions); break; case '*': result = new PointerTypeReference(result); break; case '@': result = new ByReferenceTypeReference(result); break; default: return result; } pos++; } return result; }
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { ArrayTypeReference o = other as ArrayTypeReference; return(o != null && elementType == o.elementType && dimensions == o.dimensions); }
static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos) { if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '`') { // type parameter reference pos++; if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '`') { // method type parameter reference pos++; int index = ReadTypeParameterCount(reflectionTypeName, ref pos); return(new TypeParameterReference(EntityType.Method, index)); } else { // class type parameter reference int index = ReadTypeParameterCount(reflectionTypeName, ref pos); return(new TypeParameterReference(EntityType.TypeDefinition, index)); } } // not a type parameter reference: read the actual type name int tpc; string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); string assemblyName = SkipAheadAndReadAssemblyName(reflectionTypeName, pos); ITypeReference reference = CreateGetClassTypeReference(assemblyName, typeName, tpc); // read type suffixes while (pos < reflectionTypeName.Length) { switch (reflectionTypeName[pos++]) { case '+': typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); reference = new NestedTypeReference(reference, typeName, tpc); break; case '*': reference = new PointerTypeReference(reference); break; case '&': reference = new ByReferenceTypeReference(reference); break; case '[': // this might be an array or a generic type if (pos == reflectionTypeName.Length) { throw new ReflectionNameParseException(pos, "Unexpected end"); } if (reflectionTypeName[pos] == '[') { // it's a generic type List <ITypeReference> typeArguments = new List <ITypeReference>(tpc); pos++; typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected end of type argument"); } while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { pos++; if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected another type argument"); } typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; } else { throw new ReflectionNameParseException(pos, "Expected end of type argument"); } } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; reference = new ParameterizedTypeReference(reference, typeArguments); } else { throw new ReflectionNameParseException(pos, "Expected end of generic type"); } } else { // it's an array int dimensions = 1; while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { dimensions++; pos++; } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; // end of array reference = new ArrayTypeReference(reference, dimensions); } else { throw new ReflectionNameParseException(pos, "Invalid array modifier"); } } break; case ',': // assembly qualified name, ignore everything up to the end/next ']' while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']') { pos++; } break; default: pos--; // reset pos to the character we couldn't read if (reflectionTypeName[pos] == ']') { return(reference); // return from a nested generic } else { throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'"); } } } return(reference); }
static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos, IEntity entity) { if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); if (reflectionTypeName[pos] == '`') { // type parameter reference pos++; if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); if (reflectionTypeName[pos] == '`') { // method type parameter reference pos++; int index = ReadTypeParameterCount(reflectionTypeName, ref pos); IMethod method = entity as IMethod; if (method != null && index >= 0 && index < method.TypeParameters.Count) return method.TypeParameters[index]; else return SharedTypes.UnknownType; } else { // class type parameter reference int index = ReadTypeParameterCount(reflectionTypeName, ref pos); ITypeDefinition c = (entity as ITypeDefinition) ?? (entity != null ? entity.DeclaringTypeDefinition : null); if (c != null && index >= 0 && index < c.TypeParameters.Count) return c.TypeParameters[index]; else return SharedTypes.UnknownType; } } // not a type parameter reference: read the actual type name int tpc; string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); ITypeReference reference = new GetClassTypeReference(typeName, tpc); // read type suffixes while (pos < reflectionTypeName.Length) { switch (reflectionTypeName[pos++]) { case '+': typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); reference = new NestedTypeReference(reference, typeName, tpc); break; case '*': reference = new PointerTypeReference(reference); break; case '&': reference = new ByReferenceTypeReference(reference); break; case '[': // this might be an array or a generic type if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); if (reflectionTypeName[pos] == '[') { // it's a generic type List<ITypeReference> typeArguments = new List<ITypeReference>(tpc); pos++; typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') pos++; else throw new ReflectionNameParseException(pos, "Expected end of type argument"); while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { pos++; if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[') pos++; else throw new ReflectionNameParseException(pos, "Expected another type argument"); typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') pos++; else throw new ReflectionNameParseException(pos, "Expected end of type argument"); } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; reference = new ParameterizedTypeReference(reference, typeArguments); } else { throw new ReflectionNameParseException(pos, "Expected end of generic type"); } } else { // it's an array int dimensions = 1; while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { dimensions++; pos++; } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; // end of array reference = new ArrayTypeReference(reference, dimensions); } else { throw new ReflectionNameParseException(pos, "Invalid array modifier"); } } break; case ',': // assembly qualified name, ignore everything up to the end/next ']' while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']') pos++; break; default: pos--; // reset pos to the character we couldn't read if (reflectionTypeName[pos] == ']') return reference; // return from a nested generic else throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'"); } } return reference; }
static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos) { if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); ITypeReference reference; if (reflectionTypeName[pos] == '`') { // type parameter reference pos++; if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); if (reflectionTypeName[pos] == '`') { // method type parameter reference pos++; int index = ReadTypeParameterCount(reflectionTypeName, ref pos); reference = TypeParameterReference.Create(SymbolKind.Method, index); } else { // class type parameter reference int index = ReadTypeParameterCount(reflectionTypeName, ref pos); reference = TypeParameterReference.Create(SymbolKind.TypeDefinition, index); } } else { // not a type parameter reference: read the actual type name int tpc; string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); string assemblyName = SkipAheadAndReadAssemblyName(reflectionTypeName, pos); reference = CreateGetClassTypeReference(assemblyName, typeName, tpc); } // read type suffixes while (pos < reflectionTypeName.Length) { switch (reflectionTypeName[pos++]) { case '+': int tpc; string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); reference = new NestedTypeReference(reference, typeName, tpc); break; case '*': reference = new PointerTypeReference(reference); break; case '&': reference = new ByReferenceTypeReference(reference); break; case '[': // this might be an array or a generic type if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); if (reflectionTypeName[pos] == '[') { // it's a generic type List<ITypeReference> typeArguments = new List<ITypeReference>(); pos++; typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') pos++; else throw new ReflectionNameParseException(pos, "Expected end of type argument"); while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { pos++; if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[') pos++; else throw new ReflectionNameParseException(pos, "Expected another type argument"); typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') pos++; else throw new ReflectionNameParseException(pos, "Expected end of type argument"); } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; reference = new ParameterizedTypeReference(reference, typeArguments); } else { throw new ReflectionNameParseException(pos, "Expected end of generic type"); } } else { // it's an array int dimensions = 1; while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { dimensions++; pos++; } if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { pos++; // end of array reference = new ArrayTypeReference(reference, dimensions); } else { throw new ReflectionNameParseException(pos, "Invalid array modifier"); } } break; case ',': // assembly qualified name, ignore everything up to the end/next ']' while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']') pos++; break; default: pos--; // reset pos to the character we couldn't read if (reflectionTypeName[pos] == ']') return reference; // return from a nested generic else throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'"); } } return reference; }