Browse Source

Improved C# 3.0 code-completion.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2506 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
57a8cfebb2
  1. 1
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs
  2. 4
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs
  3. 18
      src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorLINQ.cs
  4. 23
      src/Libraries/NRefactory/NRefactoryASTGenerator/AST/Expressions.cs
  5. 224
      src/Libraries/NRefactory/Project/Src/Ast/Generated.cs
  6. 6
      src/Libraries/NRefactory/Project/Src/IAstVisitor.cs
  7. 2
      src/Libraries/NRefactory/Project/Src/Lexer/BuildKeywords.pl
  8. 6
      src/Libraries/NRefactory/Project/Src/Lexer/CSharp/KeywordList.txt
  9. 6
      src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Keywords.cs
  10. 14
      src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Tokens.cs
  11. 2740
      src/Libraries/NRefactory/Project/Src/Parser/CSharp/Parser.cs
  12. 59
      src/Libraries/NRefactory/Project/Src/Parser/CSharp/cs.ATG
  13. 43
      src/Libraries/NRefactory/Project/Src/PrettyPrinter/CSharp/CSharpOutputVisitor.cs
  14. 15
      src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs
  15. 38
      src/Libraries/NRefactory/Project/Src/Visitors/AbstractASTVisitor.cs
  16. 69
      src/Libraries/NRefactory/Project/Src/Visitors/AbstractAstTransformer.cs
  17. 45
      src/Libraries/NRefactory/Project/Src/Visitors/LookupTableVisitor.cs
  18. 33
      src/Libraries/NRefactory/Project/Src/Visitors/NodeTrackingAstVisitor.cs
  19. 20
      src/Libraries/NRefactory/Test/Parser/Expressions/QueryExpressionTests.cs
  20. 15
      src/Main/Base/Project/Src/Project/Solution/Solution.cs
  21. 2
      src/Main/Base/Project/Src/TextEditor/Gui/Dialogs/GotoDialog.cs
  22. 32
      src/Main/Base/Test/MemberLookupHelperTests.cs
  23. 76
      src/Main/Base/Test/NRefactoryResolverTests.cs
  24. 1
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj
  25. 46
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CtrlSpaceResolveHelper.cs
  26. 42
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AnonymousMethodReturnType.cs
  27. 2
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/NullReturnType.cs
  28. 2
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/LanguageProperties.cs
  29. 99
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/LazyList.cs
  30. 64
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs
  31. 56
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs
  32. 84
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/TypeVisitor.cs
  33. 34
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs

1
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs

@ -266,6 +266,7 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -266,6 +266,7 @@ namespace Grunwald.BooBinding.CodeCompletion
if (ctr.ReturnType != null) {
amrt.MethodReturnType = CreateReturnType(ctr.ReturnType, callingClass, callingMember, caretLine, caretColumn, projectContent);
}
amrt.MethodParameters = new List<IParameter>();
AddParameters(ctr.Parameters, amrt.MethodParameters, callingMember, callingClass ?? new DefaultClass(new DefaultCompilationUnit(projectContent), "__Dummy"));
return amrt;
} else {

4
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs

@ -512,7 +512,8 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -512,7 +512,8 @@ namespace Grunwald.BooBinding.CodeCompletion
types[i] = (resolveResult != null) ? resolveResult.ResolvedType : null;
ClearResult();
}
MakeResult(MemberLookupHelper.FindOverload(methods, new IReturnType[0], types));
bool resultIsAcceptable;
MakeResult(MemberLookupHelper.FindOverload(methods, new IReturnType[0], types, out resultIsAcceptable));
}
#endregion
@ -618,6 +619,7 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -618,6 +619,7 @@ namespace Grunwald.BooBinding.CodeCompletion
amrt.MethodReturnType = new BooInferredReturnType(node.Body, resolver.CallingClass,
node.ContainsAnnotation("inline"));
}
amrt.MethodParameters = new List<IParameter>();
ConvertVisitor.AddParameters(node.Parameters, amrt.MethodParameters, resolver.CallingMember, resolver.CallingClass ?? new DefaultClass(resolver.CompilationUnit, "__Dummy"));
MakeResult(amrt);
}

18
src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorLINQ.cs

@ -28,12 +28,6 @@ namespace NRefactoryToBooConverter @@ -28,12 +28,6 @@ namespace NRefactoryToBooConverter
return null;
}
public object VisitQueryExpressionFromGenerator(QueryExpressionFromGenerator queryExpressionFromGenerator, object data)
{
AddError(queryExpressionFromGenerator, "QueryExpressionFromGenerator is not supported.");
return null;
}
public object VisitQueryExpressionGroupClause(QueryExpressionGroupClause queryExpressionGroupClause, object data)
{
AddError(queryExpressionGroupClause, "QueryExpressionGroupClause is not supported.");
@ -63,5 +57,17 @@ namespace NRefactoryToBooConverter @@ -63,5 +57,17 @@ namespace NRefactoryToBooConverter
AddError(queryExpressionWhereClause, "QueryExpressionWhereClause is not supported.");
return null;
}
public object VisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data)
{
AddError(queryExpressionJoinClause, "QueryExpressionJoinClause is not supported.");
return null;
}
public object VisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data)
{
AddError(queryExpressionLetClause, "QueryExpressionLetClause is not supported.");
return null;
}
}
}

23
src/Libraries/NRefactory/NRefactoryASTGenerator/AST/Expressions.cs

