Browse Source

Fixed SD2-460: Parse error (inner classes in generic types)

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@532 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 21 years ago
parent
commit
51ee84424e
  1. 7
      src/Libraries/NRefactory/Project/Src/Output/CSharp/CSharpOutputVisitor.cs
  2. 7
      src/Libraries/NRefactory/Project/Src/Output/VBNet/VBNetOutputVisitor.cs
  3. 114
      src/Libraries/NRefactory/Project/Src/Parser/AST/General/TypeReference.cs
  4. 2323
      src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs
  5. 80
      src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG
  6. 2437
      src/Libraries/NRefactory/Project/Src/Parser/VBNet/Parser.cs
  7. 191
      src/Libraries/NRefactory/Project/Src/Parser/VBNet/VBNET.ATG
  8. 6
      src/Libraries/NRefactory/Project/Src/Parser/Visitors/AbstractASTVisitor.cs
  9. 1
      src/Libraries/NRefactory/Project/Src/Parser/Visitors/IASTVisitor.cs
  10. 85
      src/Libraries/NRefactory/Test/Parser/Expressions/FieldReferenceExpressionTests.cs
  11. 32
      src/Libraries/NRefactory/Test/Parser/Expressions/TypeOfExpressionTests.cs
  12. 36
      src/Libraries/NRefactory/Test/Parser/Statements/LocalVariableDeclarationTests.cs
  13. 3
      src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs
  14. 16
      src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs
  15. 12
      src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionLoader.cs

7
src/Libraries/NRefactory/Project/Src/Output/CSharp/CSharpOutputVisitor.cs

@ -179,6 +179,13 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
return null; return null;
} }
public object Visit(InnerClassTypeReference typeReference, object data)
{
nodeTracker.TrackedVisit(typeReference.BaseType, data);
outputFormatter.PrintToken(Tokens.Dot);
return Visit((TypeReference)typeReference, data); // call Visit(TypeReference, object)
}
#region Global scope #region Global scope
void VisitAttributes(ICollection attributes, object data) void VisitAttributes(ICollection attributes, object data)
{ {

7
src/Libraries/NRefactory/Project/Src/Output/VBNet/VBNetOutputVisitor.cs

@ -160,6 +160,13 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
return null; return null;
} }
public object Visit(InnerClassTypeReference typeReference, object data)
{
nodeTracker.TrackedVisit(typeReference.BaseType, data);
outputFormatter.PrintToken(Tokens.Dot);
return Visit((TypeReference)typeReference, data); // call Visit(TypeReference, object)
}
#region Global scope #region Global scope
public object Visit(AttributeSection attributeSection, object data) public object Visit(AttributeSection attributeSection, object data)
{ {

114
src/Libraries/NRefactory/Project/Src/Parser/AST/General/TypeReference.cs

@ -80,18 +80,30 @@ namespace ICSharpCode.NRefactory.Parser.AST
return this.Clone(); return this.Clone();
} }
public TypeReference Clone() public virtual TypeReference Clone()
{ {
TypeReference c = new TypeReference(type, systemType); TypeReference c = new TypeReference(type, systemType);
c.pointerNestingLevel = pointerNestingLevel; CopyFields(this, c);
if (rankSpecifier != null) { return c;
c.rankSpecifier = (int[])rankSpecifier.Clone(); }
/// <summary>
/// Copies the pointerNestingLevel, RankSpecifier, GenericTypes and IsGlobal flag
/// from <paramref name="from"/> to <paramref name="to"/>.
/// </summary>
/// <remarks>
/// If <paramref name="to"/> already contains generics, the new generics are appended to the list.
/// </remarks>
protected static void CopyFields(TypeReference from, TypeReference to)
{
to.pointerNestingLevel = from.pointerNestingLevel;
if (from.rankSpecifier != null) {
to.rankSpecifier = (int[])from.rankSpecifier.Clone();
} }
foreach (TypeReference r in genericTypes) { foreach (TypeReference r in from.genericTypes) {
c.genericTypes.Add(r.Clone()); to.genericTypes.Add(r.Clone());
} }
c.isGlobal = isGlobal; to.isGlobal = from.isGlobal;
return c;
} }
public string Type { public string Type {
@ -147,6 +159,11 @@ namespace ICSharpCode.NRefactory.Parser.AST
} }
} }
public static TypeReference CheckNull(TypeReference typeReference)
{
return typeReference ?? NullTypeReference.Instance;
}
public static NullTypeReference Null { public static NullTypeReference Null {
get { get {
return NullTypeReference.Instance; return NullTypeReference.Instance;
@ -171,11 +188,6 @@ namespace ICSharpCode.NRefactory.Parser.AST
} }
} }
public static TypeReference CheckNull(TypeReference typeReference)
{
return typeReference == null ? NullTypeReference.Instance : typeReference;
}
string GetSystemType(string type) string GetSystemType(string type)
{ {
if (types.ContainsKey(type)) { if (types.ContainsKey(type)) {
@ -236,7 +248,26 @@ namespace ICSharpCode.NRefactory.Parser.AST
public override string ToString() public override string ToString()
{ {
return String.Format("[TypeReference: Type={0}, PointerNestingLevel={1}, RankSpecifier={2}]", type, pointerNestingLevel, rankSpecifier); StringBuilder b = new StringBuilder(type);
if (genericTypes != null && genericTypes.Count > 0) {
b.Append('<');
for (int i = 0; i < genericTypes.Count; i++) {
if (i > 0) b.Append(',');
b.Append(genericTypes[i].ToString());
}
b.Append('>');
}
if (pointerNestingLevel > 0) {
b.Append('*', pointerNestingLevel);
}
if (IsArrayType) {
foreach (int rank in rankSpecifier) {
b.Append('[');
b.Append(',', rank);
b.Append(']');
}
}
return b.ToString();
} }
} }
@ -263,4 +294,59 @@ namespace ICSharpCode.NRefactory.Parser.AST
return String.Format("[NullTypeReference]"); return String.Format("[NullTypeReference]");
} }
} }
/// <summary>
/// We need this special type reference for cases like
/// OuterClass(Of T1).InnerClass(Of T2) (in expression or type context)
/// or Dictionary(Of String, NamespaceStruct).KeyCollection (in type context, otherwise it's a
/// MemberReferenceExpression)
/// </summary>
public class InnerClassTypeReference: TypeReference
{
TypeReference baseType;
public TypeReference BaseType {
get {
return baseType;
}
}
public override TypeReference Clone()
{
InnerClassTypeReference c = new InnerClassTypeReference(baseType.Clone(), Type, GenericTypes);
CopyFields(this, c);
return c;
}
public InnerClassTypeReference(TypeReference outerClass, string innerType, List<TypeReference> innerGenericTypes)
: base(innerType, innerGenericTypes)
{
this.baseType = outerClass;
}
public override object AcceptVisitor(IASTVisitor visitor, object data)
{
return visitor.Visit(this, data);
}
/// <summary>
/// Creates a type reference where all type parameters are specified for the innermost class.
/// Namespace.OuterClass(of string).InnerClass(of integer).InnerInnerClass
/// becomes Namespace.OuterClass.InnerClass.InnerInnerClass(of string, integer)
/// </summary>
public TypeReference CombineToNormalTypeReference()
{
TypeReference tr = (baseType is InnerClassTypeReference)
? ((InnerClassTypeReference)baseType).CombineToNormalTypeReference()
: baseType.Clone();
CopyFields(this, tr);
tr.Type += "." + Type;
return tr;
}
public override string ToString()
{
return "[InnerClassTypeReference: (" + baseType.ToString() + ")." + base.ToString() + "]";
}
}
} }

