2
// TestRefactoringContext.cs
5
// Mike KrĆ¼ger <mkrueger@xamarin.com>
7
// Copyright (c) 2011 Xamarin Inc.
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
// of this software and associated documentation files (the "Software"), to deal
11
// in the Software without restriction, including without limitation the rights
12
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
// copies of the Software, and to permit persons to whom the Software is
14
// furnished to do so, subject to the following conditions:
16
// The above copyright notice and this permission notice shall be included in
17
// all copies or substantial portions of the Software.
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28
using System.Collections.Generic;
30
using ICSharpCode.NRefactory.CSharp.Refactoring;
31
using ICSharpCode.NRefactory.CSharp.Resolver;
32
using ICSharpCode.NRefactory.CSharp.TypeSystem;
33
using ICSharpCode.NRefactory.Editor;
34
using ICSharpCode.NRefactory.CSharp.FormattingTests;
35
using ICSharpCode.NRefactory.Semantics;
36
using ICSharpCode.NRefactory.TypeSystem;
37
using NUnit.Framework;
38
using System.Threading;
39
using System.Threading.Tasks;
41
namespace ICSharpCode.NRefactory.CSharp.CodeActions
43
public class TestRefactoringContext : RefactoringContext
45
public static bool UseExplict {
50
internal readonly IDocument doc;
51
readonly TextLocation location;
53
public TestRefactoringContext (IDocument document, TextLocation location, CSharpAstResolver resolver) : base(resolver, CancellationToken.None)
56
this.location = location;
57
this.UseExplicitTypes = UseExplict;
58
this.FormattingOptions = FormattingOptionsFactory.CreateMono ();
60
Services.AddService (typeof(NamingConventionService), new TestNameService ());
63
class TestNameService : NamingConventionService
65
public override IEnumerable<NamingRule> Rules {
67
return DefaultRules.GetFdgRules ();
72
public override bool Supports(Version version)
77
public override TextLocation Location {
78
get { return location; }
81
public CSharpFormattingOptions FormattingOptions { get; set; }
83
public Script StartScript ()
85
return new TestScript (this);
88
sealed class TestScript : DocumentScript
90
readonly TestRefactoringContext context;
91
public TestScript(TestRefactoringContext context) : base(context.doc, context.FormattingOptions, new TextEditorOptions ())
93
this.context = context;
96
public override Task Link (params AstNode[] nodes)
98
// check that all links are valid.
99
foreach (var node in nodes) {
100
Assert.IsNotNull (GetSegment (node));
102
return new Task (() => {});
105
public override Task InsertWithCursor(string operation, InsertPosition defaultPosition, IEnumerable<AstNode> nodes)
107
EntityDeclaration entity = context.GetNode<EntityDeclaration>();
108
if (entity is Accessor) {
109
entity = (EntityDeclaration) entity.Parent;
112
foreach (var node in nodes) {
113
InsertBefore(entity, node);
115
var tcs = new TaskCompletionSource<object> ();
116
tcs.SetResult (null);
120
public override Task InsertWithCursor (string operation, ITypeDefinition parentType, IEnumerable<AstNode> nodes)
122
var unit = context.RootNode;
123
var insertType = unit.GetNodeAt<TypeDeclaration> (parentType.Region.Begin);
125
var startOffset = GetCurrentOffset (insertType.LBraceToken.EndLocation);
126
foreach (var node in nodes.Reverse ()) {
127
var output = OutputNode (1, node, true);
128
if (parentType.Kind == TypeKind.Enum) {
129
InsertText (startOffset, output.Text +",");
131
InsertText (startOffset, output.Text);
133
output.RegisterTrackedSegments (this, startOffset);
135
var tcs = new TaskCompletionSource<object> ();
136
tcs.SetResult (null);
140
void Rename (AstNode node, string newName)
142
if (node is ObjectCreateExpression)
143
node = ((ObjectCreateExpression)node).Type;
145
if (node is InvocationExpression)
146
node = ((InvocationExpression)node).Target;
148
if (node is MemberReferenceExpression)
149
node = ((MemberReferenceExpression)node).MemberNameToken;
151
if (node is MemberType)
152
node = ((MemberType)node).MemberNameToken;
154
if (node is EntityDeclaration)
155
node = ((EntityDeclaration)node).NameToken;
157
if (node is ParameterDeclaration)
158
node = ((ParameterDeclaration)node).NameToken;
159
if (node is ConstructorDeclaration)
160
node = ((ConstructorDeclaration)node).NameToken;
161
if (node is DestructorDeclaration)
162
node = ((DestructorDeclaration)node).NameToken;
163
if (node is VariableInitializer)
164
node = ((VariableInitializer)node).NameToken;
165
Replace (node, new IdentifierExpression (newName));
168
public override void Rename (IEntity entity, string name)
170
FindReferences refFinder = new FindReferences ();
171
refFinder.FindReferencesInFile (refFinder.GetSearchScopes (entity),
172
context.UnresolvedFile,
173
context.RootNode as SyntaxTree,
174
context.Compilation, (n, r) => Rename (n, name),
175
context.CancellationToken);
178
public override void Rename (IVariable variable, string name)
180
FindReferences refFinder = new FindReferences ();
181
refFinder.FindLocalReferences (variable,
182
context.UnresolvedFile,
183
context.RootNode as SyntaxTree,
184
context.Compilation, (n, r) => Rename (n, name),
185
context.CancellationToken);
188
public override void RenameTypeParameter (IType type, string name = null)
190
FindReferences refFinder = new FindReferences ();
191
refFinder.FindTypeParameterReferences (type,
192
context.UnresolvedFile,
193
context.RootNode as SyntaxTree,
194
context.Compilation, (n, r) => Rename (n, name),
195
context.CancellationToken);
198
public override void CreateNewType (AstNode newType, NewTypeContext context)
200
var output = OutputNode (0, newType, true);
201
InsertText (0, output.Text);
207
public override bool IsSomethingSelected { get { return selectionStart > 0; } }
209
public override string SelectedText { get { return IsSomethingSelected ? doc.GetText (selectionStart, selectionEnd - selectionStart) : ""; } }
212
public override TextLocation SelectionStart { get { return doc.GetLocation (selectionStart); } }
215
public override TextLocation SelectionEnd { get { return doc.GetLocation (selectionEnd); } }
217
public override int GetOffset (TextLocation location)
219
return doc.GetOffset (location);
222
public override TextLocation GetLocation (int offset)
224
return doc.GetLocation (offset);
227
public override string GetText (int offset, int length)
229
return doc.GetText (offset, length);
232
public override string GetText (ISegment segment)
234
return doc.GetText (segment);
237
public override IDocumentLine GetLineByOffset (int offset)
239
return doc.GetLineByOffset (offset);
247
public static TestRefactoringContext Create (string content, bool expectErrors = false)
249
int idx = content.IndexOf ("$");
251
content = content.Substring (0, idx) + content.Substring (idx + 1);
252
int idx1 = content.IndexOf ("<-");
253
int idx2 = content.IndexOf ("->");
255
int selectionStart = 0;
256
int selectionEnd = 0;
257
if (0 <= idx1 && idx1 < idx2) {
258
content = content.Substring (0, idx2) + content.Substring (idx2 + 2);
259
content = content.Substring (0, idx1) + content.Substring (idx1 + 2);
260
selectionStart = idx1;
261
selectionEnd = idx2 - 2;
265
var doc = new StringBuilderDocument(content);
266
var parser = new CSharpParser();
267
var unit = parser.Parse(content, "program.cs");
269
if (parser.HasErrors) {
270
Console.WriteLine (content);
271
Console.WriteLine ("----");
273
foreach (var error in parser.Errors) {
274
Console.WriteLine(error.Message);
276
Assert.IsFalse(parser.HasErrors, "The file contains unexpected parsing errors.");
278
Assert.IsTrue(parser.HasErrors, "Expected parsing errors, but the file doesn't contain any.");
282
var unresolvedFile = unit.ToTypeSystem ();
284
IProjectContent pc = new CSharpProjectContent ();
285
pc = pc.AddOrUpdateFiles (unresolvedFile);
286
pc = pc.AddAssemblyReferences (new[] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore });
288
var compilation = pc.CreateCompilation ();
289
var resolver = new CSharpAstResolver (compilation, unit, unresolvedFile);
290
TextLocation location = TextLocation.Empty;
292
location = doc.GetLocation (idx);
293
return new TestRefactoringContext(doc, location, resolver) {
294
selectionStart = selectionStart,
295
selectionEnd = selectionEnd
299
internal static void Print (AstNode node)
301
var v = new CSharpOutputVisitor (Console.Out, FormattingOptionsFactory.CreateMono ());
302
node.AcceptVisitor (v);