@ -248,7 +248,7 @@ namespace NRefactoryASTGenerator.Ast @@ -248,7 +248,7 @@ namespace NRefactoryASTGenerator.Ast
[ImplementNullable(NullableImplementation.Shadow)]
class QueryExpression : Expression {
QueryExpressionFromClause fromClause;
List<QueryExpressionClause> fromOrWhereClauses;
List<QueryExpressionClause> fromLetWhereClauses;
List<QueryExpressionOrdering> orderings;
QueryExpressionClause selectOrGroupClause;
QueryExpressionIntoClause intoClause;
@ -261,17 +261,29 @@ namespace NRefactoryASTGenerator.Ast @@ -261,17 +261,29 @@ namespace NRefactoryASTGenerator.Ast
Expression condition;
}
[ImplementNullable(NullableImplementation.Shadow)]
class QueryExpressionFromClause : QueryExpressionClause {
List<QueryExpressionFromGenerator> generators;
class QueryExpressionLetClause : QueryExpressionClause {
[QuestionMarkDefault]
string identifier;
Expression expression;
}
class QueryExpressionFromGenerator : AbstractNode {
abstract class QueryExpressionFromOrJoinClause : QueryExpressionClause {
TypeReference type;
[QuestionMarkDefault]
string identifier;
Expression inExpression;
}
[ImplementNullable(NullableImplementation.Shadow)]
class QueryExpressionFromClause : QueryExpressionFromOrJoinClause { }
class QueryExpressionJoinClause : QueryExpressionFromOrJoinClause {
Expression onExpression;
Expression equalsExpression;
string intoIdentifier;
}
class QueryExpressionOrdering : AbstractNode {
Expression criteria;
QueryExpressionOrderingDirection direction;
@ -294,6 +306,7 @@ namespace NRefactoryASTGenerator.Ast @@ -294,6 +306,7 @@ namespace NRefactoryASTGenerator.Ast
class QueryExpressionIntoClause : QueryExpressionClause {
[QuestionMarkDefault]
string intoIdentifier;
QueryExpression continuedQuery;
}
}

224
src/Libraries/NRefactory/Project/Src/Ast/Generated.cs

@ -1586,15 +1586,15 @@ namespace ICSharpCode.NRefactory.Ast { @@ -1586,15 +1586,15 @@ namespace ICSharpCode.NRefactory.Ast {
}
}
public bool HasRemoveRegion {
public bool HasAddRegion {
get {
return !removeRegion.IsNull;
return !addRegion.IsNull;
}
}
public bool HasAddRegion {
public bool HasRemoveRegion {
get {
return !addRegion.IsNull;
return !removeRegion.IsNull;
}
}
@ -2250,18 +2250,18 @@ namespace ICSharpCode.NRefactory.Ast { @@ -2250,18 +2250,18 @@ namespace ICSharpCode.NRefactory.Ast {
elseIfSections = new List<ElseIfSection>();
}
public bool HasElseIfSections {
get {
return elseIfSections.Count > 0;
}
}
public IfElseStatement(Expression condition, Statement trueStatement)
: this(condition) {
this.trueStatement.Add(Statement.CheckNull(trueStatement));
}
public bool HasElseIfSections {
get {
return elseIfSections.Count > 0;
}
}
public IfElseStatement(Expression condition, Statement trueStatement, Statement falseStatement)
: this(condition) {
@ -2388,12 +2388,6 @@ namespace ICSharpCode.NRefactory.Ast { @@ -2388,12 +2388,6 @@ namespace ICSharpCode.NRefactory.Ast {
setRegion = PropertySetRegion.Null;
}
public bool IsWriteOnly {
get {
return !HasGetRegion && HasSetRegion;
}
}
public bool IsReadOnly {
get {
return HasGetRegion && !HasSetRegion;
@ -2406,6 +2400,12 @@ namespace ICSharpCode.NRefactory.Ast { @@ -2406,6 +2400,12 @@ namespace ICSharpCode.NRefactory.Ast {
}
}
public bool IsWriteOnly {
get {
return !HasGetRegion && HasSetRegion;
}
}
public bool HasSetRegion {
get {
return !setRegion.IsNull;
@ -3272,15 +3272,21 @@ namespace ICSharpCode.NRefactory.Ast { @@ -3272,15 +3272,21 @@ namespace ICSharpCode.NRefactory.Ast {
setRegion = PropertySetRegion.Null;
}
public bool HasGetRegion {
public bool IsWriteOnly {
get {
return !getRegion.IsNull;
return !HasGetRegion && HasSetRegion;
}
}
public bool HasSetRegion {
get {
return !setRegion.IsNull;
internal PropertyDeclaration(string name, TypeReference typeReference, Modifiers modifier, List<AttributeSection> attributes) : this(modifier, attributes, name, null)
{
this.TypeReference = typeReference;
if ((modifier & Modifiers.ReadOnly) != Modifiers.ReadOnly) {
this.SetRegion = new PropertySetRegion(null, null);
}
if ((modifier & Modifiers.WriteOnly) != Modifiers.WriteOnly) {
this.GetRegion = new PropertyGetRegion(null, null);
}
}
@ -3290,21 +3296,15 @@ namespace ICSharpCode.NRefactory.Ast { @@ -3290,21 +3296,15 @@ namespace ICSharpCode.NRefactory.Ast {
}
}
public bool IsWriteOnly {
public bool HasGetRegion {
get {
return !HasGetRegion && HasSetRegion;
return !getRegion.IsNull;
}
}
internal PropertyDeclaration(string name, TypeReference typeReference, Modifiers modifier, List<AttributeSection> attributes) : this(modifier, attributes, name, null)
{
this.TypeReference = typeReference;
if ((modifier & Modifiers.ReadOnly) != Modifiers.ReadOnly) {
this.SetRegion = new PropertySetRegion(null, null);
}
if ((modifier & Modifiers.WriteOnly) != Modifiers.WriteOnly) {
this.GetRegion = new PropertyGetRegion(null, null);
public bool HasSetRegion {
get {
return !setRegion.IsNull;
}
}
@ -3449,7 +3449,7 @@ namespace ICSharpCode.NRefactory.Ast { @@ -3449,7 +3449,7 @@ namespace ICSharpCode.NRefactory.Ast {
QueryExpressionFromClause fromClause;
List<QueryExpressionClause> fromOrWhereClauses;
List<QueryExpressionClause> fromLetWhereClauses;
List<QueryExpressionOrdering> orderings;
@ -3467,12 +3467,12 @@ namespace ICSharpCode.NRefactory.Ast { @@ -3467,12 +3467,12 @@ namespace ICSharpCode.NRefactory.Ast {
}
}
public List<QueryExpressionClause> FromOrWhereClauses {
public List<QueryExpressionClause> FromLetWhereClauses {
get {
return fromOrWhereClauses;
return fromLetWhereClauses;
}
set {
fromOrWhereClauses = value ?? new List<QueryExpressionClause>();
fromLetWhereClauses = value ?? new List<QueryExpressionClause>();
}
}
@ -3507,7 +3507,7 @@ namespace ICSharpCode.NRefactory.Ast { @@ -3507,7 +3507,7 @@ namespace ICSharpCode.NRefactory.Ast {
public QueryExpression() {
fromClause = QueryExpressionFromClause.Null;
fromOrWhereClauses = new List<QueryExpressionClause>();
fromLetWhereClauses = new List<QueryExpressionClause>();
orderings = new List<QueryExpressionOrdering>();
selectOrGroupClause = QueryExpressionClause.Null;
intoClause = QueryExpressionIntoClause.Null;
@ -3524,8 +3524,8 @@ namespace ICSharpCode.NRefactory.Ast { @@ -3524,8 +3524,8 @@ namespace ICSharpCode.NRefactory.Ast {
}
public override string ToString() {
return string.Format("[QueryExpression FromClause={0} FromOrWhereClauses={1} Orderings={2} SelectOrGrou" +
"pClause={3} IntoClause={4}]", FromClause, GetCollectionString(FromOrWhereClauses), GetCollectionString(Orderings), SelectOrGroupClause, IntoClause);
return string.Format("[QueryExpression FromClause={0} FromLetWhereClauses={1} Orderings={2} SelectOrGro" +
"upClause={3} IntoClause={4}]", FromClause, GetCollectionString(FromLetWhereClauses), GetCollectionString(Orderings), SelectOrGroupClause, IntoClause);
}
}
@ -3582,21 +3582,9 @@ namespace ICSharpCode.NRefactory.Ast { @@ -3582,21 +3582,9 @@ namespace ICSharpCode.NRefactory.Ast {
}
}
public class QueryExpressionFromClause : QueryExpressionClause {
List<QueryExpressionFromGenerator> generators;
public List<QueryExpressionFromGenerator> Generators {
get {
return generators;
}
set {
generators = value ?? new List<QueryExpressionFromGenerator>();
}
}
public class QueryExpressionFromClause : QueryExpressionFromOrJoinClause {
public QueryExpressionFromClause() {
generators = new List<QueryExpressionFromGenerator>();
}
public new static QueryExpressionFromClause Null {
@ -3610,7 +3598,7 @@ namespace ICSharpCode.NRefactory.Ast { @@ -3610,7 +3598,7 @@ namespace ICSharpCode.NRefactory.Ast {
}
public override string ToString() {
return string.Format("[QueryExpressionFromClause Generators={0}]", GetCollectionString(Generators));
return string.Format("[QueryExpressionFromClause Type={0} Identifier={1} InExpression={2}]", Type, Identifier, InExpression);
}
}
@ -3633,12 +3621,23 @@ namespace ICSharpCode.NRefactory.Ast { @@ -3633,12 +3621,23 @@ namespace ICSharpCode.NRefactory.Ast {
}
}
public class QueryExpressionFromGenerator : AbstractNode {
public abstract class QueryExpressionFromOrJoinClause : QueryExpressionClause {
TypeReference type;
string identifier;
Expression inExpression;
public TypeReference Type {
get {
return type;
}
set {
type = value ?? TypeReference.Null;
}
}
public string Identifier {
get {
return identifier;
@ -3657,19 +3656,6 @@ namespace ICSharpCode.NRefactory.Ast { @@ -3657,19 +3656,6 @@ namespace ICSharpCode.NRefactory.Ast {
if (!inExpression.IsNull) inExpression.Parent = this;
}
}
public QueryExpressionFromGenerator() {
identifier = "?";
inExpression = Expression.Null;
}
public override object AcceptVisitor(IAstVisitor visitor, object data) {
return visitor.VisitQueryExpressionFromGenerator(this, data);
}
public override string ToString() {
return string.Format("[QueryExpressionFromGenerator Identifier={0} InExpression={1}]", Identifier, InExpression);
}
}
public class QueryExpressionGroupClause : QueryExpressionClause {
@ -3776,6 +3762,98 @@ namespace ICSharpCode.NRefactory.Ast { @@ -3776,6 +3762,98 @@ namespace ICSharpCode.NRefactory.Ast {
}
}
public class QueryExpressionJoinClause : QueryExpressionFromOrJoinClause {
Expression onExpression;
Expression equalsExpression;
string intoIdentifier;
public Expression OnExpression {
get {
return onExpression;
}
set {
onExpression = value ?? Expression.Null;
if (!onExpression.IsNull) onExpression.Parent = this;
}
}
public Expression EqualsExpression {
get {
return equalsExpression;
}
set {
equalsExpression = value ?? Expression.Null;
if (!equalsExpression.IsNull) equalsExpression.Parent = this;
}
}
public string IntoIdentifier {
get {
return intoIdentifier;
}
set {
intoIdentifier = value ?? "";
}
}
public QueryExpressionJoinClause() {
onExpression = Expression.Null;
equalsExpression = Expression.Null;
intoIdentifier = "";
}
public override object AcceptVisitor(IAstVisitor visitor, object data) {
return visitor.VisitQueryExpressionJoinClause(this, data);
}
public override string ToString() {
return string.Format("[QueryExpressionJoinClause OnExpression={0} EqualsExpression={1} IntoIdentifier={" +
"2} Type={3} Identifier={4} InExpression={5}]", OnExpression, EqualsExpression, IntoIdentifier, Type, Identifier, InExpression);
}
}
public class QueryExpressionLetClause : QueryExpressionClause {
string identifier;
Expression expression;
public string Identifier {
get {
return identifier;
}
set {
identifier = string.IsNullOrEmpty(value) ? "?" : value;
}
}
public Expression Expression {
get {
return expression;
}
set {
expression = value ?? Expression.Null;
if (!expression.IsNull) expression.Parent = this;
}
}
public QueryExpressionLetClause() {
identifier = "?";
expression = Expression.Null;
}
public override object AcceptVisitor(IAstVisitor visitor, object data) {
return visitor.VisitQueryExpressionLetClause(this, data);
}
public override string ToString() {
return string.Format("[QueryExpressionLetClause Identifier={0} Expression={1}]", Identifier, Expression);
}
}
public class QueryExpressionOrdering : AbstractNode {
Expression criteria;
@ -4693,10 +4771,10 @@ public TypeReferenceExpression(string typeName) : this(new TypeReference(typeNam @@ -4693,10 +4771,10 @@ public TypeReferenceExpression(string typeName) : this(new TypeReference(typeNam
Usings = usings;
}
public UsingDeclaration(string @namespace, TypeReference alias) { usings = new List<Using>(1); usings.Add(new Using(@namespace, alias)); }
public UsingDeclaration(string @namespace) : this(@namespace, null) {}
public UsingDeclaration(string @namespace, TypeReference alias) { usings = new List<Using>(1); usings.Add(new Using(@namespace, alias)); }
public override object AcceptVisitor(IAstVisitor visitor, object data) {
return visitor.VisitUsingDeclaration(this, data);
}
@ -4871,15 +4949,15 @@ public UsingDeclaration(string @namespace) : this(@namespace, null) {} @@ -4871,15 +4949,15 @@ public UsingDeclaration(string @namespace) : this(@namespace, null) {}
Statement = statement;
}
public bool IsYieldBreak {
public bool IsYieldReturn {
get {
return statement is BreakStatement;
return statement is ReturnStatement;
}
}
public bool IsYieldReturn {
public bool IsYieldBreak {
get {
return statement is ReturnStatement;
return statement is BreakStatement;
}
}

6
src/Libraries/NRefactory/Project/Src/IAstVisitor.cs

@ -165,12 +165,14 @@ namespace ICSharpCode.NRefactory { @@ -165,12 +165,14 @@ namespace ICSharpCode.NRefactory {
object VisitQueryExpressionFromClause(QueryExpressionFromClause queryExpressionFromClause, object data);
object VisitQueryExpressionFromGenerator(QueryExpressionFromGenerator queryExpressionFromGenerator, object data);
object VisitQueryExpressionGroupClause(QueryExpressionGroupClause queryExpressionGroupClause, object data);
object VisitQueryExpressionIntoClause(QueryExpressionIntoClause queryExpressionIntoClause, object data);
object VisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data);
object VisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data);
object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data);
object VisitQueryExpressionSelectClause(QueryExpressionSelectClause queryExpressionSelectClause, object data);

2
src/Libraries/NRefactory/Project/Src/Lexer/BuildKeywords.pl

@ -127,7 +127,7 @@ sub write_keywordfile @@ -127,7 +127,7 @@ sub write_keywordfile
sub write_token {
$formattedString = sprintf("%-20s", ucfirst $tokenName);
if ($tokenName eq "GetType") {
if (($tokenName eq "GetType") or ($tokenName eq "equals")) {
print DAT "\t\tnew public const int $formattedString = $tokenValue;\n";
} else {
print DAT "\t\tpublic const int $formattedString = $tokenValue;\n";

6
src/Libraries/NRefactory/Project/Src/Lexer/CSharp/KeywordList.txt

@ -170,11 +170,15 @@ LambdaArrow = "=>" @@ -170,11 +170,15 @@ LambdaArrow = "=>"
"ascending"
"descending"
"orderby"
"let"
"join"
"on"
"equals"
#Sets
# When changing IdentifierTokens, ensure you also change the "Identifier" production in cs.ATG
IdentifierTokens(Identifier, "partial", "where", "get", "set", "add", "remove", "yield", "select", "group", "by", "into", "from", "ascending", "descending", "orderby")
IdentifierTokens(Identifier, "partial", "where", "get", "set", "add", "remove", "yield", "select", "group", "by", "into", "from", "ascending", "descending", "orderby", "let", "join", "on", "equals")
OverloadableUnaryOp("-", "!", "~", "++", "--", "true", "false")
OverloadableBinaryOp("+", "-", "*", "/", "%", "&", "|", "^", "<<", "==", "!=", ">", "<", ">=", "<=")

6
src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Keywords.cs

@ -97,7 +97,11 @@ namespace ICSharpCode.NRefactory.Parser.CSharp @@ -97,7 +97,11 @@ namespace ICSharpCode.NRefactory.Parser.CSharp
"from",
"ascending",
"descending",
"orderby"
"orderby",
"let",
"join",
"on",
"equals"
};
static LookupTable keywords = new LookupTable(true);

14
src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Tokens.cs

@ -152,8 +152,12 @@ namespace ICSharpCode.NRefactory.Parser.CSharp @@ -152,8 +152,12 @@ namespace ICSharpCode.NRefactory.Parser.CSharp
public const int Ascending = 138;
public const int Descending = 139;
public const int Orderby = 140;
public const int Let = 141;
public const int Join = 142;
public const int On = 143;
new public const int Equals = 144;
public const int MaxToken = 141;
public const int MaxToken = 145;
static BitArray NewSet(params int[] values)
{
BitArray bitArray = new BitArray(MaxToken);
@ -162,13 +166,13 @@ namespace ICSharpCode.NRefactory.Parser.CSharp @@ -162,13 +166,13 @@ namespace ICSharpCode.NRefactory.Parser.CSharp
}
return bitArray;
}
public static BitArray IdentifierTokens = NewSet(Identifier, Partial, Where, Get, Set, Add, Remove, Yield, Select, Group, By, Into, From, Ascending, Descending, Orderby);
public static BitArray IdentifierTokens = NewSet(Identifier, Partial, Where, Get, Set, Add, Remove, Yield, Select, Group, By, Into, From, Ascending, Descending, Orderby, Let, Join, On, Equals);
public static BitArray OverloadableUnaryOp = NewSet(Minus, Not, BitwiseComplement, Increment, Decrement, True, False);
public static BitArray OverloadableBinaryOp = NewSet(Plus, Minus, Times, Div, Mod, BitwiseAnd, BitwiseOr, Xor, ShiftLeft, Equal, NotEqual, GreaterThan, LessThan, GreaterEqual, LessEqual);
public static BitArray TypeKW = NewSet(Char, Bool, Object, String, Sbyte, Byte, Short, Ushort, Int, Uint, Long, Ulong, Float, Double, Decimal);
public static BitArray UnaryHead = NewSet(Plus, Minus, Not, BitwiseComplement, Times, Increment, Decrement, BitwiseAnd);
public static BitArray AssnStartOp = NewSet(Plus, Minus, Not, BitwiseComplement, Times);
public static BitArray CastFollower = NewSet(Identifier, Partial, Where, Get, Set, Add, Remove, Yield, Select, Group, By, Into, From, Ascending, Descending, Orderby, Literal, OpenParenthesis, New, This, Base, Null, Checked, Unchecked, Typeof, Sizeof, Delegate, Minus, Not, BitwiseComplement, Increment, Decrement, True, False, Plus, Minus, Not, BitwiseComplement, Times, Increment, Decrement, BitwiseAnd);
public static BitArray CastFollower = NewSet(Identifier, Partial, Where, Get, Set, Add, Remove, Yield, Select, Group, By, Into, From, Ascending, Descending, Orderby, Let, Join, On, Equals, Literal, OpenParenthesis, New, This, Base, Null, Checked, Unchecked, Typeof, Sizeof, Delegate, Minus, Not, BitwiseComplement, Increment, Decrement, True, False, Plus, Minus, Not, BitwiseComplement, Times, Increment, Decrement, BitwiseAnd);
public static BitArray AssgnOps = NewSet(Assign, PlusAssign, MinusAssign, TimesAssign, DivAssign, ModAssign, BitwiseAndAssign, BitwiseOrAssign, ShiftLeftAssign);
public static BitArray UnaryOp = NewSet(Plus, Minus, Not, BitwiseComplement, Times, Increment, Decrement, BitwiseAnd);
public static BitArray TypeDeclarationKW = NewSet(Class, Interface, Struct, Enum, Delegate);
@ -318,6 +322,10 @@ namespace ICSharpCode.NRefactory.Parser.CSharp @@ -318,6 +322,10 @@ namespace ICSharpCode.NRefactory.Parser.CSharp
"ascending",
"descending",
"orderby",
"let",
"join",
"on",
"equals",
};
public static string GetTokenString(int token)
{

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

File diff suppressed because it is too large Load Diff

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

@ -162,6 +162,10 @@ TOKENS @@ -162,6 +162,10 @@ TOKENS
"ascending"
"descending"
"orderby"
"let"
"join"
"on"
"equals"
/* END AUTOGENERATED TOKENS SECTION */
/*------------------------------------------------------------------------*
@ -2212,34 +2216,51 @@ QueryExpression<out Expression outExpr> @@ -2212,34 +2216,51 @@ QueryExpression<out Expression outExpr>
QueryExpressionFromClause<out QueryExpressionFromClause fc>
(. fc = new QueryExpressionFromClause(); fc.StartLocation = la.Location;
QueryExpressionFromGenerator fg;
.)
=
"from"
QueryExpressionFromGenerator<out fg> (. SafeAdd(fc, fc.Generators, fg); .)
{ ","
QueryExpressionFromGenerator<out fg> (. SafeAdd(fc, fc.Generators, fg); .)
}
QueryExpressionFromOrJoinClause<fc>
(. fc.EndLocation = t.EndLocation; .)
.
QueryExpressionFromGenerator<out QueryExpressionFromGenerator fg>
(. Expression expr; fg = new QueryExpressionFromGenerator(); fg.StartLocation = la.Location; .)
QueryExpressionJoinClause<out QueryExpressionJoinClause jc>
(. jc = new QueryExpressionJoinClause(); jc.StartLocation = la.Location;
Expression expr;
.)
=
Identifier (. fg.Identifier = t.val; .)
"join"
QueryExpressionFromOrJoinClause<jc>
"on"
Expr<out expr> (. jc.OnExpression = expr; .)
"equals"
Expr<out expr> (. jc.EqualsExpression = expr; .)
[ "into"
Identifier (. jc.IntoIdentifier = t.val; .)
]
(. jc.EndLocation = t.EndLocation; .)
.
QueryExpressionFromOrJoinClause<QueryExpressionFromOrJoinClause fjc>
(. TypeReference type; Expression expr; .)
=
(. fjc.Type = null; .)
/*[ Type<out type> (. fjc.Type = type; .) ]*/
Identifier (. fjc.Identifier = t.val; .)
"in"
Expr<out expr> (. fg.InExpression = expr; .)
(. fg.EndLocation = t.EndLocation; .)
Expr<out expr> (. fjc.InExpression = expr; .)
.
QueryExpressionBody<QueryExpression q>
(. QueryExpressionFromClause fromClause; QueryExpressionWhereClause whereClause;
QueryExpressionLetClause letClause; QueryExpressionJoinClause joinClause;
QueryExpressionSelectClause selectClause; QueryExpressionGroupClause groupClause;
QueryExpressionIntoClause intoClause;
.)
=
{ ( QueryExpressionFromClause<out fromClause> (. SafeAdd<QueryExpressionClause>(q, q.FromOrWhereClauses, fromClause); .)
| QueryExpressionWhereClause<out whereClause> (. SafeAdd<QueryExpressionClause>(q, q.FromOrWhereClauses, whereClause); .)
{ ( QueryExpressionFromClause<out fromClause> (. SafeAdd<QueryExpressionClause>(q, q.FromLetWhereClauses, fromClause); .)
| QueryExpressionWhereClause<out whereClause> (. SafeAdd<QueryExpressionClause>(q, q.FromLetWhereClauses, whereClause); .)
| QueryExpressionLetClause<out letClause> (. SafeAdd<QueryExpressionClause>(q, q.FromLetWhereClauses, letClause); .)
| QueryExpressionJoinClause<out joinClause> (. SafeAdd<QueryExpressionClause>(q, q.FromLetWhereClauses, joinClause); .)
) }
[ QueryExpressionOrderByClause<q> ]
( QueryExpressionSelectClause<out selectClause> (. q.SelectOrGroupClause = selectClause; .)
@ -2256,6 +2277,16 @@ QueryExpressionWhereClause<out QueryExpressionWhereClause wc> @@ -2256,6 +2277,16 @@ QueryExpressionWhereClause<out QueryExpressionWhereClause wc>
(. wc.EndLocation = t.EndLocation; .)
.
QueryExpressionLetClause<out QueryExpressionLetClause wc>
(. Expression expr; wc = new QueryExpressionLetClause(); wc.StartLocation = la.Location; .)
=
"let"
Identifier (. wc.Identifier = t.val; .)
"="
Expr<out expr> (. wc.Expression = expr; .)
(. wc.EndLocation = t.EndLocation; .)
.
QueryExpressionOrderByClause<QueryExpression q>
(. QueryExpressionOrdering ordering; .)
=
@ -2326,6 +2357,10 @@ Identifier @@ -2326,6 +2357,10 @@ Identifier
| "ascending"
| "descending"
| "orderby"
| "let"
| "join"
| "on"
| "equals"
.

43
src/Libraries/NRefactory/Project/Src/PrettyPrinter/CSharp/CSharpOutputVisitor.cs

@ -2566,7 +2566,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter @@ -2566,7 +2566,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
{
outputFormatter.IndentationLevel++;
queryExpression.FromClause.AcceptVisitor(this, data);
queryExpression.FromOrWhereClauses.ForEach(PrintClause);
queryExpression.FromLetWhereClauses.ForEach(PrintClause);
if (queryExpression.Orderings.Count > 0) {
outputFormatter.NewLine();
outputFormatter.Indent();
@ -2593,17 +2593,50 @@ namespace ICSharpCode.NRefactory.PrettyPrinter @@ -2593,17 +2593,50 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
{
outputFormatter.PrintToken(Tokens.From);
outputFormatter.Space();
AppendCommaSeparatedList(fromClause.Generators);
VisitQueryExpressionFromOrJoinClause(fromClause, data);
return null;
}
public override object TrackedVisitQueryExpressionFromGenerator(QueryExpressionFromGenerator fromGenerator, object data)
public override object TrackedVisitQueryExpressionJoinClause(QueryExpressionJoinClause joinClause, object data)
{
outputFormatter.PrintIdentifier(fromGenerator.Identifier);
outputFormatter.PrintToken(Tokens.From);
outputFormatter.Space();
VisitQueryExpressionFromOrJoinClause(joinClause, data);
outputFormatter.Space();
outputFormatter.PrintToken(Tokens.On);
outputFormatter.Space();
joinClause.OnExpression.AcceptVisitor(this, data);
outputFormatter.Space();
outputFormatter.PrintToken(Tokens.Equals);
outputFormatter.Space();
joinClause.EqualsExpression.AcceptVisitor(this, data);
if (!string.IsNullOrEmpty(joinClause.IntoIdentifier)) {
outputFormatter.Space();
outputFormatter.PrintToken(Tokens.Into);
outputFormatter.Space();
outputFormatter.PrintIdentifier(joinClause.IntoIdentifier);
}
return null;
}
void VisitQueryExpressionFromOrJoinClause(QueryExpressionFromOrJoinClause clause, object data)
{
outputFormatter.PrintIdentifier(clause.Identifier);
outputFormatter.Space();
outputFormatter.PrintToken(Tokens.In);
outputFormatter.Space();
return fromGenerator.InExpression.AcceptVisitor(this, data);
clause.InExpression.AcceptVisitor(this, data);
}
public override object TrackedVisitQueryExpressionLetClause(QueryExpressionLetClause letClause, object data)
{
outputFormatter.PrintToken(Tokens.Let);
outputFormatter.Space();
outputFormatter.PrintIdentifier(letClause.Identifier);
outputFormatter.Space();
outputFormatter.PrintToken(Tokens.Assign);
outputFormatter.Space();
return letClause.Expression.AcceptVisitor(this, data);
}
public override object TrackedVisitQueryExpressionGroupClause(QueryExpressionGroupClause groupClause, object data)

15
src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs

@ -2731,11 +2731,6 @@ namespace ICSharpCode.NRefactory.PrettyPrinter @@ -2731,11 +2731,6 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
throw new NotImplementedException();
}
public override object TrackedVisitQueryExpressionFromGenerator(QueryExpressionFromGenerator queryExpressionFromGenerator, object data)
{
throw new NotImplementedException();
}
public override object TrackedVisitQueryExpressionGroupClause(QueryExpressionGroupClause queryExpressionGroupClause, object data)
{
throw new NotImplementedException();
@ -2760,5 +2755,15 @@ namespace ICSharpCode.NRefactory.PrettyPrinter @@ -2760,5 +2755,15 @@ namespace ICSharpCode.NRefactory.PrettyPrinter
{
throw new NotImplementedException();
}
public override object TrackedVisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data)
{
throw new NotImplementedException();
}
public override object TrackedVisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data)
{
throw new NotImplementedException();
}
}
}

38
src/Libraries/NRefactory/Project/Src/Visitors/AbstractASTVisitor.cs

@ -822,12 +822,12 @@ namespace ICSharpCode.NRefactory.Visitors { @@ -822,12 +822,12 @@ namespace ICSharpCode.NRefactory.Visitors {
public virtual object VisitQueryExpression(QueryExpression queryExpression, object data) {
Debug.Assert((queryExpression != null));
Debug.Assert((queryExpression.FromClause != null));
Debug.Assert((queryExpression.FromOrWhereClauses != null));
Debug.Assert((queryExpression.FromLetWhereClauses != null));
Debug.Assert((queryExpression.Orderings != null));
Debug.Assert((queryExpression.SelectOrGroupClause != null));
Debug.Assert((queryExpression.IntoClause != null));
queryExpression.FromClause.AcceptVisitor(this, data);
foreach (QueryExpressionClause o in queryExpression.FromOrWhereClauses) {
foreach (QueryExpressionClause o in queryExpression.FromLetWhereClauses) {
Debug.Assert(o != null);
o.AcceptVisitor(this, data);
}
@ -841,18 +841,10 @@ namespace ICSharpCode.NRefactory.Visitors { @@ -841,18 +841,10 @@ namespace ICSharpCode.NRefactory.Visitors {
public virtual object VisitQueryExpressionFromClause(QueryExpressionFromClause queryExpressionFromClause, object data) {
Debug.Assert((queryExpressionFromClause != null));
Debug.Assert((queryExpressionFromClause.Generators != null));
foreach (QueryExpressionFromGenerator o in queryExpressionFromClause.Generators) {
Debug.Assert(o != null);
o.AcceptVisitor(this, data);
}
return null;
}
public virtual object VisitQueryExpressionFromGenerator(QueryExpressionFromGenerator queryExpressionFromGenerator, object data) {
Debug.Assert((queryExpressionFromGenerator != null));
Debug.Assert((queryExpressionFromGenerator.InExpression != null));
return queryExpressionFromGenerator.InExpression.AcceptVisitor(this, data);
Debug.Assert((queryExpressionFromClause.Type != null));
Debug.Assert((queryExpressionFromClause.InExpression != null));
queryExpressionFromClause.Type.AcceptVisitor(this, data);
return queryExpressionFromClause.InExpression.AcceptVisitor(this, data);
}
public virtual object VisitQueryExpressionGroupClause(QueryExpressionGroupClause queryExpressionGroupClause, object data) {
@ -869,6 +861,24 @@ namespace ICSharpCode.NRefactory.Visitors { @@ -869,6 +861,24 @@ namespace ICSharpCode.NRefactory.Visitors {
return queryExpressionIntoClause.ContinuedQuery.AcceptVisitor(this, data);
}
public virtual object VisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data) {
Debug.Assert((queryExpressionJoinClause != null));
Debug.Assert((queryExpressionJoinClause.Type != null));
Debug.Assert((queryExpressionJoinClause.InExpression != null));
Debug.Assert((queryExpressionJoinClause.OnExpression != null));
Debug.Assert((queryExpressionJoinClause.EqualsExpression != null));
queryExpressionJoinClause.Type.AcceptVisitor(this, data);
queryExpressionJoinClause.InExpression.AcceptVisitor(this, data);
queryExpressionJoinClause.OnExpression.AcceptVisitor(this, data);
return queryExpressionJoinClause.EqualsExpression.AcceptVisitor(this, data);
}
public virtual object VisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data) {
Debug.Assert((queryExpressionLetClause != null));
Debug.Assert((queryExpressionLetClause.Expression != null));
return queryExpressionLetClause.Expression.AcceptVisitor(this, data);
}
public virtual object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) {
Debug.Assert((queryExpressionOrdering != null));
Debug.Assert((queryExpressionOrdering.Criteria != null));

69
src/Libraries/NRefactory/Project/Src/Visitors/AbstractAstTransformer.cs

@ -1515,23 +1515,23 @@ namespace ICSharpCode.NRefactory.Visitors { @@ -1515,23 +1515,23 @@ namespace ICSharpCode.NRefactory.Visitors {
public virtual object VisitQueryExpression(QueryExpression queryExpression, object data) {
Debug.Assert((queryExpression != null));
Debug.Assert((queryExpression.FromClause != null));
Debug.Assert((queryExpression.FromOrWhereClauses != null));
Debug.Assert((queryExpression.FromLetWhereClauses != null));
Debug.Assert((queryExpression.Orderings != null));
Debug.Assert((queryExpression.SelectOrGroupClause != null));
Debug.Assert((queryExpression.IntoClause != null));
nodeStack.Push(queryExpression.FromClause);
queryExpression.FromClause.AcceptVisitor(this, data);
queryExpression.FromClause = ((QueryExpressionFromClause)(nodeStack.Pop()));
for (int i = 0; i < queryExpression.FromOrWhereClauses.Count; i++) {
QueryExpressionClause o = queryExpression.FromOrWhereClauses[i];
for (int i = 0; i < queryExpression.FromLetWhereClauses.Count; i++) {
QueryExpressionClause o = queryExpression.FromLetWhereClauses[i];
Debug.Assert(o != null);
nodeStack.Push(o);
o.AcceptVisitor(this, data);
o = (QueryExpressionClause)nodeStack.Pop();
if (o == null)
queryExpression.FromOrWhereClauses.RemoveAt(i--);
queryExpression.FromLetWhereClauses.RemoveAt(i--);
else
queryExpression.FromOrWhereClauses[i] = o;
queryExpression.FromLetWhereClauses[i] = o;
}
for (int i = 0; i < queryExpression.Orderings.Count; i++) {
QueryExpressionOrdering o = queryExpression.Orderings[i];
@ -1555,27 +1555,14 @@ namespace ICSharpCode.NRefactory.Visitors { @@ -1555,27 +1555,14 @@ namespace ICSharpCode.NRefactory.Visitors {
public virtual object VisitQueryExpressionFromClause(QueryExpressionFromClause queryExpressionFromClause, object data) {
Debug.Assert((queryExpressionFromClause != null));
Debug.Assert((queryExpressionFromClause.Generators != null));
for (int i = 0; i < queryExpressionFromClause.Generators.Count; i++) {
QueryExpressionFromGenerator o = queryExpressionFromClause.Generators[i];
Debug.Assert(o != null);
nodeStack.Push(o);
o.AcceptVisitor(this, data);
o = (QueryExpressionFromGenerator)nodeStack.Pop();
if (o == null)
queryExpressionFromClause.Generators.RemoveAt(i--);
else
queryExpressionFromClause.Generators[i] = o;
}
return null;
}
public virtual object VisitQueryExpressionFromGenerator(QueryExpressionFromGenerator queryExpressionFromGenerator, object data) {
Debug.Assert((queryExpressionFromGenerator != null));
Debug.Assert((queryExpressionFromGenerator.InExpression != null));
nodeStack.Push(queryExpressionFromGenerator.InExpression);
queryExpressionFromGenerator.InExpression.AcceptVisitor(this, data);
queryExpressionFromGenerator.InExpression = ((Expression)(nodeStack.Pop()));
Debug.Assert((queryExpressionFromClause.Type != null));
Debug.Assert((queryExpressionFromClause.InExpression != null));
nodeStack.Push(queryExpressionFromClause.Type);
queryExpressionFromClause.Type.AcceptVisitor(this, data);
queryExpressionFromClause.Type = ((TypeReference)(nodeStack.Pop()));
nodeStack.Push(queryExpressionFromClause.InExpression);
queryExpressionFromClause.InExpression.AcceptVisitor(this, data);
queryExpressionFromClause.InExpression = ((Expression)(nodeStack.Pop()));
return null;
}
@ -1601,6 +1588,36 @@ namespace ICSharpCode.NRefactory.Visitors { @@ -1601,6 +1588,36 @@ namespace ICSharpCode.NRefactory.Visitors {
return null;
}
public virtual object VisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data) {
Debug.Assert((queryExpressionJoinClause != null));
Debug.Assert((queryExpressionJoinClause.Type != null));
Debug.Assert((queryExpressionJoinClause.InExpression != null));
Debug.Assert((queryExpressionJoinClause.OnExpression != null));
Debug.Assert((queryExpressionJoinClause.EqualsExpression != null));
nodeStack.Push(queryExpressionJoinClause.Type);
queryExpressionJoinClause.Type.AcceptVisitor(this, data);
queryExpressionJoinClause.Type = ((TypeReference)(nodeStack.Pop()));
nodeStack.Push(queryExpressionJoinClause.InExpression);
queryExpressionJoinClause.InExpression.AcceptVisitor(this, data);
queryExpressionJoinClause.InExpression = ((Expression)(nodeStack.Pop()));
nodeStack.Push(queryExpressionJoinClause.OnExpression);
queryExpressionJoinClause.OnExpression.AcceptVisitor(this, data);
queryExpressionJoinClause.OnExpression = ((Expression)(nodeStack.Pop()));
nodeStack.Push(queryExpressionJoinClause.EqualsExpression);
queryExpressionJoinClause.EqualsExpression.AcceptVisitor(this, data);
queryExpressionJoinClause.EqualsExpression = ((Expression)(nodeStack.Pop()));
return null;
}
public virtual object VisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data) {
Debug.Assert((queryExpressionLetClause != null));
Debug.Assert((queryExpressionLetClause.Expression != null));
nodeStack.Push(queryExpressionLetClause.Expression);
queryExpressionLetClause.Expression.AcceptVisitor(this, data);
queryExpressionLetClause.Expression = ((Expression)(nodeStack.Pop()));
return null;
}
public virtual object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) {
Debug.Assert((queryExpressionOrdering != null));
Debug.Assert((queryExpressionOrdering.Criteria != null));

45
src/Libraries/NRefactory/Project/Src/Visitors/LookupTableVisitor.cs

@ -137,19 +137,50 @@ namespace ICSharpCode.NRefactory.Visitors @@ -137,19 +137,50 @@ namespace ICSharpCode.NRefactory.Visitors
return base.VisitLambdaExpression(lambdaExpression, data);
}
public override object VisitQueryExpressionFromGenerator(QueryExpressionFromGenerator queryExpressionFromGenerator, object data)
public override object VisitQueryExpressionFromClause(QueryExpressionFromClause fromClause, object data)
{
if (queryExpressionFromGenerator.Parent != null) {
// find parent QueryExpression
QueryExpression parentExpression = queryExpressionFromGenerator.Parent.Parent as QueryExpression;
QueryExpression parentExpression = fromClause.Parent as QueryExpression;
if (parentExpression != null) {
AddVariable(fromClause.Type, fromClause.Identifier,
parentExpression.StartLocation, parentExpression.EndLocation,
false, true, fromClause.InExpression);
}
return base.VisitQueryExpressionFromClause(fromClause, data);
}
public override object VisitQueryExpressionJoinClause(QueryExpressionJoinClause joinClause, object data)
{
if (string.IsNullOrEmpty(joinClause.IntoIdentifier)) {
QueryExpression parentExpression = joinClause.Parent as QueryExpression;
if (parentExpression != null) {
AddVariable(joinClause.Type, joinClause.Identifier,
parentExpression.StartLocation, parentExpression.EndLocation,
false, true, joinClause.InExpression);
}
} else {
AddVariable(joinClause.Type, joinClause.Identifier,
joinClause.StartLocation, joinClause.EndLocation,
false, true, joinClause.InExpression);
QueryExpression parentExpression = joinClause.Parent as QueryExpression;
if (parentExpression != null) {
AddVariable(null, queryExpressionFromGenerator.Identifier,
AddVariable(joinClause.Type, joinClause.IntoIdentifier,
parentExpression.StartLocation, parentExpression.EndLocation,
false, true, queryExpressionFromGenerator.InExpression);
false, false, joinClause.InExpression);
}
}
return base.VisitQueryExpressionFromGenerator(queryExpressionFromGenerator, data);
return base.VisitQueryExpressionJoinClause(joinClause, data);
}
public override object VisitQueryExpressionLetClause(QueryExpressionLetClause letClause, object data)
{
QueryExpression parentExpression = letClause.Parent as QueryExpression;
if (parentExpression != null) {
AddVariable(null, letClause.Identifier,
parentExpression.StartLocation, parentExpression.EndLocation,
false, false, letClause.Expression);
}
return base.VisitQueryExpressionLetClause(letClause, data);
}
public override object VisitForNextStatement(ForNextStatement forNextStatement, object data)

33
src/Libraries/NRefactory/Project/Src/Visitors/NodeTrackingAstVisitor.cs

@ -556,13 +556,6 @@ namespace ICSharpCode.NRefactory.Visitors { @@ -556,13 +556,6 @@ namespace ICSharpCode.NRefactory.Visitors {
return result;
}
public sealed override object VisitQueryExpressionFromGenerator(QueryExpressionFromGenerator queryExpressionFromGenerator, object data) {
this.BeginVisit(queryExpressionFromGenerator);
object result = this.TrackedVisitQueryExpressionFromGenerator(queryExpressionFromGenerator, data);
this.EndVisit(queryExpressionFromGenerator);
return result;
}
public sealed override object VisitQueryExpressionGroupClause(QueryExpressionGroupClause queryExpressionGroupClause, object data) {
this.BeginVisit(queryExpressionGroupClause);
object result = this.TrackedVisitQueryExpressionGroupClause(queryExpressionGroupClause, data);
@ -577,6 +570,20 @@ namespace ICSharpCode.NRefactory.Visitors { @@ -577,6 +570,20 @@ namespace ICSharpCode.NRefactory.Visitors {
return result;
}
public sealed override object VisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data) {
this.BeginVisit(queryExpressionJoinClause);
object result = this.TrackedVisitQueryExpressionJoinClause(queryExpressionJoinClause, data);
this.EndVisit(queryExpressionJoinClause);
return result;
}
public sealed override object VisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data) {
this.BeginVisit(queryExpressionLetClause);
object result = this.TrackedVisitQueryExpressionLetClause(queryExpressionLetClause, data);
this.EndVisit(queryExpressionLetClause);
return result;
}
public sealed override object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) {
this.BeginVisit(queryExpressionOrdering);
object result = this.TrackedVisitQueryExpressionOrdering(queryExpressionOrdering, data);
@ -1101,10 +1108,6 @@ namespace ICSharpCode.NRefactory.Visitors { @@ -1101,10 +1108,6 @@ namespace ICSharpCode.NRefactory.Visitors {
return base.VisitQueryExpressionFromClause(queryExpressionFromClause, data);
}
public virtual object TrackedVisitQueryExpressionFromGenerator(QueryExpressionFromGenerator queryExpressionFromGenerator, object data) {
return base.VisitQueryExpressionFromGenerator(queryExpressionFromGenerator, data);
}
public virtual object TrackedVisitQueryExpressionGroupClause(QueryExpressionGroupClause queryExpressionGroupClause, object data) {
return base.VisitQueryExpressionGroupClause(queryExpressionGroupClause, data);
}
@ -1113,6 +1116,14 @@ namespace ICSharpCode.NRefactory.Visitors { @@ -1113,6 +1116,14 @@ namespace ICSharpCode.NRefactory.Visitors {
return base.VisitQueryExpressionIntoClause(queryExpressionIntoClause, data);
}
public virtual object TrackedVisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data) {
return base.VisitQueryExpressionJoinClause(queryExpressionJoinClause, data);
}
public virtual object TrackedVisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data) {
return base.VisitQueryExpressionLetClause(queryExpressionLetClause, data);
}
public virtual object TrackedVisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) {
return base.VisitQueryExpressionOrdering(queryExpressionOrdering, data);
}

20
src/Libraries/NRefactory/Test/Parser/Expressions/QueryExpressionTests.cs

@ -22,12 +22,11 @@ namespace ICSharpCode.NRefactory.Tests.Ast @@ -22,12 +22,11 @@ namespace ICSharpCode.NRefactory.Tests.Ast
QueryExpression qe = ParseUtilCSharp.ParseExpression<QueryExpression>(
"from c in customers where c.City == \"London\" select c"
);
Assert.AreEqual(1, qe.FromClause.Generators.Count);
Assert.AreEqual("c", qe.FromClause.Generators[0].Identifier);
Assert.AreEqual("customers", ((IdentifierExpression)qe.FromClause.Generators[0].InExpression).Identifier);
Assert.AreEqual(1, qe.FromOrWhereClauses.Count);
Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.FromOrWhereClauses[0]);
QueryExpressionWhereClause wc = (QueryExpressionWhereClause)qe.FromOrWhereClauses[0];
Assert.AreEqual("c", qe.FromClause.Identifier);
Assert.AreEqual("customers", ((IdentifierExpression)qe.FromClause.InExpression).Identifier);
Assert.AreEqual(1, qe.FromLetWhereClauses.Count);
Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.FromLetWhereClauses[0]);
QueryExpressionWhereClause wc = (QueryExpressionWhereClause)qe.FromLetWhereClauses[0];
Assert.IsInstanceOfType(typeof(BinaryOperatorExpression), wc.Condition);
Assert.IsInstanceOfType(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause);
}
@ -41,11 +40,10 @@ where c.City == ""London"" @@ -41,11 +40,10 @@ where c.City == ""London""
from o in c.Orders
where o.OrderDate.Year == 2005
select new { c.Name, o.OrderID, o.Total }");
Assert.AreEqual(1, qe.FromClause.Generators.Count);
Assert.AreEqual(3, qe.FromOrWhereClauses.Count);
Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.FromOrWhereClauses[0]);
Assert.IsInstanceOfType(typeof(QueryExpressionFromClause), qe.FromOrWhereClauses[1]);
Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.FromOrWhereClauses[2]);
Assert.AreEqual(3, qe.FromLetWhereClauses.Count);
Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.FromLetWhereClauses[0]);
Assert.IsInstanceOfType(typeof(QueryExpressionFromClause), qe.FromLetWhereClauses[1]);
Assert.IsInstanceOfType(typeof(QueryExpressionWhereClause), qe.FromLetWhereClauses[2]);
Assert.IsInstanceOfType(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause);
}

15
src/Main/Base/Project/Src/Project/Solution/Solution.cs

@ -29,6 +29,11 @@ namespace ICSharpCode.SharpDevelop.Project @@ -29,6 +29,11 @@ namespace ICSharpCode.SharpDevelop.Project
// contains <guid>, (IProject/ISolutionFolder) pairs.
Dictionary<string, ISolutionFolder> guidDictionary = new Dictionary<string, ISolutionFolder>();
/// <summary>
/// The version number of the solution (9 = Whidbey, 10 = Orcas)
/// </summary>
int versionNumber = 9;
string fileName = String.Empty;
MSBuild.Engine buildEngine = MSBuildInternals.CreateEngine();
@ -333,8 +338,10 @@ namespace ICSharpCode.SharpDevelop.Project @@ -333,8 +338,10 @@ namespace ICSharpCode.SharpDevelop.Project
// we need to specify UTF8 because MSBuild needs the BOM
using (StreamWriter sw = new StreamWriter(fileName, false, Encoding.UTF8)) {
sw.WriteLine();
sw.WriteLine("Microsoft Visual Studio Solution File, Format Version 9.00");
sw.WriteLine("# Visual Studio 2005");
sw.WriteLine("Microsoft Visual Studio Solution File, Format Version " + versionNumber + ".00");
if (versionNumber == 9) {
sw.WriteLine("# Visual Studio 2005");
}
sw.WriteLine("# SharpDevelop " + RevisionClass.FullVersion);
sw.Write(projectSection.ToString());
@ -446,6 +453,10 @@ namespace ICSharpCode.SharpDevelop.Project @@ -446,6 +453,10 @@ namespace ICSharpCode.SharpDevelop.Project
}
break;
case "9.00":
newSolution.versionNumber = 9;
break;
case "10.00":
newSolution.versionNumber = 10;
break;
default:
MessageService.ShowErrorFormatted("${res:SharpDevelop.Solution.UnknownSolutionVersion}", match.Result("${Version}"));

2
src/Main/Base/Project/Src/TextEditor/Gui/Dialogs/GotoDialog.cs

@ -199,7 +199,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -199,7 +199,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (ProjectService.OpenSolution != null) {
foreach (IProject project in ProjectService.OpenSolution.Projects) {
foreach (ProjectItem item in project.Items) {
if (item is FileProjectItem) {
if (item is FileProjectItem && item.ItemType != ItemType.Folder) {
AddSourceFile(text, lineNumber, item);
}
}

32
src/Main/Base/Test/MemberLookupHelperTests.cs

@ -329,5 +329,37 @@ namespace ICSharpCode.SharpDevelop.Tests @@ -329,5 +329,37 @@ namespace ICSharpCode.SharpDevelop.Tests
Assert.IsTrue(MemberLookupHelper.ConversionExists(new ArrayReturnType(msc, msc.SystemTypes.String, 1),
IListOf(CreateT())));
}
[Test]
public void ConversionExistsFromAnonymousDelegateToSystemPredicate()
{
Assert.IsTrue(MemberLookupHelper.ConversionExists(
new AnonymousMethodReturnType(new DefaultCompilationUnit(msc)),
new GetClassReturnType(msc, "System.Predicate", 1)
));
}
[Test]
public void NoConversionExistsFromParameterlessAnonymousDelegateToSystemPredicate()
{
AnonymousMethodReturnType amrt = new AnonymousMethodReturnType(new DefaultCompilationUnit(msc));
amrt.MethodParameters = new List<IParameter>();
Assert.IsFalse(MemberLookupHelper.ConversionExists(
amrt,
new GetClassReturnType(msc, "System.Predicate", 1)
));
}
[Test]
public void ConversionExistsFromAnonymousDelegateWithParameterToSystemPredicate()
{
AnonymousMethodReturnType amrt = new AnonymousMethodReturnType(new DefaultCompilationUnit(msc));
amrt.MethodParameters = new List<IParameter>();
amrt.MethodParameters.Add(new DefaultParameter("test", msc.SystemTypes.Object, DomRegion.Empty));
Assert.IsTrue(MemberLookupHelper.ConversionExists(
amrt,
new GetClassReturnType(msc, "System.Predicate", 1)
));
}
}
}

76
src/Main/Base/Test/NRefactoryResolverTests.cs

@ -1060,6 +1060,82 @@ namespace OtherName { class Bla { } } @@ -1060,6 +1060,82 @@ namespace OtherName { class Bla { } }
#endregion
#region C# 3.0 tests
[Test]
public void ExtensionMethodsTest()
{
string program = @"using XN;
class TestClass {
static void Test(A a, B b, C c) {
}
}
class A { }
class B {
public void F(int i) { }
}
class C {
public void F(object obj) { }
}
namespace XN {
public static class XC {
public static void F(this object obj, int i) { }
public static void F(this object obj, string s) { }
}
}
";
MemberResolveResult mrr;
mrr = Resolve<MemberResolveResult>(program, "a.F(1)", 4);
Assert.AreEqual("XN.XC.F", mrr.ResolvedMember.FullyQualifiedName);
Assert.AreEqual("System.Int32", ((IMethod)mrr.ResolvedMember).Parameters[1].ReturnType.FullyQualifiedName);
mrr = Resolve<MemberResolveResult>(program, "a.F(\"text\")", 4);
Assert.AreEqual("XN.XC.F", mrr.ResolvedMember.FullyQualifiedName);
Assert.AreEqual("System.String", ((IMethod)mrr.ResolvedMember).Parameters[1].ReturnType.FullyQualifiedName);
mrr = Resolve<MemberResolveResult>(program, "b.F(1)", 4);
Assert.AreEqual("B.F", mrr.ResolvedMember.FullyQualifiedName);
mrr = Resolve<MemberResolveResult>(program, "b.F(\"text\")", 4);
Assert.AreEqual("XN.XC.F", mrr.ResolvedMember.FullyQualifiedName);
Assert.AreEqual("System.String", ((IMethod)mrr.ResolvedMember).Parameters[1].ReturnType.FullyQualifiedName);
mrr = Resolve<MemberResolveResult>(program, "c.F(1)", 4);
Assert.AreEqual("C.F", mrr.ResolvedMember.FullyQualifiedName);
mrr = Resolve<MemberResolveResult>(program, "c.F(\"text\")", 4);
Assert.AreEqual("C.F", mrr.ResolvedMember.FullyQualifiedName);
}
[Test]
public void ExtensionMethodsTest2()
{
string program = @"using System; using System.Collections.Generic;
class TestClass {
static void Test(string[] args) {
}
}
public static class XC {
public static int ToInt32(this string s) { return int.Parse(s); }
public static T[] Slice<T>(this T[] source, int index, int count) { throw new NotImplementedException(); }
public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, Predicate<T> predicate) { throw new NotImplementedException(); }
}
";
MemberResolveResult mrr;
mrr = Resolve<MemberResolveResult>(program, "\"text\".ToInt32()", 4);
Assert.AreEqual("XC.ToInt32", mrr.ResolvedMember.FullyQualifiedName);
mrr = Resolve<MemberResolveResult>(program, "args.Slice(1, 2)", 4);
Assert.AreEqual("XC.Slice", mrr.ResolvedMember.FullyQualifiedName);
Assert.AreEqual("System.String[]", mrr.ResolvedType.DotNetName);
mrr = Resolve<MemberResolveResult>(program, "args.Filter(delegate { return true; })", 4);
Assert.AreEqual("XC.Filter", mrr.ResolvedMember.FullyQualifiedName);
Assert.AreEqual("System.Collections.Generic.IEnumerable{System.String}", mrr.ResolvedType.DotNetName);
}
[Test]
public void SimpleLinqTest()
{

1
src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj

@ -86,6 +86,7 @@ @@ -86,6 +86,7 @@
<Compile Include="Src\Implementations\SearchClassReturnType.cs" />
<Compile Include="Src\Implementations\SystemTypes.cs" />
<Compile Include="Src\Interfaces\ExplicitInterfaceImplementation.cs" />
<Compile Include="Src\LazyList.cs" />
<Compile Include="Src\NRefactoryResolver\CSharpToVBNetConvertVisitor.cs" />
<Compile Include="Src\NRefactoryResolver\InferredReturnType.cs" />
<Compile Include="Src\NRefactoryResolver\NRefactoryASTConvertVisitor.cs" />

46
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CtrlSpaceResolveHelper.cs

@ -173,5 +173,51 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -173,5 +173,51 @@ namespace ICSharpCode.SharpDevelop.Dom
}
return null;
}
public static IList<IMethodOrProperty> FindAllExtensions(LanguageProperties language, IClass callingClass)
{
if (language == null)
throw new ArgumentNullException("language");
if (callingClass == null)
throw new ArgumentNullException("callingClass");
List<IMethodOrProperty> res = new List<IMethodOrProperty>();
bool supportsExtensionMethods = language.SupportsExtensionMethods;
bool supportsExtensionProperties = language.SupportsExtensionProperties;
if (supportsExtensionMethods || supportsExtensionProperties) {
ArrayList list = new ArrayList();
IMethod dummyMethod = new DefaultMethod("dummy", VoidReturnType.Instance, ModifierEnum.Static, DomRegion.Empty, DomRegion.Empty, callingClass);
CtrlSpaceResolveHelper.AddContentsFromCalling(list, callingClass, dummyMethod);
CtrlSpaceResolveHelper.AddImportedNamespaceContents(list, callingClass.CompilationUnit, callingClass);
bool searchExtensionsInClasses = language.SearchExtensionsInClasses;
foreach (object o in list) {
IMethodOrProperty mp = o as IMethodOrProperty;
if (mp != null && mp.IsExtensionMethod &&
(supportsExtensionMethods && o is IMethod || supportsExtensionProperties && o is IProperty))
{
res.Add(mp);
} else if (searchExtensionsInClasses && o is IClass) {
IClass c = o as IClass;
if (c.HasExtensionMethods) {
if (supportsExtensionProperties) {
foreach (IProperty p in c.Properties) {
if (p.IsExtensionMethod)
res.Add(p);
}
}
if (supportsExtensionMethods) {
foreach (IMethod m in c.Methods) {
if (m.IsExtensionMethod)
res.Add(m);
}
}
}
}
}
}
return res;
}
}
}

42
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AnonymousMethodReturnType.cs

@ -17,7 +17,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -17,7 +17,7 @@ namespace ICSharpCode.SharpDevelop.Dom
public sealed class AnonymousMethodReturnType : DecoratingReturnType
{
IReturnType returnType;
IList<IParameter> parameters = new List<IParameter>();
IList<IParameter> parameters;
ICompilationUnit cu;
public AnonymousMethodReturnType(ICompilationUnit cu)
@ -60,26 +60,25 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -60,26 +60,25 @@ namespace ICSharpCode.SharpDevelop.Dom
}
/// <summary>
/// Gets the list of method parameters.
/// Gets the list of method parameters. Can be null if the anonymous method has no parameter list.
/// </summary>
public IList<IParameter> MethodParameters {
get {
return parameters;
}
set {
if (value == null) throw new ArgumentNullException("value");
parameters = value;
}
get { return parameters; }
set { parameters = value; }
}
public bool HasParameterList {
get { return parameters != null; }
}
volatile DefaultClass cachedClass;
DefaultClass cachedClass;
public override IClass GetUnderlyingClass()
{
if (cachedClass != null) return cachedClass;
DefaultClass c = new DefaultClass(cu, ClassType.Delegate, ModifierEnum.None, DomRegion.Empty, null);
c.BaseTypes.Add(cu.ProjectContent.SystemTypes.Delegate);
AddDefaultDelegateMethod(c, returnType ?? cu.ProjectContent.SystemTypes.Object, parameters);
AddDefaultDelegateMethod(c, returnType ?? cu.ProjectContent.SystemTypes.Object, parameters ?? new IParameter[0]);
cachedClass = c;
return c;
}
@ -118,17 +117,20 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -118,17 +117,20 @@ namespace ICSharpCode.SharpDevelop.Dom
public override string FullyQualifiedName {
get {
StringBuilder b = new StringBuilder("delegate(");
bool first = true;
foreach (IParameter p in parameters) {
if (first) first = false; else b.Append(", ");
b.Append(p.Name);
if (p.ReturnType != null) {
b.Append(":");
b.Append(p.ReturnType.Name);
StringBuilder b = new StringBuilder("delegate");
if (HasParameterList) {
bool first = true;
b.Append("(");
foreach (IParameter p in parameters) {
if (first) first = false; else b.Append(", ");
b.Append(p.Name);
if (p.ReturnType != null) {
b.Append(":");
b.Append(p.ReturnType.Name);
}
}
b.Append(")");
}
b.Append(")");
if (returnType != null) {
b.Append(":");
b.Append(returnType.Name);

2
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/NullReturnType.cs

@ -13,6 +13,8 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -13,6 +13,8 @@ namespace ICSharpCode.SharpDevelop.Dom
/// <summary>The type of the 'null'/'nothing' literal.</summary>
public sealed class NullReturnType : AbstractReturnType
{
private NullReturnType() {}
public static readonly NullReturnType Instance = new NullReturnType();
public override bool Equals(IReturnType o)

2
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/LanguageProperties.cs

@ -101,7 +101,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -101,7 +101,7 @@ namespace ICSharpCode.SharpDevelop.Dom
/// <summary>
/// Gets if extension methods/properties are searched in imported classes (returns true) or if
/// only the extensions from the current class, imported classes and imported modules are used
/// (returns false). This property has no effect if the language doesn't support
/// (returns false). This property has no effect if the language doesn't support extension methods or properties.
/// </summary>
public virtual bool SearchExtensionsInClasses {
get { return false; }

99
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/LazyList.cs

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
namespace ICSharpCode.SharpDevelop.Dom
{
/// <summary>
/// A list that lazily initializes its content. The base list returned by the initializer may be
/// modified.
/// </summary>
sealed class LazyList<T> : IList<T>
{
readonly Func<IList<T>> initializer;
IList<T> innerList;
public IList<T> InnerList {
get {
if (innerList == null)
innerList = initializer();
return innerList;
}
}
public LazyList(Func<IList<T>> initializer)
{
if (initializer == null) throw new ArgumentNullException("initializer");
this.initializer = initializer;
}
public T this[int index] {
get { return InnerList[index]; }
set { InnerList[index] = value; }
}
public int Count {
get { return InnerList.Count; }
}
public bool IsReadOnly {
get { return InnerList.IsReadOnly; }
}
public int IndexOf(T item)
{
return InnerList.IndexOf(item);
}
public void Insert(int index, T item)
{
InnerList.Insert(index, item);
}
public void RemoveAt(int index)
{
InnerList.RemoveAt(index);
}
public void Add(T item)
{
InnerList.Add(item);
}
public void Clear()
{
InnerList.Clear();
}
public bool Contains(T item)
{
return InnerList.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
InnerList.CopyTo(array, arrayIndex);
}
public bool Remove(T item)
{
return InnerList.Remove(item);
}
public IEnumerator<T> GetEnumerator()
{
return InnerList.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}

64
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs

@ -14,18 +14,30 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -14,18 +14,30 @@ namespace ICSharpCode.SharpDevelop.Dom
/// Class with methods to help finding the correct overload for a member.
/// </summary>
/// <remarks>
/// This class tries to do member lookup as close to the C# spec (ECMA-334, § 14.3) as possible.
/// This class does member lookup like specified by the C# spec (ECMA-334, § 14.3).
/// Other languages might need custom lookup methods.
/// </remarks>
public static class MemberLookupHelper
{
#region FindOverload
public static IMethod FindOverload(IList<IMethod> methods, IReturnType[] typeParameters, IReturnType[] arguments)
/// <summary>
/// Finds the correct overload according to the C# specification.
/// </summary>
/// <param name="methods">List with the methods to check.<br/>
/// <b>Generic methods in the input type are replaced by methods with have the types substituted!</b>
/// </param>
/// <param name="typeParameters">The type parameters passed to the method.</param>
/// <param name="arguments">The types of the arguments passed to the method.</param>
/// <param name="resultIsAcceptable">Out parameter. Will be true if the resulting method
/// is an acceptable match, false if the resulting method is just a guess and will lead
/// to a compile error.</param>
/// <returns>The method that will be called.</returns>
public static IMethod FindOverload(IList<IMethod> methods, IReturnType[] typeParameters, IReturnType[] arguments, out bool resultIsAcceptable)
{
resultIsAcceptable = false;
if (methods.Count == 0)
return null;
bool tmp;
int[] ranking = RankOverloads(methods, typeParameters, arguments, false, out tmp);
int[] ranking = RankOverloads(methods, typeParameters, arguments, false, out resultIsAcceptable);
int bestRanking = -1;
int best = 0;
for (int i = 0; i < ranking.Length; i++) {
@ -61,7 +73,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -61,7 +73,7 @@ namespace ICSharpCode.SharpDevelop.Dom
/// <summary>
/// Assigns a ranking score to each method in the <paramref name="list"/>.
/// </summary>
/// <param name="list">Link with the methods to check.<br/>
/// <param name="list">List with the methods to check.<br/>
/// <b>Generic methods in the input type are replaced by methods with have the types substituted!</b>
/// </param>
/// <param name="typeParameters">List with the type parameters passed to the method.
@ -212,7 +224,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -212,7 +224,7 @@ namespace ICSharpCode.SharpDevelop.Dom
// the old member is better
ranking[i] = score - 1;
// this is not really correct, we would need to compare the member with other members
// but this works as we're mostly interested in the best overload only
// but this works as we're interested in the best overload only
break;
}
}
@ -397,20 +409,25 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -397,20 +409,25 @@ namespace ICSharpCode.SharpDevelop.Dom
/// Returns false when expectedArgument and passedArgument are incompatible, otherwise true
/// is returned (true is used both for successful inferring and other kind of errors).
/// </summary>
/// <remarks>
/// The C# spec (§ 25.6.4) has a bug: it says that type inference works if the passedArgument is IEnumerable{T}
/// and the expectedArgument is an array; passedArgument and expectedArgument must be swapped here.
/// </remarks>
public static bool InferTypeArgument(IReturnType expectedArgument, IReturnType passedArgument, IReturnType[] outputArray)
{
if (expectedArgument == null) return true;
if (passedArgument == null) return true; // TODO: NullTypeReference
if (expectedArgument.IsArrayReturnType) {
IReturnType expectedArrayElementType = expectedArgument.CastToArrayReturnType().ArrayElementType;
if (passedArgument.IsArrayReturnType && expectedArgument.CastToArrayReturnType().ArrayDimensions == passedArgument.CastToArrayReturnType().ArrayDimensions) {
return InferTypeArgument(expectedArrayElementType, passedArgument.CastToArrayReturnType().ArrayElementType, outputArray);
} else if (passedArgument.IsConstructedReturnType) {
switch (passedArgument.FullyQualifiedName) {
if (passedArgument == null || passedArgument == NullReturnType.Instance) return true;
if (passedArgument.IsArrayReturnType) {
IReturnType passedArrayElementType = passedArgument.CastToArrayReturnType().ArrayElementType;
if (expectedArgument.IsArrayReturnType && expectedArgument.CastToArrayReturnType().ArrayDimensions == passedArgument.CastToArrayReturnType().ArrayDimensions) {
return InferTypeArgument(expectedArgument.CastToArrayReturnType().ArrayElementType, passedArrayElementType, outputArray);
} else if (expectedArgument.IsConstructedReturnType) {
switch (expectedArgument.FullyQualifiedName) {
case "System.Collections.Generic.IList":
case "System.Collections.Generic.ICollection":
case "System.Collections.Generic.IEnumerable":
return InferTypeArgument(expectedArrayElementType, passedArgument.CastToConstructedReturnType().TypeArguments[0], outputArray);
return InferTypeArgument(expectedArgument.CastToConstructedReturnType().TypeArguments[0], passedArrayElementType, outputArray);
}
}
// If P is an array type, and A is not an array type of the same rank,
@ -505,7 +522,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -505,7 +522,7 @@ namespace ICSharpCode.SharpDevelop.Dom
public static bool IsApplicable(IReturnType argument, IReturnType expected)
{
if (argument == null) // TODO: Use NullReturnType instead of no return type
if (argument == null || argument == NullReturnType.Instance)
return true; // "null" can be passed for any argument
if (expected.IsGenericReturnType) {
foreach (IReturnType constraint in expected.CastToGenericReturnType().TypeParameter.Constraints) {
@ -585,6 +602,23 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -585,6 +602,23 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
if (from.IsDecoratingReturnType<AnonymousMethodReturnType>() && (toIsDefault || to.IsConstructedReturnType)) {
IList<IParameter> methodParameters = from.CastToDecoratingReturnType<AnonymousMethodReturnType>().MethodParameters;
IClass toClass = to.GetUnderlyingClass();
if (toClass != null && toClass.ClassType == ClassType.Delegate) {
if (methodParameters == null) {
return true;
} else {
foreach (IMethod m in toClass.Methods) {
if (m.Name == "Invoke") {
return m.Parameters.Count == methodParameters.Count;
}
}
return true;
}
}
}
return false;
}

56
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
@ -17,6 +18,17 @@ using NR = ICSharpCode.NRefactory; @@ -17,6 +18,17 @@ using NR = ICSharpCode.NRefactory;
namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
{
/// <summary>
/// NRefactoryResolver implements the IResolver interface for the NRefactory languages (C# and VB).
/// </summary>
/// <remarks>
/// About implementing code-completion for other languages:
///
/// It possible to convert from your AST to NRefactory (to C# or VB) (or even let your parser create
/// NRefactory AST objects directly), but then code-completion might be incorrect when the rules of your language
/// differ from the C#/VB language rules.
/// If you want to correctly implement code-completion for your own language, you should implement your own resolver.
/// </remarks>
public class NRefactoryResolver : IResolver
{
ICompilationUnit cu;
@ -341,7 +353,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -341,7 +353,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
ctors.Add(m);
}
TypeVisitor typeVisitor = new TypeVisitor(this);
return CreateMemberResolveResult(typeVisitor.FindOverload(ctors, null, ie.Arguments, null));
return CreateMemberResolveResult(typeVisitor.FindOverload(ctors, null, ie.Arguments));
}
}
return null;
@ -440,7 +452,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -440,7 +452,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
typeParameters = new IReturnType[type.CastToConstructedReturnType().TypeArguments.Count];
type.CastToConstructedReturnType().TypeArguments.CopyTo(typeParameters, 0);
}
ResolveResult rr = CreateMemberResolveResult(typeVisitor.FindOverload(constructors, typeParameters, ((ObjectCreateExpression)expr).Parameters, null));
ResolveResult rr = CreateMemberResolveResult(typeVisitor.FindOverload(constructors, typeParameters, ((ObjectCreateExpression)expr).Parameters));
if (rr != null) {
rr.ResolvedType = type;
}
@ -887,20 +899,36 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -887,20 +899,36 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
methods.Add(m);
}
}
if (methods.Count == 0) {
if (languageProperties.SupportsExtensionMethods && callingClass != null) {
ArrayList list = new ArrayList();
ResolveResult.AddExtensions(languageProperties, list, callingClass, type);
foreach (IMethodOrProperty mp in list) {
if (mp is IMethod && IsSameName(mp.Name, memberName)) {
methods.Add((IMethod)mp);
}
}
}
}
return methods;
}
public IList<IMethod> SearchExtensionMethods(string name)
{
List<IMethod> results = new List<IMethod>();
foreach (IMethodOrProperty m in SearchAllExtensionMethods()) {
if (IsSameName(name, m.Name)) {
results.Add((IMethod)m);
}
}
return results;
}
ReadOnlyCollection<IMethodOrProperty> cachedExtensionMethods;
IClass cachedExtensionMethods_LastClass; // invalidate cache when callingClass != LastClass
static readonly ReadOnlyCollection<IMethodOrProperty> emptyMethodOrPropertyList = new ReadOnlyCollection<IMethodOrProperty>(new IMethodOrProperty[0]);
public ReadOnlyCollection<IMethodOrProperty> SearchAllExtensionMethods()
{
if (callingClass == null)
return emptyMethodOrPropertyList;
if (callingClass != cachedExtensionMethods_LastClass) {
cachedExtensionMethods_LastClass = callingClass;
cachedExtensionMethods = new ReadOnlyCollection<IMethodOrProperty>(CtrlSpaceResolveHelper.FindAllExtensions(languageProperties, callingClass));
}
return cachedExtensionMethods;
}
#endregion
#region SearchMember
@ -975,7 +1003,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -975,7 +1003,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return null;
}
if (v.TypeRef == null || v.TypeRef.Type == "var") {
if (v.TypeRef == null || v.TypeRef.IsNull || v.TypeRef.Type == "var") {
if (v.IsLoopVariable) {
return new ElementReturnType(this.projectContent,
new InferredReturnType(v.Initializer, this));

84
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/TypeVisitor.cs

@ -110,21 +110,64 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -110,21 +110,64 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return null;
}
public IMethod FindOverload(List<IMethod> methods, IReturnType[] typeParameters, IList<Expression> arguments, object data)
static readonly IMethod[] emptyMethodsArray = new IMethod[0];
/// <summary>
/// Find the correct overload from a list of overloads.
/// </summary>
/// <param name="methods">The list of available methods to call.</param>
/// <param name="typeParameters">The type parameters used for the method call.</param>
/// <param name="arguments">The arguments passed to the method.</param>
/// <returns>The chosen overload.</returns>
public IMethod FindOverload(IList<IMethod> methods, IReturnType[] typeParameters, IList<Expression> arguments)
{
if (methods.Count <= 0) {
return FindOverload(methods, null, null, typeParameters, arguments);
}
/// <summary>
/// Find the correct overload from a list of overloads.
/// </summary>
/// <param name="methods">The list of available methods to call.</param>
/// <param name="extensionMethods">The list of available extension methods to call.</param>
/// <param name="targetType">The type of the expression on which the method is called. Used as first argument to the extension methods.</param>
/// <param name="typeParameters">The type parameters used for the method call.</param>
/// <param name="arguments">The arguments passed to the method.</param>
/// <returns>The chosen overload.</returns>
public IMethod FindOverload(IList<IMethod> methods, IList<IMethod> extensionMethods, IReturnType targetType, IReturnType[] typeParameters, IList<Expression> arguments)
{
if (extensionMethods == null) extensionMethods = emptyMethodsArray;
if (methods.Count == 0 && extensionMethods.Count == 0) {
return null;
}
// We can't use this shortcut because MemberLookupHelper does type inference and
// type substitution for us
//if (methods.Count == 1)
// return methods[0];
// We must call FindOverload even if there is only one possible match
// because MemberLookupHelper does type inference and type substitution for us
IReturnType[] types = new IReturnType[arguments.Count];
for (int i = 0; i < types.Length; ++i) {
types[i] = arguments[i].AcceptVisitor(this, data) as IReturnType;
types[i] = arguments[i].AcceptVisitor(this, null) as IReturnType;
}
bool matchIsAcceptable;
IMethod result = MemberLookupHelper.FindOverload(methods, typeParameters, types, out matchIsAcceptable);
if (matchIsAcceptable) return result;
if (extensionMethods.Count > 0) {
IReturnType[] extendedTypes = new IReturnType[types.Length + 1];
extendedTypes[0] = targetType;
types.CopyTo(extendedTypes, 1);
IMethod extensionResult = MemberLookupHelper.FindOverload(extensionMethods, typeParameters, extendedTypes, out matchIsAcceptable);
if (matchIsAcceptable)
return extensionResult;
else
return result ?? extensionResult;
} else {
return result;
}
return MemberLookupHelper.FindOverload(methods, typeParameters, types);
}
/// <summary>
@ -136,11 +179,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -136,11 +179,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
IReturnType[] typeParameters = CreateReturnTypes(invocationExpression.TypeArguments);
if (invocationExpression.TargetObject is FieldReferenceExpression) {
FieldReferenceExpression field = (FieldReferenceExpression)invocationExpression.TargetObject;
IReturnType type = field.TargetObject.AcceptVisitor(this, null) as IReturnType;
List<IMethod> methods = resolver.SearchMethod(type, field.FieldName);
if (methods.Count == 0 && resolver.Language == SupportedLanguage.VBNet)
IReturnType targetType = field.TargetObject.AcceptVisitor(this, null) as IReturnType;
List<IMethod> methods = resolver.SearchMethod(targetType, field.FieldName);
// FindOverload does not need the extensionMethods if a normal method is applicable,
// so we use a LazyList because SearchExtensionMethods is expensive and we don't want to call it
// if it is not required.
IList<IMethod> extensionMethods = new LazyList<IMethod>(
delegate { return resolver.SearchExtensionMethods(field.FieldName); });
if (methods.Count == 0 && extensionMethods.Count == 0 && resolver.Language == SupportedLanguage.VBNet)
return GetVisualBasicIndexer(invocationExpression);
return FindOverload(methods, typeParameters, invocationExpression.Arguments, null);
return FindOverload(methods, extensionMethods, targetType, typeParameters, invocationExpression.Arguments);
} else if (invocationExpression.TargetObject is IdentifierExpression) {
string id = ((IdentifierExpression)invocationExpression.TargetObject).Identifier;
if (resolver.CallingClass == null) {
@ -149,7 +200,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -149,7 +200,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
List<IMethod> methods = resolver.SearchMethod(id);
if (methods.Count == 0 && resolver.Language == SupportedLanguage.VBNet)
return GetVisualBasicIndexer(invocationExpression);
return FindOverload(methods, typeParameters, invocationExpression.Arguments, null);
return FindOverload(methods, typeParameters, invocationExpression.Arguments);
} else {
// this could be a nested indexer access
if (resolver.Language == SupportedLanguage.VBNet)
@ -423,8 +474,11 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -423,8 +474,11 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
public override object VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data)
{
AnonymousMethodReturnType amrt = new AnonymousMethodReturnType(resolver.CompilationUnit);
foreach (ParameterDeclarationExpression param in anonymousMethodExpression.Parameters) {
amrt.MethodParameters.Add(NRefactoryASTConvertVisitor.CreateParameter(param, resolver.CallingMember as IMethod, resolver.CallingClass, resolver.CompilationUnit));
if (anonymousMethodExpression.HasParameterList) {
amrt.MethodParameters = new List<IParameter>();
foreach (ParameterDeclarationExpression param in anonymousMethodExpression.Parameters) {
amrt.MethodParameters.Add(NRefactoryASTConvertVisitor.CreateParameter(param, resolver.CallingMember as IMethod, resolver.CallingClass, resolver.CompilationUnit));
}
}
return amrt;
}

34
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs

@ -112,39 +112,13 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -112,39 +112,13 @@ namespace ICSharpCode.SharpDevelop.Dom
throw new ArgumentNullException("language");
if (res == null)
throw new ArgumentNullException("res");
if (callingClass == null)
throw new ArgumentNullException("callingClass");
if (resolvedType == null)
throw new ArgumentNullException("resolvedType");
if (callingClass == null)
throw new ArgumentNullException("callingClass");
bool supportsExtensionMethods = language.SupportsExtensionMethods;
bool supportsExtensionProperties = language.SupportsExtensionProperties;
if (supportsExtensionMethods || supportsExtensionProperties) {
ArrayList list = new ArrayList();
IMethod dummyMethod = new DefaultMethod("dummy", VoidReturnType.Instance, ModifierEnum.Static, DomRegion.Empty, DomRegion.Empty, callingClass);
CtrlSpaceResolveHelper.AddContentsFromCalling(list, callingClass, dummyMethod);
CtrlSpaceResolveHelper.AddImportedNamespaceContents(list, callingClass.CompilationUnit, callingClass);
bool searchExtensionsInClasses = language.SearchExtensionsInClasses;
foreach (object o in list) {
if (supportsExtensionMethods && o is IMethod || supportsExtensionProperties && o is IProperty) {
TryAddExtension(language, res, o as IMethodOrProperty, resolvedType);
} else if (searchExtensionsInClasses && o is IClass) {
IClass c = o as IClass;
if (c.HasExtensionMethods) {
if (supportsExtensionProperties) {
foreach (IProperty p in c.Properties) {
TryAddExtension(language, res, p, resolvedType);
}
}
if (supportsExtensionMethods) {
foreach (IMethod m in c.Methods) {
TryAddExtension(language, res, m, resolvedType);
}
}
}
}
}
foreach (IMethodOrProperty mp in CtrlSpaceResolveHelper.FindAllExtensions(language, callingClass)) {
TryAddExtension(language, res, mp, resolvedType);
}
}

Loading…
Cancel
Save