2323
src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs

File diff suppressed because it is too large Load Diff

80
src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG

@ -358,9 +358,14 @@ bool IsLocalVarDecl () {
StartPeek(); StartPeek();
Token pt = la ; Token pt = la ;
string ignore; string ignore;
if (!IsQualident(ref pt, out ignore)) return false;
return IsQualident(ref pt, out ignore) && SkipGeneric(ref pt) && SkipQuestionMark(ref pt) && IsPointerOrDims(ref pt) && if (!SkipGeneric(ref pt)) return false;
pt.kind == Tokens.Identifier; while (pt.kind == Tokens.Dot) {
pt = Peek();
if (!IsQualident(ref pt, out ignore)) return false;
if (!SkipGeneric(ref pt)) return false;
}
return SkipQuestionMark(ref pt) && IsPointerOrDims(ref pt) && pt.kind == Tokens.Identifier;
} }
/* True if lookahead is type parameters (<...>) followed by the specified token */ /* True if lookahead is type parameters (<...>) followed by the specified token */
@ -431,6 +436,7 @@ bool IsTypeReferenceExpression(Expression expr)
if (expr is TypeReferenceExpression) return ((TypeReferenceExpression)expr).TypeReference.GenericTypes.Count == 0; if (expr is TypeReferenceExpression) return ((TypeReferenceExpression)expr).TypeReference.GenericTypes.Count == 0;
while (expr is FieldReferenceExpression) { while (expr is FieldReferenceExpression) {
expr = ((FieldReferenceExpression)expr).TargetObject; expr = ((FieldReferenceExpression)expr).TargetObject;
if (expr is TypeReferenceExpression) return true;
} }
return expr is IdentifierExpression; return expr is IdentifierExpression;
} }
@ -442,19 +448,43 @@ TypeReferenceExpression GetTypeReferenceExpression(Expression expr, List<TypeRef
return new TypeReferenceExpression(new TypeReference(tre.TypeReference.Type, tre.TypeReference.PointerNestingLevel, tre.TypeReference.RankSpecifier, genericTypes)); return new TypeReferenceExpression(new TypeReference(tre.TypeReference.Type, tre.TypeReference.PointerNestingLevel, tre.TypeReference.RankSpecifier, genericTypes));
} }
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
WriteFullTypeName(b, expr); if (!WriteFullTypeName(b, expr)) {
// there is some TypeReferenceExpression hidden in the expression
while (expr is FieldReferenceExpression) {
expr = ((FieldReferenceExpression)expr).TargetObject;
}
tre = expr as TypeReferenceExpression;
if (tre != null) {
TypeReference typeRef = tre.TypeReference;
if (typeRef.GenericTypes.Count == 0) {
typeRef = typeRef.Clone();
typeRef.Type += "." + b.ToString();
typeRef.GenericTypes.AddRange(genericTypes);
} else {
typeRef = new InnerClassTypeReference(typeRef, b.ToString(), genericTypes);
}
return new TypeReferenceExpression(typeRef);
}
}
return new TypeReferenceExpression(new TypeReference(b.ToString(), 0, null, genericTypes)); return new TypeReferenceExpression(new TypeReference(b.ToString(), 0, null, genericTypes));
} }
void WriteFullTypeName(StringBuilder b, Expression expr) /* Writes the type name represented through the expression into the string builder. */
/* Returns true when the expression was converted successfully, returns false when */
/* There was an unknown expression (e.g. TypeReferenceExpression) in it */
bool WriteFullTypeName(StringBuilder b, Expression expr)
{ {
FieldReferenceExpression fre = expr as FieldReferenceExpression; FieldReferenceExpression fre = expr as FieldReferenceExpression;
if (fre != null) { if (fre != null) {
WriteFullTypeName(b, fre.TargetObject); bool result = WriteFullTypeName(b, fre.TargetObject);
b.Append('.'); if (b.Length > 0) b.Append('.');
b.Append(fre.FieldName); b.Append(fre.FieldName);
return result;
} else if (expr is IdentifierExpression) { } else if (expr is IdentifierExpression) {
b.Append(((IdentifierExpression)expr).Identifier); b.Append(((IdentifierExpression)expr).Identifier);
return true;
} else {
return false;
} }
} }
@ -2048,7 +2078,9 @@ PrimaryExpr<out Expression pexpr>
| "null" (.pexpr = new PrimitiveExpression(null, "null"); .) /* from literal token */ | "null" (.pexpr = new PrimitiveExpression(null, "null"); .) /* from literal token */
| Literal (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .) | Literal (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .)
| IF (la.kind == Tokens.Identifier && Peek(1).kind == Tokens.DoubleColon) | IF (la.kind == Tokens.Identifier && Peek(1).kind == Tokens.DoubleColon)
TypeName<out type, false> (. pexpr = new TypeReferenceExpression(type); .) ident (. type = new TypeReference(t.val); .)
"::" (. pexpr = new TypeReferenceExpression(type); .)
ident (. if (type.Type == "global") { type.IsGlobal = true; type.Type = t.val; } else type.Type += "." + t.val; .)
/*--- simple name: */ /*--- simple name: */
| ident (. pexpr = new IdentifierExpression(t.val); .) | ident (. pexpr = new IdentifierExpression(t.val); .)
/*--- parenthesized expression: */ /*--- parenthesized expression: */
@ -2147,14 +2179,15 @@ PrimaryExpr<out Expression pexpr>
| "." ident (. pexpr = new FieldReferenceExpression(pexpr, t.val);.) | "." ident (. pexpr = new FieldReferenceExpression(pexpr, t.val);.)
/* member access on generic type */ /* member access on generic type */
| ( IF (IsGenericFollowedBy(Tokens.Dot) && IsTypeReferenceExpression(pexpr)) | ( IF (IsGenericFollowedBy(Tokens.Dot) && IsTypeReferenceExpression(pexpr))
TypeArgumentList<out typeList> ) TypeArgumentList<out typeList, false> )
"." ident (. pexpr = new FieldReferenceExpression(GetTypeReferenceExpression(pexpr, typeList), t.val);.) "." ident
(. pexpr = new FieldReferenceExpression(GetTypeReferenceExpression(pexpr, typeList), t.val);.)
/*--- invocation expression: */ /*--- invocation expression: */
| "(" (. ArrayList parameters = new ArrayList(); .) | "(" (. ArrayList parameters = new ArrayList(); .)
[ Argument<out expr> (. if (expr != null) {parameters.Add(expr);} .) [ Argument<out expr> (. if (expr != null) {parameters.Add(expr);} .)
{ "," Argument<out expr> (. if (expr != null) {parameters.Add(expr);} .) { "," Argument<out expr> (. if (expr != null) {parameters.Add(expr);} .)
} ] ")" (. pexpr = new InvocationExpression(pexpr, parameters); .) } ] ")" (. pexpr = new InvocationExpression(pexpr, parameters); .)
| ( IF (IsGenericFollowedBy(Tokens.OpenParenthesis)) TypeArgumentList<out typeList> ) | ( IF (IsGenericFollowedBy(Tokens.OpenParenthesis)) TypeArgumentList<out typeList, false> )
"(" (. ArrayList parameters = new ArrayList(); .) "(" (. ArrayList parameters = new ArrayList(); .)
[ Argument<out expr> (. if (expr != null) {parameters.Add(expr);} .) [ Argument<out expr> (. if (expr != null) {parameters.Add(expr);} .)
{ "," Argument<out expr> (. if (expr != null) {parameters.Add(expr);} .) { "," Argument<out expr> (. if (expr != null) {parameters.Add(expr);} .)
@ -2329,14 +2362,7 @@ TypeName<out TypeReference typeRef, bool canBeUnbound>
"::" "::"
] ]
Qualident<out qualident> Qualident<out qualident>
( IF (canBeUnbound && la.kind == Tokens.LessThan && (Peek(1).kind == Tokens.GreaterThan || Peek(1).kind == Tokens.Comma)) [TypeArgumentList<out typeArguments, canBeUnbound>]
(. typeArguments = new List<TypeReference>(); .)
"<"
(. typeArguments.Add(NullTypeReference.Instance); .)
{ "," (. typeArguments.Add(NullTypeReference.Instance); .) }
">"
| [TypeArgumentList<out typeArguments>]
)
(. (.
if (alias == null) { if (alias == null) {
typeRef = new TypeReference(qualident, typeArguments); typeRef = new TypeReference(qualident, typeArguments);
@ -2347,6 +2373,11 @@ TypeName<out TypeReference typeRef, bool canBeUnbound>
typeRef = new TypeReference(alias + "." + qualident, typeArguments); typeRef = new TypeReference(alias + "." + qualident, typeArguments);
} }
.) .)
{ "." (. typeArguments = null; .)
Qualident<out qualident>
[TypeArgumentList<out typeArguments, canBeUnbound>]
(. typeRef = new InnerClassTypeReference(typeRef, qualident, typeArguments); .)
}
. .
@ -2360,14 +2391,19 @@ NullableQuestionMark<ref TypeReference typeRef>
.) .)
. .
TypeArgumentList<out List<TypeReference> types> TypeArgumentList<out List<TypeReference> types, bool canBeUnbound>
(. (.
types = new List<TypeReference>(); types = new List<TypeReference>();
TypeReference type = null; TypeReference type = null;
.) .)
= =
"<" Type<out type> (. types.Add(type); .) "<"
{ "," Type<out type> (. types.Add(type); .) } ( IF (canBeUnbound && (la.kind == Tokens.GreaterThan || la.kind == Tokens.Comma))
(. types.Add(TypeReference.Null); .)
{ "," (. types.Add(TypeReference.Null); .) }
| Type<out type> (. types.Add(type); .)
{ "," Type<out type> (. types.Add(type); .) }
)
">" ">"
. .

2437
src/Libraries/NRefactory/Project/Src/Parser/VBNet/Parser.cs

File diff suppressed because it is too large Load Diff

191
src/Libraries/NRefactory/Project/Src/Parser/VBNet/VBNET.ATG

@ -200,6 +200,53 @@ bool IsMustOverride(Modifiers m)
return m.Contains(Modifier.Abstract); return m.Contains(Modifier.Abstract);
} }
TypeReferenceExpression GetTypeReferenceExpression(Expression expr, List<TypeReference> genericTypes)
{
TypeReferenceExpression tre = expr as TypeReferenceExpression;
if (tre != null) {
return new TypeReferenceExpression(new TypeReference(tre.TypeReference.Type, tre.TypeReference.PointerNestingLevel, tre.TypeReference.RankSpecifier, genericTypes));
}
StringBuilder b = new StringBuilder();
if (!WriteFullTypeName(b, expr)) {
// there is some TypeReferenceExpression hidden in the expression
while (expr is FieldReferenceExpression) {
expr = ((FieldReferenceExpression)expr).TargetObject;
}
tre = expr as TypeReferenceExpression;
if (tre != null) {
TypeReference typeRef = tre.TypeReference;
if (typeRef.GenericTypes.Count == 0) {
typeRef = typeRef.Clone();
typeRef.Type += "." + b.ToString();
typeRef.GenericTypes.AddRange(genericTypes);
} else {
typeRef = new InnerClassTypeReference(typeRef, b.ToString(), genericTypes);
}
return new TypeReferenceExpression(typeRef);
}
}
return new TypeReferenceExpression(new TypeReference(b.ToString(), 0, null, genericTypes));
}
/* Writes the type name represented through the expression into the string builder. */
/* Returns true when the expression was converted successfully, returns false when */
/* There was an unknown expression (e.g. TypeReferenceExpression) in it */
bool WriteFullTypeName(StringBuilder b, Expression expr)
{
FieldReferenceExpression fre = expr as FieldReferenceExpression;
if (fre != null) {
bool result = WriteFullTypeName(b, fre.TargetObject);
if (b.Length > 0) b.Append('.');
b.Append(fre.FieldName);
return result;
} else if (expr is IdentifierExpression) {
b.Append(((IdentifierExpression)expr).Identifier);
return true;
} else {
return false;
}
}
/* /*
True, if lookahead is a local attribute target specifier, True, if lookahead is a local attribute target specifier,
i.e. one of "event", "return", "field", "method", i.e. one of "event", "return", "field", "method",
@ -1678,72 +1725,86 @@ AssignmentOperator<out AssignmentOperatorType op>
/* 11.4 */ /* 11.4 */
SimpleExpr<out Expression pexpr> SimpleExpr<out Expression pexpr>
(. (.
Expression expr; Expression expr;
TypeReference type = null; TypeReference type = null;
string name = String.Empty; string name = String.Empty;
pexpr = null; pexpr = null;
.) = .) =
( (
( (
/* 11.4.1 */ /* 11.4.1 */
LiteralString (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .) LiteralString (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .)
| LiteralCharacter (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .) | LiteralCharacter (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .)
| LiteralSingle (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .) | LiteralSingle (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .)
| LiteralDouble (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .) | LiteralDouble (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .)
| LiteralInteger (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .) | LiteralInteger (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .)
| LiteralDate (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .) | LiteralDate (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .)
| LiteralDecimal (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .) | LiteralDecimal (.pexpr = new PrimitiveExpression(t.literalValue, t.val); .)
/* True, False and Nothing are handled as literals in the spec */ /* True, False and Nothing are handled as literals in the spec */
| "True" (.pexpr = new PrimitiveExpression(true, "true"); .) | "True" (.pexpr = new PrimitiveExpression(true, "true"); .)
| "False" (.pexpr = new PrimitiveExpression(false, "false"); .) | "False" (.pexpr = new PrimitiveExpression(false, "false"); .)
| "Nothing" (.pexpr = new PrimitiveExpression(null, "null"); .) | "Nothing" (.pexpr = new PrimitiveExpression(null, "null"); .)
| /* 11.4.2 */ "(" Expr<out expr> ")" (. pexpr = new ParenthesizedExpression(expr); .) | /* 11.4.2 */ "(" Expr<out expr> ")" (. pexpr = new ParenthesizedExpression(expr); .)
| /* 11.4.4 */ Identifier (. pexpr = new IdentifierExpression(t.val); .) | /* 11.4.4 */ Identifier (. pexpr = new IdentifierExpression(t.val); .)
| (. string val = String.Empty; .) PrimitiveTypeName<out val> | (. string val = String.Empty; .)
PrimitiveTypeName<out val>
"." (. t.val = ""; .) Identifier (. pexpr = new FieldReferenceExpression(new TypeReferenceExpression(val), t.val); .) "." (. t.val = ""; .) Identifier (. pexpr = new FieldReferenceExpression(new TypeReferenceExpression(val), t.val); .)
| "Me" (. pexpr = new ThisReferenceExpression(); .) | "Me" (. pexpr = new ThisReferenceExpression(); .)
| (. Expression retExpr = null; .) | (. Expression retExpr = null; .)
( "MyBase" (. retExpr = new BaseReferenceExpression(); .) ( "MyBase" (. retExpr = new BaseReferenceExpression(); .)
| "MyClass" (. retExpr = new ClassReferenceExpression(); .) | "MyClass" (. retExpr = new ClassReferenceExpression(); .)
) )
"." IdentifierOrKeyword<out name> (. pexpr = new FieldReferenceExpression(retExpr, name); .) "." IdentifierOrKeyword<out name> (. pexpr = new FieldReferenceExpression(retExpr, name); .)
| IF (la.kind == Tokens.Global) TypeName<out type> (. pexpr = new TypeReferenceExpression(type); .) | "Global" "."
| ObjectCreateExpression<out expr> (. pexpr = expr; .) Identifier (. type = new TypeReference(t.val ?? ""); .)
| /* 11.11 */ ( "DirectCast" | "CType" ) "(" Expr<out expr> "," TypeName<out type> ")" (. pexpr = new CastExpression(type, expr); .) /* fallback to "" is required if the token wasn't an identifier (->parser error but no exception) */
| /* 11.11 */ "TryCast" "(" Expr<out expr> "," TypeName<out type> ")" (. pexpr = new BinaryOperatorExpression(expr, BinaryOperatorType.AsCast, new TypeReferenceExpression(type)); .) (. type.IsGlobal = true; .)
| /* 11.11 */ CastTarget<out type> "(" Expr<out expr> ")" (. pexpr = new CastExpression(type, expr, true); .) (. pexpr = new TypeReferenceExpression(type); .)
| /* 11.4.5 */ "AddressOf" Expr<out expr> (. pexpr = new AddressOfExpression(expr); .) | ObjectCreateExpression<out expr> (. pexpr = expr; .)
| /* 11.5.1 */ "GetType" "(" GetTypeTypeName<out type> ")" (. pexpr = new TypeOfExpression(type); .) | /* 11.11 */ ( "DirectCast" | "CType" ) "(" Expr<out expr> "," TypeName<out type> ")" (. pexpr = new CastExpression(type, expr); .)
| /* 11.5.2 */ "TypeOf" SimpleExpr<out expr> "Is" TypeName<out type> (. pexpr = new TypeOfIsExpression(expr, type); .) | /* 11.11 */ "TryCast" "(" Expr<out expr> "," TypeName<out type> ")" (. pexpr = new BinaryOperatorExpression(expr, BinaryOperatorType.AsCast, new TypeReferenceExpression(type)); .)
| /* 11.11 */ CastTarget<out type> "(" Expr<out expr> ")" (. pexpr = new CastExpression(type, expr, true); .)
| /* 11.4.5 */ "AddressOf" Expr<out expr> (. pexpr = new AddressOfExpression(expr); .)
| /* 11.5.1 */ "GetType" "(" GetTypeTypeName<out type> ")" (. pexpr = new TypeOfExpression(type); .)
| /* 11.5.2 */ "TypeOf" SimpleExpr<out expr> "Is" TypeName<out type> (. pexpr = new TypeOfIsExpression(expr, type); .)
) )
{ { InvocationOrMemberReferenceExpression<ref pexpr> }
"." IdentifierOrKeyword<out name> (. pexpr = new FieldReferenceExpression(pexpr, name); .)
| InvocationExpression<ref pexpr>
}
| |
/* this form only occurs in with statements*/ /* this form only occurs in WithStatements*/
"." IdentifierOrKeyword<out name> (. pexpr = new FieldReferenceExpression(pexpr, name);.) "." IdentifierOrKeyword<out name> (. pexpr = new FieldReferenceExpression(pexpr, name);.)
{ { InvocationOrMemberReferenceExpression<ref pexpr> }
"." IdentifierOrKeyword<out name> (. pexpr = new FieldReferenceExpression(pexpr, name); .)
| InvocationExpression<ref pexpr>
}
) )
. .
InvocationOrMemberReferenceExpression<ref Expression pexpr>
(. string name; .)
=
"." IdentifierOrKeyword<out name> (. pexpr = new FieldReferenceExpression(pexpr, name); .)
| InvocationExpression<ref pexpr>
.
InvocationExpression<ref Expression pexpr> InvocationExpression<ref Expression pexpr>
(. List<TypeReference> typeParameters = new List<TypeReference>(); (. List<TypeReference> typeParameters = new List<TypeReference>();
ArrayList parameters = null; ArrayList parameters = null;
TypeReference type; .) TypeReference type; .)
= =
"(" (. Point start = t.Location; .) "(" (. Point start = t.Location; .)
[ "Of" ( "Of"
TypeName<out type> (. if (type != null) typeParameters.Add(type); .) TypeName<out type> (. if (type != null) typeParameters.Add(type); .)
")" "(" ")"
] (
ArgumentList<out parameters> "." Identifier
")" (. pexpr = new FieldReferenceExpression(GetTypeReferenceExpression(pexpr, typeParameters), t.val); .)
(. pexpr = new InvocationExpression(pexpr, parameters, typeParameters); .) | "("
ArgumentList<out parameters>
")"
(. pexpr = new InvocationExpression(pexpr, parameters, typeParameters); .)
)
| ArgumentList<out parameters>
")"
(. pexpr = new InvocationExpression(pexpr, parameters, typeParameters); .)
)
(. pexpr.StartLocation = start; pexpr.EndLocation = t.Location; .) (. pexpr.StartLocation = start; pexpr.EndLocation = t.Location; .)
. .
@ -1975,22 +2036,32 @@ NonArrayTypeName<out TypeReference typeref, bool canBeUnbound>
.) = .) =
( (
[ "Global" "." (. isGlobal = true; .) ] [ "Global" "." (. isGlobal = true; .) ]
Qualident<out name> QualIdentAndTypeArguments<out typeref, canBeUnbound>
(. typeref = new TypeReference(name); typeref.IsGlobal = isGlobal; .) (. typeref.IsGlobal = isGlobal; .)
[IF (la.kind == Tokens.OpenParenthesis && Peek(1).kind == Tokens.Of) { "." (. TypeReference nestedTypeRef; .)
"(" "Of" QualIdentAndTypeArguments<out nestedTypeRef, canBeUnbound>
( IF (canBeUnbound && (la.kind == Tokens.CloseParenthesis || la.kind == Tokens.Comma)) (. typeref = new InnerClassTypeReference(typeref, nestedTypeRef.Type, nestedTypeRef.GenericTypes); .)
(. typeref.GenericTypes.Add(NullTypeReference.Instance); .) }
{ "," (. typeref.GenericTypes.Add(NullTypeReference.Instance); .) }
| TypeArgumentList<typeref.GenericTypes>
)
")"
]
) )
| "Object" (. typeref = new TypeReference("System.Object"); .) | "Object" (. typeref = new TypeReference("System.Object"); .)
| PrimitiveTypeName<out name> (. typeref = new TypeReference(name); .) | PrimitiveTypeName<out name> (. typeref = new TypeReference(name); .)
. .
QualIdentAndTypeArguments<out TypeReference typeref, bool canBeUnbound>
(. string name; typeref = null; .)
=
Qualident<out name>
(. typeref = new TypeReference(name); .)
[IF (la.kind == Tokens.OpenParenthesis && Peek(1).kind == Tokens.Of)
"(" "Of"
( IF (canBeUnbound && (la.kind == Tokens.CloseParenthesis || la.kind == Tokens.Comma))
(. typeref.GenericTypes.Add(NullTypeReference.Instance); .)
{ "," (. typeref.GenericTypes.Add(NullTypeReference.Instance); .) }
| TypeArgumentList<typeref.GenericTypes>
)
")"
]
.
/* 7.9 */ /* 7.9 */
ArrayNameModifier<out ArrayList arrayModifiers> ArrayNameModifier<out ArrayList arrayModifiers>

6
src/Libraries/NRefactory/Project/Src/Parser/Visitors/AbstractASTVisitor.cs

@ -47,6 +47,12 @@ namespace ICSharpCode.NRefactory.Parser
return data; return data;
} }
public virtual object Visit(InnerClassTypeReference innerClassTypeReference, object data)
{
Debug.Assert(innerClassTypeReference != null);
return data;
}
public virtual object Visit(AttributeSection attributeSection, object data) public virtual object Visit(AttributeSection attributeSection, object data)
{ {
Debug.Assert(attributeSection != null); Debug.Assert(attributeSection != null);

1
src/Libraries/NRefactory/Project/Src/Parser/Visitors/IASTVisitor.cs

@ -17,6 +17,7 @@ namespace ICSharpCode.NRefactory.Parser
object Visit(CompilationUnit compilationUnit, object data); object Visit(CompilationUnit compilationUnit, object data);
object Visit(TypeReference typeReference, object data); object Visit(TypeReference typeReference, object data);
object Visit(InnerClassTypeReference innerClassTypeReference, object data);
object Visit(AttributeSection attributeSection, object data); object Visit(AttributeSection attributeSection, object data);
object Visit(ICSharpCode.NRefactory.Parser.AST.Attribute attribute, object data); object Visit(ICSharpCode.NRefactory.Parser.AST.Attribute attribute, object data);
object Visit(NamedArgumentExpression namedArgumentExpression, object data); object Visit(NamedArgumentExpression namedArgumentExpression, object data);

85
src/Libraries/NRefactory/Test/Parser/Expressions/FieldReferenceExpressionTests.cs

@ -1,4 +1,4 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright> // <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license> // <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/> // <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
@ -49,6 +49,35 @@ namespace ICSharpCode.NRefactory.Tests.AST
Assert.AreEqual(1, tr.GenericTypes.Count); Assert.AreEqual(1, tr.GenericTypes.Count);
Assert.AreEqual("System.String", tr.GenericTypes[0].SystemType); Assert.AreEqual("System.String", tr.GenericTypes[0].SystemType);
} }
[Test]
public void CSharpGlobalFullNamespaceGenericFieldReferenceExpressionTest()
{
FieldReferenceExpression fre = (FieldReferenceExpression)ParseUtilCSharp.ParseExpression("global::Namespace.Subnamespace.SomeClass<string>.myField", typeof(FieldReferenceExpression));
Assert.AreEqual("myField", fre.FieldName);
Assert.IsTrue(fre.TargetObject is TypeReferenceExpression);
TypeReference tr = ((TypeReferenceExpression)fre.TargetObject).TypeReference;
Assert.IsFalse(tr is InnerClassTypeReference);
Assert.AreEqual("Namespace.Subnamespace.SomeClass", tr.Type);
Assert.AreEqual(1, tr.GenericTypes.Count);
Assert.AreEqual("System.String", tr.GenericTypes[0].SystemType);
Assert.IsTrue(tr.IsGlobal);
}
[Test]
public void CSharpNestedGenericFieldReferenceExpressionTest()
{
FieldReferenceExpression fre = (FieldReferenceExpression)ParseUtilCSharp.ParseExpression("MyType<string>.InnerClass<int>.myField", typeof(FieldReferenceExpression));
Assert.AreEqual("myField", fre.FieldName);
Assert.IsTrue(fre.TargetObject is TypeReferenceExpression);
InnerClassTypeReference ic = (InnerClassTypeReference)((TypeReferenceExpression)fre.TargetObject).TypeReference;
Assert.AreEqual("InnerClass", ic.Type);
Assert.AreEqual(1, ic.GenericTypes.Count);
Assert.AreEqual("System.Int32", ic.GenericTypes[0].SystemType);
Assert.AreEqual("MyType", ic.BaseType.Type);
Assert.AreEqual(1, ic.BaseType.GenericTypes.Count);
Assert.AreEqual("System.String", ic.BaseType.GenericTypes[0].SystemType);
}
#endregion #endregion
#region VB.NET #region VB.NET
@ -60,6 +89,60 @@ namespace ICSharpCode.NRefactory.Tests.AST
Assert.IsTrue(fre.TargetObject is IdentifierExpression); Assert.IsTrue(fre.TargetObject is IdentifierExpression);
Assert.AreEqual("myTargetObject", ((IdentifierExpression)fre.TargetObject).Identifier); Assert.AreEqual("myTargetObject", ((IdentifierExpression)fre.TargetObject).Identifier);
} }
[Test]
public void VBNetGenericFieldReferenceExpressionTest()
{
FieldReferenceExpression fre = (FieldReferenceExpression)ParseUtilVBNet.ParseExpression("SomeClass(of string).myField", typeof(FieldReferenceExpression));
Assert.AreEqual("myField", fre.FieldName);
Assert.IsTrue(fre.TargetObject is TypeReferenceExpression);
TypeReference tr = ((TypeReferenceExpression)fre.TargetObject).TypeReference;
Assert.AreEqual("SomeClass", tr.Type);
Assert.AreEqual(1, tr.GenericTypes.Count);
Assert.AreEqual("System.String", tr.GenericTypes[0].SystemType);
}
[Test]
public void VBNetFullNamespaceGenericFieldReferenceExpressionTest()
{
FieldReferenceExpression fre = (FieldReferenceExpression)ParseUtilVBNet.ParseExpression("System.Subnamespace.SomeClass(of string).myField", typeof(FieldReferenceExpression));
Assert.AreEqual("myField", fre.FieldName);
Assert.IsTrue(fre.TargetObject is TypeReferenceExpression);
TypeReference tr = ((TypeReferenceExpression)fre.TargetObject).TypeReference;
Assert.AreEqual("System.Subnamespace.SomeClass", tr.Type);
Assert.AreEqual(1, tr.GenericTypes.Count);
Assert.AreEqual("System.String", tr.GenericTypes[0].SystemType);
}
[Test]
public void VBNetGlobalFullNamespaceGenericFieldReferenceExpressionTest()
{
FieldReferenceExpression fre = (FieldReferenceExpression)ParseUtilVBNet.ParseExpression("Global.System.Subnamespace.SomeClass(of string).myField", typeof(FieldReferenceExpression));
Assert.AreEqual("myField", fre.FieldName);
Assert.IsTrue(fre.TargetObject is TypeReferenceExpression);
TypeReference tr = ((TypeReferenceExpression)fre.TargetObject).TypeReference;
Assert.IsFalse(tr is InnerClassTypeReference);
Assert.AreEqual("System.Subnamespace.SomeClass", tr.Type);
Assert.AreEqual(1, tr.GenericTypes.Count);
Assert.AreEqual("System.String", tr.GenericTypes[0].SystemType);
Assert.IsTrue(tr.IsGlobal);
}
[Test]
public void VBNetNestedGenericFieldReferenceExpressionTest()
{
FieldReferenceExpression fre = (FieldReferenceExpression)ParseUtilVBNet.ParseExpression("MyType(of string).InnerClass(of integer).myField", typeof(FieldReferenceExpression));
Assert.AreEqual("myField", fre.FieldName);
Assert.IsTrue(fre.TargetObject is TypeReferenceExpression);
InnerClassTypeReference ic = (InnerClassTypeReference)((TypeReferenceExpression)fre.TargetObject).TypeReference;
Assert.AreEqual("InnerClass", ic.Type);
Assert.AreEqual(1, ic.GenericTypes.Count);
Assert.AreEqual("System.Int32", ic.GenericTypes[0].SystemType);
Assert.AreEqual("MyType", ic.BaseType.Type);
Assert.AreEqual(1, ic.BaseType.GenericTypes.Count);
Assert.AreEqual("System.String", ic.BaseType.GenericTypes[0].SystemType);
}
#endregion #endregion
} }
} }

32
src/Libraries/NRefactory/Test/Parser/Expressions/TypeOfExpressionTests.cs

@ -61,6 +61,22 @@ namespace ICSharpCode.NRefactory.Tests.AST
Assert.AreEqual("System.String", toe.TypeReference.GenericTypes[0].SystemType); Assert.AreEqual("System.String", toe.TypeReference.GenericTypes[0].SystemType);
} }
[Test]
public void CSharpNestedGenericTypeOfExpressionTest()
{
TypeOfExpression toe = (TypeOfExpression)ParseUtilCSharp.ParseExpression("typeof(MyType<string>.InnerClass<int>.InnerInnerClass)", typeof(TypeOfExpression));
InnerClassTypeReference ic = (InnerClassTypeReference)toe.TypeReference;
Assert.AreEqual("InnerInnerClass", ic.Type);
Assert.AreEqual(0, ic.GenericTypes.Count);
ic = (InnerClassTypeReference)ic.BaseType;
Assert.AreEqual("InnerClass", ic.Type);
Assert.AreEqual(1, ic.GenericTypes.Count);
Assert.AreEqual("System.Int32", ic.GenericTypes[0].SystemType);
Assert.AreEqual("MyType", ic.BaseType.Type);
Assert.AreEqual(1, ic.BaseType.GenericTypes.Count);
Assert.AreEqual("System.String", ic.BaseType.GenericTypes[0].SystemType);
}
[Test] [Test]
public void CSharpNullableTypeOfExpressionTest() public void CSharpNullableTypeOfExpressionTest()
{ {
@ -133,6 +149,22 @@ namespace ICSharpCode.NRefactory.Tests.AST
Assert.IsTrue(toe.TypeReference.GenericTypes[0].IsNull); Assert.IsTrue(toe.TypeReference.GenericTypes[0].IsNull);
Assert.IsTrue(toe.TypeReference.GenericTypes[1].IsNull); Assert.IsTrue(toe.TypeReference.GenericTypes[1].IsNull);
} }
[Test]
public void VBNestedGenericTypeOfExpressionTest()
{
TypeOfExpression toe = (TypeOfExpression)ParseUtilVBNet.ParseExpression("GetType(MyType(Of string).InnerClass(of integer).InnerInnerClass)", typeof(TypeOfExpression));
InnerClassTypeReference ic = (InnerClassTypeReference)toe.TypeReference;
Assert.AreEqual("InnerInnerClass", ic.Type);
Assert.AreEqual(0, ic.GenericTypes.Count);
ic = (InnerClassTypeReference)ic.BaseType;
Assert.AreEqual("InnerClass", ic.Type);
Assert.AreEqual(1, ic.GenericTypes.Count);
Assert.AreEqual("System.Int32", ic.GenericTypes[0].SystemType);
Assert.AreEqual("MyType", ic.BaseType.Type);
Assert.AreEqual(1, ic.BaseType.GenericTypes.Count);
Assert.AreEqual("System.String", ic.BaseType.GenericTypes[0].SystemType);
}
#endregion #endregion
} }
} }

36
src/Libraries/NRefactory/Test/Parser/Statements/LocalVariableDeclarationTests.cs

@ -1,4 +1,4 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright> // <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license> // <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/> // <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
@ -47,6 +47,23 @@ namespace ICSharpCode.NRefactory.Tests.AST
// TODO: Check initializer // TODO: Check initializer
} }
[Test]
public void CSharpNestedGenericLocalVariableDeclarationTest()
{
LocalVariableDeclaration lvd = (LocalVariableDeclaration)ParseUtilCSharp.ParseStatment("MyType<string>.InnerClass<int>.InnerInnerClass a;", typeof(LocalVariableDeclaration));
Assert.AreEqual(1, lvd.Variables.Count);
InnerClassTypeReference ic = (InnerClassTypeReference)lvd.GetTypeForVariable(0);
Assert.AreEqual("InnerInnerClass", ic.Type);
Assert.AreEqual(0, ic.GenericTypes.Count);
ic = (InnerClassTypeReference)ic.BaseType;
Assert.AreEqual("InnerClass", ic.Type);
Assert.AreEqual(1, ic.GenericTypes.Count);
Assert.AreEqual("System.Int32", ic.GenericTypes[0].SystemType);
Assert.AreEqual("MyType", ic.BaseType.Type);
Assert.AreEqual(1, ic.BaseType.GenericTypes.Count);
Assert.AreEqual("System.String", ic.BaseType.GenericTypes[0].SystemType);
}
[Test] [Test]
public void CSharpGenericWithArrayLocalVariableDeclarationTest1() public void CSharpGenericWithArrayLocalVariableDeclarationTest1()
{ {
@ -291,6 +308,23 @@ namespace ICSharpCode.NRefactory.Tests.AST
Assert.AreEqual("Integer", type.GenericTypes[0].Type); Assert.AreEqual("Integer", type.GenericTypes[0].Type);
// TODO: Check initializer // TODO: Check initializer
} }
[Test]
public void VBNetNestedGenericLocalVariableDeclarationTest()
{
LocalVariableDeclaration lvd = (LocalVariableDeclaration)ParseUtilVBNet.ParseStatment("Dim a as MyType(of string).InnerClass(of integer).InnerInnerClass", typeof(LocalVariableDeclaration));
Assert.AreEqual(1, lvd.Variables.Count);
InnerClassTypeReference ic = (InnerClassTypeReference)lvd.GetTypeForVariable(0);
Assert.AreEqual("InnerInnerClass", ic.Type);
Assert.AreEqual(0, ic.GenericTypes.Count);
ic = (InnerClassTypeReference)ic.BaseType;
Assert.AreEqual("InnerClass", ic.Type);
Assert.AreEqual(1, ic.GenericTypes.Count);
Assert.AreEqual("System.Int32", ic.GenericTypes[0].SystemType);
Assert.AreEqual("MyType", ic.BaseType.Type);
Assert.AreEqual(1, ic.BaseType.GenericTypes.Count);
Assert.AreEqual("System.String", ic.BaseType.GenericTypes[0].SystemType);
}
#endregion #endregion
} }
} }

3
src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs

@ -484,6 +484,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
{ {
if (reference == null) return null; if (reference == null) return null;
if (reference.IsNull) return null; if (reference.IsNull) return null;
if (reference is InnerClassTypeReference) {
reference = ((InnerClassTypeReference)reference).CombineToNormalTypeReference();
}
LanguageProperties languageProperties = projectContent.Language; LanguageProperties languageProperties = projectContent.Language;
IReturnType t = null; IReturnType t = null;
if (callingClass != null && !reference.IsGlobal) { if (callingClass != null && !reference.IsGlobal) {

16
src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs

@ -1,9 +1,9 @@
/* // <file>
* Created by SharpDevelop. // <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
* User: Daniel Grunwald // <license see="prj:///doc/license.txt">GNU General Public License</license>
* Date: 28.09.2005 // <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
* Time: 19:52 // <version>$Revision$</version>
*/ // </file>
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -76,7 +76,9 @@ namespace ICSharpCode.SharpDevelop.Dom
pc = new ReadWriteHelper(reader).ReadProjectContent(); pc = new ReadWriteHelper(reader).ReadProjectContent();
} }
} }
pc.InitializeSpecialClasses(); if (pc != null) {
pc.InitializeSpecialClasses();
}
return pc; return pc;
} }
#endregion #endregion

12
src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionLoader.cs

@ -1,9 +1,9 @@
/* // <file>
* Created by SharpDevelop. // <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
* User: Daniel Grunwald // <license see="prj:///doc/license.txt">GNU General Public License</license>
* Date: 28.09.2005 // <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
* Time: 18:48 // <version>$Revision$</version>
*/ // </file>
using System; using System;
using System.IO; using System.IO;

Loading…
Cancel
Save