mirror of https://github.com/icsharpcode/ILSpy.git
Browse Source
36c9cae Add ICompilation.Import() extension methods. 1467ce3 Fixed accessibility check for protected members in outer classes. f410a2b Enum members are implicitly cast to the underlying type when used in an enum member initializer. a9c743c Fixed type inference for "condition ? someEnum : 0" 42ce4ca Fixed type inference in foreach when the collection type does not implement IEnumerable. 45bcad4 Added getsubtype definitions helper method. 78ac5bb Fixed some code completion unit tests. ff2a11b Worked on unit tests. 51986c4 Worked on code completion unit tests. c453405 Updated code completion to the latest type system changes. a564ebb Added easy to access enumerables for various member types. a71670f Fixed some issues with code round-tripping; and added unit tests for some parser failures. 4db74d9 Fixed roundtripping of preprocessor directives. bf88746 Added some failing parser tests for bugs discovered trying to roundtrip NRefactory itself. a6433d4 Do not try to infer a type from the null literal. b0b9942 Add ISolutionSnapshot for creating compilations for multiple projects from a single consistent snapshot. 7e95cb7 Add CSharpAstResolver.GetResolverStateBefore 4ccc313 Normalize newlines 9ffbdb8 Merge type system refactoring into NRefactory master. 4d4f1f4 Fixed various resolver bugs. c4ce934 Fixed bug when resolving base constructor calls. 0b263b0 TypeSystemConvertVisitor: implemented ConvertInterfaceImplementation for methods and properties. Implemented 'goto case' support in control flow analysis. f11eed9 Introduce a named unknown type (this allows TypeSystemAstBuilder to work better when there are resolve errors). e2cb546 Adjust CodeDomConvertVisitor and DefiniteAssignmentAnalysis to new type system. 3d9b3ec Improved enum parsing. e69e9f1 Fixed enum context. bf3a1d7 Added gtk text editor lib. 9cc151d Started support for unclosed expression statements. bcde6f1 Worked on enum context. 37798b0 Improved get/set keyword handling. 2ec341e Merged with mcs. 7e53805 Updated mcs/fixed some code completion cases. 73438b7 Make CSharpResolveVisitor internal and expose CSharpAstResolver instead. 9d7c018 Adjusted C# resolver to refactored type system. c02e801 Introduce ResolvedUsingScope (serves as cache per using-scope; avoids resolving imported namespaces repeatedly). 5069b98 Fixed code completion bug. 3b6fda2 Added gtk demo & fixed code completion bug. 54851a7 C# Type System implementation 057c0be Fixed "partial" bug. ba88599 Added a method to determine the current parameter index. a701436 Changed parameter completion API slightly. 4a41972 Fixed code completion bug "Bug 1932 - [new resolver] fields don't show up unless prefixed with 'this.'". 2ea298c Fixed some null reference exceptions. f479cb0 fixed bug in parameter parsing. 98d1826 Added error expression as ast node. fa6ea12 Added error expression for the for construct. 817a2da Added error expression for invalid initializers. 4376927 Renamed file. a4259ef * cs-tokenizer.cs: Fixed location bug. ec82082 Handled pre processor directives as separate AST node. 11a9ce2 Added context action unit tests. f9916d8 WIP: Type system refactoring. 2d70017 Fixed some parameter resolve result issues. 1bc609f Added pre processor "if"/"elif" contexts. 03ee478 Improved current member recognition. c29b4ed Added missing follow up char. 0ab566c Fixed "partial" context. a097af0 Fixed multiple line comment content. 8124eaa Fixed invalid expression statement. a348bbd Merge branch 'master' of github.com:icsharpcode/NRefactory 41607d7 Added invalid expression statements to the ast. d461987 Improved comment & string context recognition. f631199 Type system refactoring: split unresolved/resolved type systems. 1ebf835 Fixed parameter completion issue. af6ba7d Fixed unit test. bf3fdb3 Added variable statement declaration tests. 4824080 Implemented indexer parameter data provider. 8c82864 Fixed field declaration context & "new" expression context. 86b3da2 Added object initializer tests & fixed them. fb374aa Fixed unit test. f1612d5 Added some more keyword tests & fixed some cases. f5730d5 * CSharpCompletionEngine.cs: Fixed some bugs in global/type context. 85e1173 Fixed parser bug. 59ce505 Fixed last failing code completion unit test. bc4ca21 * NRefactory.sln: cfcaca8 Merged mcs. b74cfbb Added switch context handling. fa5e7e5 Fixed potential resolve issue. Note: That doesn't really fix the problem - only 90% of the cases. The partial class representation could need a change. c498bc8 Fixed completion inside try ... catch bodies. 03407fd Fixed failing unit test. 2a795ae Fixed some unit tests. 8942cd5 Fixed failing unit test. 2cfd9b2 Added attribute context. 7a8e9d0 Merged with mcs master. 18e088e SpecializedMethod: Perform type substitution in the type parameter constraints. 69360a2 Implemented constraint inheritance. 57d55c6 Fixed resolving simple names within a generic class that refer to a non-generic inner class. 5d614c0 Fixed unit test. 98ad3ba Fixed unit test. ffa2fc9 Fixed failing unit test. 42c0a2d Fixed unit test. 6d4a825 Fixed some unit tests. a81096d Included interfaces in type parameter base types. 2bc6105 Fixed some completion unit tests. I'm not 100% sure if that's the best solution fixing this, but makes things easier for now. fd91bdc Fixed resolving non-generic classes that are nested within generic classes. f043e30 Fix ResolveVisitor.GetResolverStateBefore(): ensure that the resolver always registers the state before it caches a result. ed86963 Failed assertions now fail unit tests. 81cac5e Fixed little code completion ast bug. f3ea71a Fixed some completion tests. 7f697b3 Fixed resolver usage. e96dbbd Added 'UnknownTypeResolveResult'. Makes it easier to implement the 'add missing namespace import' function. 0320a66 Added monodevelop code completion tests. 5ee9b73 Added missing unit test. 1c0ce1d Added default parameters for type parameter count. f7b3094 Merged with md master. 7063203 FieldDeclaration/EventDeclaration/VariableDeclarationStatement now resolve to 'void'. Only the individual VariableInitializers will resolve to the field/event/variable. 800b951 Fixed bugs in ResolveVisitor: - forgot scanning into ForEachStatement.InExpression when the variable type was not 'var' - ProcessConversion() was called for Expression.Null - made Resolve() internal because it hard to use correctly b3d07d8 Ported over the monodevelop completion engine to nrefactory. f46609b Worked on basic nrefactory completion infrastructure. 8389d7a Use OperatorResolveResult for assignments. 9ddf9bc Combine C#-specific UnaryOperatorResolveResult/BinaryOperatorResolveResult and ConditionalOperatorResolveResult classes into a single language-independent OperatorResolveResult class. 4bbcf2d Add "public ResolveResult Body { get; }" to LambdaResolveResult. 751b601 Shorten inner type names. 434ec17 Correctly set kind of compound types. 177fb85 Fix infinite recursion when resolving the base type of "class Test : Test.Base { public class Base {} }" 475f838 Make DefaultTypeDefinition.FullName cache thread-safe. 8c3899f Cached TypeDefiniton FullName. This is required for the navigate to feature which checks the full name as well as the name. Otherwise it would cause thousands of slow string concats. Since the type system should be treaded as read only namespaces & declaring type definitions can't change. 7b542f4 Enabled async tests. e4c70d4 Added await/async support & updated mcs. d91eb2c Print error information. b7fcc55 Re-enable resolver unit tests that failed due to the parser returning incorrect positions. 25176ef Fixed IMember.IsOverridable to return true for abstract members. e4850e9 Added async modifier. 0c3d5e0 Fix bug in ParameterListComparer: the method signatures "Method<T>(T a)" and "Method<S>(S b)" were considered unequal. 4d73e48 Add GetEffectiveBaseClass() and GetEffectiveInterfaceSet() to ITypeParameter, and fixed a bug in DefaultTypeParameter.IsReferenceType(). 0c03236 Update AssemblyInfo for ICSharpCode.NRefactory.CSharp 813c8f5 Merge NRefactory 'b059dbcf413786069599d1686ac608150bd3f357' into SharpDevelop repository. b059dbc Fixed NullReferenceException when resolving group join clause. ad1e90b Merge pull request #205 - Decompilation of lifted operators f0bfded C# AST: when setting a string property to null or an empty string, remove the corresponding identifier token. 9f988f6 Adjust ILSpy to NRefactory changes. 6994e19 Merge NRefactory '88ebd0b9596edab0e916ff28ae53f6febbdff032' to ILSpy. 5a2b4d2 fix out parameter output in CSharpToVBConverterVisitor f085e9c fix AlwaysUseShortTypeNames omitting generic type arguments 02f1929 implement find references on local variables 8a598a7 fix CSharpBinding reference to NRefactory.CSharp; fix long type names bug in CSharpAmbience 02b1e15 Fix unit tests after moving CSharpAmbienceTests to different namespace. e6d84ff moved Ambience to NRefactory 49c5c79 implement all different members in CSharpAmbience output 5beb702 implement CSharpAmbience for ITypeDefinition 9526969 Adjust SharpDevelop to NRefactory changes (move ICSharpCode.Editor -> ICSharpCode.NRefactory.Editor; put NR.C# in separate assembly) 2f4f82c Merge changes from NRefactory into SharpDevelop newNR branch. 10a6608 Merge branch 'master' of git://github.com/icsharpcode/ILSpy 472daa9 remove old files 588557e fix case sensitivity in IsKeyword check 3e37fb2 fix output of object initializers 7a9bb56 InsertParenthesesVisitor: insert parenthesis in "(new int[1])[0]" ddc5d8a Merge branch 'master' of git://github.com/icsharpcode/ILSpy 1398d8a add missing space after Case keyword a854421 corrected spelling of Overrides-modifier; convert virtual to Overridable and override to Overrides 5c10903 Merge branch 'master' of git://github.com/icsharpcode/ILSpy ee384a2 PDB files for release mode. File alignments and base addresses improved. git-subtree-dir: NRefactory git-subtree-split: 36c9caec101ad5b2c47d11ac12bcd043d8d6e115pull/297/head
363 changed files with 35459 additions and 19974 deletions
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// ErrorExpression.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp |
||||
{ |
||||
public class ErrorExpression : EmptyExpression |
||||
{ |
||||
public ErrorExpression () |
||||
{ |
||||
} |
||||
|
||||
public ErrorExpression (TextLocation location) : base (location) |
||||
{ |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
@ -0,0 +1,117 @@
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// PreProcessorDirective.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp |
||||
{ |
||||
public enum PreProcessorDirectiveType : byte |
||||
{ |
||||
Invalid = 0, |
||||
Region = 1, |
||||
Endregion = 2, |
||||
|
||||
If = 3, |
||||
Endif = 4, |
||||
Elif = 5, |
||||
Else = 6, |
||||
|
||||
Define = 7, |
||||
Undef = 8, |
||||
Error = 9, |
||||
Warning = 10, |
||||
Pragma = 11, |
||||
Line = 12 |
||||
} |
||||
|
||||
public class PreProcessorDirective : AstNode, IRelocatable |
||||
{ |
||||
public override NodeType NodeType { |
||||
get { |
||||
return NodeType.Whitespace; |
||||
} |
||||
} |
||||
|
||||
public PreProcessorDirectiveType Type { |
||||
get; |
||||
set; |
||||
} |
||||
|
||||
public string Argument { |
||||
get; |
||||
set; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// For an '#if' directive, specifies whether the condition evaluated to true.
|
||||
/// </summary>
|
||||
public bool Take { |
||||
get; |
||||
set; |
||||
} |
||||
|
||||
TextLocation startLocation; |
||||
public override TextLocation StartLocation { |
||||
get { |
||||
return startLocation; |
||||
} |
||||
} |
||||
|
||||
TextLocation endLocation; |
||||
public override TextLocation EndLocation { |
||||
get { |
||||
return endLocation; |
||||
} |
||||
} |
||||
|
||||
public PreProcessorDirective (PreProcessorDirectiveType type, TextLocation startLocation, TextLocation endLocation) |
||||
{ |
||||
this.Type = type; |
||||
this.startLocation = startLocation; |
||||
this.endLocation = endLocation; |
||||
} |
||||
|
||||
#region IRelocationable implementation
|
||||
void IRelocatable.SetStartLocation (TextLocation startLocation) |
||||
{ |
||||
int lineDelta = startLocation.Line - this.startLocation.Line; |
||||
endLocation = new TextLocation (endLocation.Line + lineDelta, lineDelta != 0 ? endLocation.Column : endLocation.Column + startLocation.Column - this.startLocation.Column); |
||||
this.startLocation = startLocation; |
||||
} |
||||
#endregion
|
||||
|
||||
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data = default(T)) |
||||
{ |
||||
return visitor.VisitPreProcessorDirective (this, data); |
||||
} |
||||
|
||||
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) |
||||
{ |
||||
PreProcessorDirective o = other as PreProcessorDirective; |
||||
return o != null && Type == o.Type && MatchString(Argument, o.Argument); |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,159 @@
@@ -0,0 +1,159 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Runtime.Serialization; |
||||
using ICSharpCode.NRefactory.CSharp.TypeSystem; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
||||
using ICSharpCode.NRefactory.Utils; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp |
||||
{ |
||||
[Serializable] |
||||
public class CSharpProjectContent : IProjectContent |
||||
{ |
||||
string assemblyName; |
||||
Dictionary<string, IParsedFile> parsedFiles; |
||||
List<IAssemblyReference> assemblyReferences; |
||||
|
||||
public CSharpProjectContent() |
||||
{ |
||||
this.assemblyName = string.Empty; |
||||
this.parsedFiles = new Dictionary<string, IParsedFile>(Platform.FileNameComparer); |
||||
this.assemblyReferences = new List<IAssemblyReference>(); |
||||
} |
||||
|
||||
protected CSharpProjectContent(CSharpProjectContent pc) |
||||
{ |
||||
this.assemblyName = pc.assemblyName; |
||||
this.parsedFiles = new Dictionary<string, IParsedFile>(pc.parsedFiles); |
||||
this.assemblyReferences = new List<IAssemblyReference>(pc.assemblyReferences); |
||||
} |
||||
|
||||
public IEnumerable<IParsedFile> Files { |
||||
get { return parsedFiles.Values; } |
||||
} |
||||
|
||||
public IEnumerable<IAssemblyReference> AssemblyReferences { |
||||
get { return assemblyReferences; } |
||||
} |
||||
|
||||
public string AssemblyName { |
||||
get { return assemblyName; } |
||||
} |
||||
|
||||
public IEnumerable<IUnresolvedAttribute> AssemblyAttributes { |
||||
get { |
||||
return this.Files.SelectMany(f => f.AssemblyAttributes); |
||||
} |
||||
} |
||||
|
||||
public IEnumerable<IUnresolvedAttribute> ModuleAttributes { |
||||
get { |
||||
return this.Files.SelectMany(f => f.ModuleAttributes); |
||||
} |
||||
} |
||||
|
||||
public IEnumerable<IUnresolvedTypeDefinition> TopLevelTypeDefinitions { |
||||
get { |
||||
return this.Files.SelectMany(f => f.TopLevelTypeDefinitions); |
||||
} |
||||
} |
||||
|
||||
public IParsedFile GetFile(string fileName) |
||||
{ |
||||
IParsedFile file; |
||||
if (parsedFiles.TryGetValue(fileName, out file)) |
||||
return file; |
||||
else |
||||
return null; |
||||
} |
||||
|
||||
public ICompilation CreateCompilation() |
||||
{ |
||||
var solutionSnapshot = new DefaultSolutionSnapshot(); |
||||
ICompilation compilation = new SimpleCompilation(solutionSnapshot, this, assemblyReferences); |
||||
solutionSnapshot.AddCompilation(this, compilation); |
||||
return compilation; |
||||
} |
||||
|
||||
public ICompilation CreateCompilation(ISolutionSnapshot solutionSnapshot) |
||||
{ |
||||
return new SimpleCompilation(solutionSnapshot, this, assemblyReferences); |
||||
} |
||||
|
||||
public IProjectContent SetAssemblyName(string newAssemblyName) |
||||
{ |
||||
CSharpProjectContent pc = new CSharpProjectContent(this); |
||||
pc.assemblyName = newAssemblyName; |
||||
return pc; |
||||
} |
||||
|
||||
public IProjectContent AddAssemblyReferences(IEnumerable<IAssemblyReference> references) |
||||
{ |
||||
CSharpProjectContent pc = new CSharpProjectContent(this); |
||||
pc.assemblyReferences.AddRange(references); |
||||
return pc; |
||||
} |
||||
|
||||
public IProjectContent RemoveAssemblyReferences(IEnumerable<IAssemblyReference> references) |
||||
{ |
||||
CSharpProjectContent pc = new CSharpProjectContent(this); |
||||
pc.assemblyReferences.RemoveAll(r => references.Contains(r)); |
||||
return pc; |
||||
} |
||||
|
||||
public IProjectContent UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile) |
||||
{ |
||||
if (oldFile == null && newFile == null) |
||||
return this; |
||||
if (oldFile != null && newFile != null) { |
||||
if (!Platform.FileNameComparer.Equals(oldFile.FileName, newFile.FileName)) |
||||
throw new ArgumentException("When both oldFile and newFile are specified, they must use the same file name."); |
||||
} |
||||
CSharpProjectContent pc = new CSharpProjectContent(this); |
||||
if (newFile == null) |
||||
pc.parsedFiles.Remove(oldFile.FileName); |
||||
else |
||||
pc.parsedFiles[newFile.FileName] = newFile; |
||||
return pc; |
||||
} |
||||
|
||||
public IProjectContent UpdateProjectContent(IEnumerable<IParsedFile> oldFiles, IEnumerable<IParsedFile> newFiles) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
IAssembly IAssemblyReference.Resolve(ITypeResolveContext context) |
||||
{ |
||||
if (context == null) |
||||
throw new ArgumentNullException("context"); |
||||
var cache = context.Compilation.CacheManager; |
||||
IAssembly asm = (IAssembly)cache.GetShared(this); |
||||
if (asm != null) { |
||||
return asm; |
||||
} else { |
||||
asm = new CSharpAssembly(context.Compilation, this); |
||||
return (IAssembly)cache.GetOrAddShared(this, asm); |
||||
} |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,495 @@
@@ -0,0 +1,495 @@
|
||||
//
|
||||
// CSharpCompletionEngineBase.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Text; |
||||
|
||||
using ICSharpCode.NRefactory.CSharp.Resolver; |
||||
using ICSharpCode.NRefactory.Editor; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.Semantics; |
||||
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
||||
using ICSharpCode.NRefactory.CSharp.TypeSystem; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Completion |
||||
{ |
||||
/// <summary>
|
||||
/// Acts as a common base between code completion and parameter completion.
|
||||
/// </summary>
|
||||
public class CSharpCompletionEngineBase |
||||
{ |
||||
protected IDocument document; |
||||
protected int offset; |
||||
protected TextLocation location; |
||||
protected IUnresolvedTypeDefinition currentType; |
||||
protected IUnresolvedMember currentMember; |
||||
|
||||
#region Input properties
|
||||
public CSharpTypeResolveContext ctx { get; set; } |
||||
|
||||
public CompilationUnit Unit { get; set; } |
||||
|
||||
public CSharpParsedFile CSharpParsedFile { get; set; } |
||||
|
||||
public IProjectContent ProjectContent { get; set; } |
||||
|
||||
ICompilation compilation; |
||||
protected ICompilation Compilation { |
||||
get { |
||||
if (compilation == null) |
||||
compilation = ProjectContent.Resolve (ctx).Compilation; |
||||
return compilation; |
||||
} |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
protected void SetOffset (int offset) |
||||
{ |
||||
Reset (); |
||||
|
||||
this.offset = offset; |
||||
this.location = document.GetLocation (offset); |
||||
|
||||
this.currentType = CSharpParsedFile.GetInnermostTypeDefinition (location); |
||||
this.currentMember = null; |
||||
if (this.currentType != null) { |
||||
foreach (var member in currentType.Members) { |
||||
if (member.Region.Begin < location && (currentMember == null || currentMember.Region.Begin < member.Region.Begin)) |
||||
currentMember = member; |
||||
} |
||||
} |
||||
var stack = GetBracketStack (GetMemberTextToCaret ().Item1); |
||||
if (stack.Count == 0) |
||||
currentMember = null; |
||||
} |
||||
|
||||
#region Context helper methods
|
||||
protected bool IsInsideCommentOrString () |
||||
{ |
||||
var text = GetMemberTextToCaret (); |
||||
bool inSingleComment = false, inString = false, inVerbatimString = false, inChar = false, inMultiLineComment = false; |
||||
|
||||
for (int i = 0; i < text.Item1.Length - 1; i++) { |
||||
char ch = text.Item1 [i]; |
||||
char nextCh = text.Item1 [i + 1]; |
||||
|
||||
switch (ch) { |
||||
case '/': |
||||
if (inString || inChar || inVerbatimString) |
||||
break; |
||||
if (nextCh == '/') { |
||||
i++; |
||||
inSingleComment = true; |
||||
} |
||||
if (nextCh == '*') |
||||
inMultiLineComment = true; |
||||
break; |
||||
case '*': |
||||
if (inString || inChar || inVerbatimString || inSingleComment) |
||||
break; |
||||
if (nextCh == '/') { |
||||
i++; |
||||
inMultiLineComment = false; |
||||
} |
||||
break; |
||||
case '@': |
||||
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) |
||||
break; |
||||
if (nextCh == '"') { |
||||
i++; |
||||
inVerbatimString = true; |
||||
} |
||||
break; |
||||
case '\n': |
||||
case '\r': |
||||
inSingleComment = false; |
||||
inString = false; |
||||
inChar = false; |
||||
break; |
||||
case '\\': |
||||
if (inString || inChar) |
||||
i++; |
||||
break; |
||||
case '"': |
||||
if (inSingleComment || inMultiLineComment || inChar) |
||||
break; |
||||
if (inVerbatimString) { |
||||
if (nextCh == '"') { |
||||
i++; |
||||
break; |
||||
} |
||||
inVerbatimString = false; |
||||
break; |
||||
} |
||||
inString = !inString; |
||||
break; |
||||
case '\'': |
||||
if (inSingleComment || inMultiLineComment || inString || inVerbatimString) |
||||
break; |
||||
inChar = !inChar; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return inSingleComment || inString || inVerbatimString || inChar || inMultiLineComment; |
||||
} |
||||
|
||||
protected bool IsInsideComment (int offset) |
||||
{ |
||||
var loc = document.GetLocation (offset); |
||||
return Unit.GetNodeAt<ICSharpCode.NRefactory.CSharp.Comment> (loc.Line, loc.Column) != null; |
||||
} |
||||
|
||||
protected bool IsInsideDocComment () |
||||
{ |
||||
var loc = document.GetLocation (offset); |
||||
var cmt = Unit.GetNodeAt<ICSharpCode.NRefactory.CSharp.Comment> (loc.Line, loc.Column - 1); |
||||
return cmt != null && cmt.CommentType == CommentType.Documentation; |
||||
} |
||||
|
||||
protected bool IsInsideString (int offset) |
||||
{ |
||||
|
||||
var loc = document.GetLocation (offset); |
||||
var expr = Unit.GetNodeAt<PrimitiveExpression> (loc.Line, loc.Column); |
||||
return expr != null && expr.Value is string; |
||||
} |
||||
#endregion
|
||||
|
||||
#region Basic parsing/resolving functions
|
||||
Stack<Tuple<char, int>> GetBracketStack (string memberText) |
||||
{ |
||||
var bracketStack = new Stack<Tuple<char, int>> (); |
||||
|
||||
bool isInString = false, isInChar = false; |
||||
bool isInLineComment = false, isInBlockComment = false; |
||||
|
||||
for (int pos = 0; pos < memberText.Length; pos++) { |
||||
char ch = memberText [pos]; |
||||
switch (ch) { |
||||
case '(': |
||||
case '[': |
||||
case '{': |
||||
if (!isInString && !isInChar && !isInLineComment && !isInBlockComment) |
||||
bracketStack.Push (Tuple.Create (ch, pos)); |
||||
break; |
||||
case ')': |
||||
case ']': |
||||
case '}': |
||||
if (!isInString && !isInChar && !isInLineComment && !isInBlockComment) |
||||
if (bracketStack.Count > 0) |
||||
bracketStack.Pop (); |
||||
break; |
||||
case '\r': |
||||
case '\n': |
||||
isInLineComment = false; |
||||
break; |
||||
case '/': |
||||
if (isInBlockComment) { |
||||
if (pos > 0 && memberText [pos - 1] == '*') |
||||
isInBlockComment = false; |
||||
} else if (!isInString && !isInChar && pos + 1 < memberText.Length) { |
||||
char nextChar = memberText [pos + 1]; |
||||
if (nextChar == '/') |
||||
isInLineComment = true; |
||||
if (!isInLineComment && nextChar == '*') |
||||
isInBlockComment = true; |
||||
} |
||||
break; |
||||
case '"': |
||||
if (!(isInChar || isInLineComment || isInBlockComment)) |
||||
isInString = !isInString; |
||||
break; |
||||
case '\'': |
||||
if (!(isInString || isInLineComment || isInBlockComment)) |
||||
isInChar = !isInChar; |
||||
break; |
||||
default : |
||||
break; |
||||
} |
||||
} |
||||
return bracketStack; |
||||
} |
||||
|
||||
protected void AppendMissingClosingBrackets (StringBuilder wrapper, string memberText, bool appendSemicolon) |
||||
{ |
||||
var bracketStack = GetBracketStack (memberText); |
||||
bool didAppendSemicolon = !appendSemicolon; |
||||
char lastBracket = '\0'; |
||||
while (bracketStack.Count > 0) { |
||||
var t = bracketStack.Pop (); |
||||
switch (t.Item1) { |
||||
case '(': |
||||
wrapper.Append (')'); |
||||
didAppendSemicolon = false; |
||||
lastBracket = ')'; |
||||
break; |
||||
case '[': |
||||
wrapper.Append (']'); |
||||
didAppendSemicolon = false; |
||||
lastBracket = ']'; |
||||
break; |
||||
case '<': |
||||
wrapper.Append ('>'); |
||||
didAppendSemicolon = false; |
||||
lastBracket = '>'; |
||||
break; |
||||
case '{': |
||||
int o = t.Item2 - 1; |
||||
if (!didAppendSemicolon) { |
||||
didAppendSemicolon = true; |
||||
wrapper.Append (';'); |
||||
} |
||||
|
||||
bool didAppendCatch = false; |
||||
while (o >= "try".Length) { |
||||
char ch = memberText [o]; |
||||
if (!char.IsWhiteSpace (ch)) { |
||||
if (ch == 'y' && memberText [o - 1] == 'r' && memberText [o - 2] == 't') { |
||||
wrapper.Append ("} catch {}"); |
||||
didAppendCatch = true; |
||||
} |
||||
break; |
||||
} |
||||
o--; |
||||
} |
||||
if (!didAppendCatch) |
||||
wrapper.Append ('}'); |
||||
break; |
||||
} |
||||
} |
||||
if (currentMember == null && lastBracket == ']') { |
||||
// attribute context
|
||||
wrapper.Append ("class GenAttr {}"); |
||||
} else { |
||||
if (!didAppendSemicolon) |
||||
wrapper.Append (';'); |
||||
} |
||||
} |
||||
|
||||
protected CompilationUnit ParseStub (string continuation, bool appendSemicolon = true) |
||||
{ |
||||
var mt = GetMemberTextToCaret (); |
||||
if (mt == null) |
||||
return null; |
||||
|
||||
string memberText = mt.Item1; |
||||
bool wrapInClass = mt.Item2; |
||||
|
||||
var wrapper = new StringBuilder (); |
||||
|
||||
if (wrapInClass) { |
||||
/* foreach (var child in Unit.Children) { |
||||
if (child is UsingDeclaration) { |
||||
var offset = document.GetOffset (child.StartLocation); |
||||
wrapper.Append (document.GetText (offset, document.GetOffset (child.EndLocation) - offset)); |
||||
} |
||||
}*/ |
||||
wrapper.Append ("class Stub {"); |
||||
wrapper.AppendLine (); |
||||
} |
||||
|
||||
wrapper.Append (memberText); |
||||
wrapper.Append (continuation); |
||||
AppendMissingClosingBrackets (wrapper, memberText, appendSemicolon); |
||||
|
||||
if (wrapInClass) |
||||
wrapper.Append ('}'); |
||||
|
||||
TextLocation memberLocation; |
||||
if (currentMember != null && currentType.Kind != TypeKind.Enum) { |
||||
memberLocation = currentMember.Region.Begin; |
||||
} else if (currentType != null) { |
||||
memberLocation = currentType.Region.Begin; |
||||
} else { |
||||
memberLocation = new TextLocation (1, 1); |
||||
} |
||||
using (var stream = new System.IO.StringReader (wrapper.ToString ())) { |
||||
try { |
||||
var parser = new CSharpParser (); |
||||
return parser.Parse (stream, "stub.cs" , wrapInClass ? memberLocation.Line - 2 : 0); |
||||
} catch (Exception){ |
||||
Console.WriteLine ("------"); |
||||
Console.WriteLine (wrapper); |
||||
throw; |
||||
} |
||||
} |
||||
} |
||||
|
||||
string cachedText = null; |
||||
|
||||
protected virtual void Reset () |
||||
{ |
||||
cachedText = null; |
||||
} |
||||
|
||||
protected Tuple<string, bool> GetMemberTextToCaret () |
||||
{ |
||||
int startOffset; |
||||
if (currentMember != null && currentType.Kind != TypeKind.Enum) { |
||||
startOffset = document.GetOffset (currentMember.Region.BeginLine, currentMember.Region.BeginColumn); |
||||
} else if (currentType != null) { |
||||
startOffset = document.GetOffset (currentType.Region.BeginLine, currentType.Region.BeginColumn); |
||||
} else { |
||||
startOffset = 0; |
||||
} |
||||
while (startOffset > 0) { |
||||
char ch = document.GetCharAt (startOffset - 1); |
||||
if (ch != ' ' && ch != '\t') |
||||
break; |
||||
--startOffset; |
||||
} |
||||
if (cachedText == null) |
||||
cachedText = document.GetText (startOffset, offset - startOffset); |
||||
|
||||
return Tuple.Create (cachedText, startOffset != 0); |
||||
} |
||||
|
||||
protected Tuple<CSharpParsedFile, AstNode, CompilationUnit> GetInvocationBeforeCursor (bool afterBracket) |
||||
{ |
||||
CompilationUnit baseUnit; |
||||
if (currentMember == null) { |
||||
baseUnit = ParseStub ("", false); |
||||
var section = baseUnit.GetNodeAt<AttributeSection> (location.Line, location.Column - 2); |
||||
var attr = section != null ? section.Attributes.LastOrDefault () : null; |
||||
if (attr != null) { |
||||
// insert target type into compilation unit, to respect the
|
||||
attr.Remove (); |
||||
var node = Unit.GetNodeAt (location) ?? Unit; |
||||
node.AddChild (attr, AttributeSection.AttributeRole); |
||||
return Tuple.Create (CSharpParsedFile, (AstNode)attr, Unit); |
||||
} |
||||
} |
||||
|
||||
if (currentMember == null && currentType == null) { |
||||
return null; |
||||
} |
||||
baseUnit = ParseStub (afterBracket ? "" : "x"); |
||||
|
||||
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin; |
||||
var mref = baseUnit.GetNodeAt (location.Line, location.Column - 1, n => n is InvocationExpression || n is ObjectCreateExpression); |
||||
AstNode expr; |
||||
if (mref is InvocationExpression) { |
||||
expr = ((InvocationExpression)mref).Target; |
||||
} else if (mref is ObjectCreateExpression) { |
||||
expr = mref; |
||||
} else { |
||||
return null; |
||||
} |
||||
// Print (baseUnit);
|
||||
/* var member = Unit.GetNodeAt<AttributedNode> (memberLocation); |
||||
var member2 = baseUnit.GetNodeAt<AttributedNode> (memberLocation); |
||||
member2.Remove (); |
||||
member.ReplaceWith (member2); |
||||
var tsvisitor = new TypeSystemConvertVisitor (ProjectContent, CSharpParsedFile.FileName); |
||||
baseUnit.AcceptVisitor (tsvisitor, null);*/ |
||||
return Tuple.Create (CSharpParsedFile, (AstNode)expr, baseUnit); |
||||
|
||||
/* |
||||
|
||||
///////
|
||||
if (currentMember == null && currentType == null) |
||||
return null; |
||||
|
||||
CSharpParser parser = new CSharpParser (); |
||||
int startOffset; |
||||
if (currentMember != null) { |
||||
startOffset = document.Editor.LocationToOffset (currentMember.Region.BeginLine, currentMember.Region.BeginColumn); |
||||
} else { |
||||
startOffset = document.Editor.LocationToOffset (currentType.Region.BeginLine, currentType.Region.BeginColumn); |
||||
} |
||||
string memberText = Document.Editor.GetTextBetween (startOffset, Document.Editor.Caret.Offset - 1); |
||||
|
||||
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin; |
||||
StringBuilder wrapper = new StringBuilder (); |
||||
wrapper.Append ("class Stub {"); |
||||
wrapper.AppendLine (); |
||||
wrapper.Append (memberText); |
||||
|
||||
if (afterBracket) { |
||||
wrapper.Append ("();"); |
||||
} else { |
||||
wrapper.Append ("x);"); |
||||
} |
||||
|
||||
wrapper.Append (" SomeCall (); } } }"); |
||||
var stream = new System.IO.StringReader (wrapper.ToString ()); |
||||
var baseUnit = parser.Parse (stream, memberLocation.Line - 2); |
||||
stream.Close (); |
||||
var expr = baseUnit.GetNodeAt<Expression> (document.Editor.Caret.Line, document.Editor.Caret.Column); |
||||
if (expr is InvocationExpression) { |
||||
expr = ((InvocationExpression)expr).Target; |
||||
} |
||||
if (expr == null) |
||||
return null; |
||||
var member = Unit.GetNodeAt<AttributedNode> (memberLocation); |
||||
var member2 = baseUnit.GetNodeAt<AttributedNode> (memberLocation); |
||||
member2.Remove (); |
||||
member.ReplaceWith (member2); |
||||
|
||||
var tsvisitor = new TypeSystemConvertVisitor (ProjectContext, Document.FileName); |
||||
Unit.AcceptVisitor (tsvisitor, null); |
||||
return Tuple.Create (tsvisitor.ParsedFile, expr, Unit);*/ |
||||
} |
||||
|
||||
protected Tuple<ResolveResult, CSharpResolver> ResolveExpression (CSharpParsedFile file, AstNode expr, CompilationUnit unit) |
||||
{ |
||||
if (expr == null) |
||||
return null; |
||||
AstNode resolveNode; |
||||
if (expr is Expression || expr is AstType) { |
||||
resolveNode = expr; |
||||
} else if (expr is VariableDeclarationStatement) { |
||||
resolveNode = ((VariableDeclarationStatement)expr).Type; |
||||
} else { |
||||
resolveNode = expr; |
||||
} |
||||
|
||||
// var newContent = ProjectContent.UpdateProjectContent (CSharpParsedFile, file);
|
||||
|
||||
var csResolver = new CSharpResolver (ctx); |
||||
|
||||
var navigator = new NodeListResolveVisitorNavigator (new[] { resolveNode }); |
||||
var visitor = new ResolveVisitor (csResolver, CSharpParsedFile, navigator); |
||||
|
||||
visitor.Scan (unit); |
||||
var state = visitor.GetResolverStateBefore (resolveNode); |
||||
var result = visitor.GetResolveResult (resolveNode); |
||||
return Tuple.Create (result, state); |
||||
} |
||||
|
||||
protected static void Print (AstNode node) |
||||
{ |
||||
var v = new CSharpOutputVisitor (Console.Out, new CSharpFormattingOptions ()); |
||||
node.AcceptVisitor (v, null); |
||||
} |
||||
|
||||
#endregion
|
||||
} |
||||
} |
@ -0,0 +1,326 @@
@@ -0,0 +1,326 @@
|
||||
//
|
||||
// CSharpParameterCompletionEngine.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System; |
||||
using ICSharpCode.NRefactory.Editor; |
||||
using ICSharpCode.NRefactory.Completion; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.NRefactory.Semantics; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.CSharp.Resolver; |
||||
using ICSharpCode.NRefactory.CSharp.TypeSystem; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Completion |
||||
{ |
||||
public class CSharpParameterCompletionEngine : CSharpCompletionEngineBase |
||||
{ |
||||
internal IParameterCompletionDataFactory factory; |
||||
|
||||
public CSharpParameterCompletionEngine (IDocument document, IParameterCompletionDataFactory factory) |
||||
{ |
||||
this.document = document; |
||||
this.factory = factory; |
||||
} |
||||
|
||||
public Tuple<CSharpParsedFile, AstNode, CompilationUnit> GetIndexerBeforeCursor () |
||||
{ |
||||
CompilationUnit baseUnit; |
||||
if (currentMember == null && currentType == null) |
||||
return null; |
||||
baseUnit = ParseStub ("x] = a[1"); |
||||
|
||||
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin; |
||||
var mref = baseUnit.GetNodeAt (location, n => n is IndexerExpression); |
||||
Print (baseUnit); |
||||
AstNode expr; |
||||
if (mref is IndexerExpression) { |
||||
expr = ((IndexerExpression)mref).Target; |
||||
} else { |
||||
return null; |
||||
} |
||||
|
||||
var member = Unit.GetNodeAt<AttributedNode> (memberLocation); |
||||
var member2 = baseUnit.GetNodeAt<AttributedNode> (memberLocation); |
||||
member2.Remove (); |
||||
member.ReplaceWith (member2); |
||||
var tsvisitor = new TypeSystemConvertVisitor (CSharpParsedFile.FileName); |
||||
Unit.AcceptVisitor (tsvisitor, null); |
||||
return Tuple.Create (tsvisitor.ParsedFile, (AstNode)expr, Unit); |
||||
} |
||||
|
||||
public IParameterDataProvider GetParameterDataProvider (int offset, char completionChar) |
||||
{ |
||||
if (offset <= 0) |
||||
return null; |
||||
if (completionChar != '(' && completionChar != '<' && completionChar != '[' && completionChar != ',') |
||||
return null; |
||||
|
||||
SetOffset (offset); |
||||
if (IsInsideCommentOrString ()) |
||||
return null; |
||||
|
||||
var invoke = GetInvocationBeforeCursor (true) ?? GetIndexerBeforeCursor (); |
||||
if (invoke == null) |
||||
return null; |
||||
|
||||
ResolveResult resolveResult; |
||||
switch (completionChar) { |
||||
case '(': |
||||
if (invoke.Item2 is ObjectCreateExpression) { |
||||
var createType = ResolveExpression (invoke.Item1, ((ObjectCreateExpression)invoke.Item2).Type, invoke.Item3); |
||||
return factory.CreateConstructorProvider (createType.Item1.Type); |
||||
} |
||||
|
||||
if (invoke.Item2 is ICSharpCode.NRefactory.CSharp.Attribute) { |
||||
var attribute = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); |
||||
if (attribute == null || attribute.Item1 == null) |
||||
return null; |
||||
return factory.CreateConstructorProvider (attribute.Item1.Type); |
||||
} |
||||
var invocationExpression = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); |
||||
if (invocationExpression == null || invocationExpression.Item1 == null || invocationExpression.Item1.IsError) |
||||
return null; |
||||
resolveResult = invocationExpression.Item1; |
||||
if (resolveResult is MethodGroupResolveResult) |
||||
return factory.CreateMethodDataProvider (resolveResult as MethodGroupResolveResult); |
||||
if (resolveResult is MemberResolveResult) { |
||||
var mr = resolveResult as MemberResolveResult; |
||||
if (mr.Member is IMethod) |
||||
return factory.CreateMethodDataProvider ((IMethod)mr.Member); |
||||
} |
||||
|
||||
if (resolveResult.Type.Kind == TypeKind.Delegate) |
||||
return factory.CreateDelegateDataProvider (resolveResult.Type); |
||||
|
||||
//
|
||||
// if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) {
|
||||
// if (resolveResult is ThisResolveResult)
|
||||
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult);
|
||||
// if (resolveResult is BaseResolveResult)
|
||||
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult);
|
||||
// }
|
||||
// IType resolvedType = resolver.SearchType (resolveResult.ResolvedType);
|
||||
// if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) {
|
||||
// return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType);
|
||||
// }
|
||||
break; |
||||
case ',': |
||||
if (invoke.Item2 is ObjectCreateExpression) { |
||||
var createType = ResolveExpression (invoke.Item1, ((ObjectCreateExpression)invoke.Item2).Type, invoke.Item3); |
||||
return factory.CreateConstructorProvider (createType.Item1.Type); |
||||
} |
||||
|
||||
if (invoke.Item2 is ICSharpCode.NRefactory.CSharp.Attribute) { |
||||
var attribute = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); |
||||
if (attribute == null || attribute.Item1 == null) |
||||
return null; |
||||
return factory.CreateConstructorProvider (attribute.Item1.Type); |
||||
} |
||||
|
||||
invocationExpression = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); |
||||
|
||||
if (invocationExpression == null || invocationExpression.Item1 == null || invocationExpression.Item1.IsError) |
||||
return null; |
||||
|
||||
resolveResult = invocationExpression.Item1; |
||||
if (resolveResult is MethodGroupResolveResult) |
||||
return factory.CreateMethodDataProvider (resolveResult as MethodGroupResolveResult); |
||||
if (resolveResult is MemberResolveResult) { |
||||
if (resolveResult.Type.Kind == TypeKind.Delegate) |
||||
return factory.CreateDelegateDataProvider (resolveResult.Type); |
||||
var mr = resolveResult as MemberResolveResult; |
||||
if (mr.Member is IMethod) |
||||
return factory.CreateMethodDataProvider ((IMethod)mr.Member); |
||||
} |
||||
if (resolveResult != null) |
||||
return factory.CreateIndexerParameterDataProvider (resolveResult.Type, invoke.Item2); |
||||
break; |
||||
// case '<':
|
||||
// if (string.IsNullOrEmpty (result.Expression))
|
||||
// return null;
|
||||
// return new NRefactoryTemplateParameterDataProvider (textEditorData, resolver, GetUsedNamespaces (), result, new TextLocation (completionContext.TriggerLine, completionContext.TriggerLineOffset));
|
||||
|
||||
case '[': |
||||
var indexerExpression = ResolveExpression (invoke.Item1, invoke.Item2, invoke.Item3); |
||||
if (indexerExpression == null || indexerExpression.Item1 == null || indexerExpression.Item1.IsError) |
||||
return null; |
||||
return factory.CreateIndexerParameterDataProvider (indexerExpression.Item1.Type, invoke.Item2); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
List<string> GetUsedNamespaces () |
||||
{ |
||||
var scope = CSharpParsedFile.GetUsingScope (location); |
||||
var result = new List<string> (); |
||||
var resolver = new CSharpResolver (ctx); |
||||
while (scope != null) { |
||||
result.Add (scope.NamespaceName); |
||||
|
||||
foreach (var u in scope.Usings) { |
||||
var ns = u.ResolveNamespace (resolver); |
||||
if (ns == null) |
||||
continue; |
||||
result.Add (ns.FullName); |
||||
} |
||||
scope = scope.Parent; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public int GetCurrentParameterIndex (int triggerOffset) |
||||
{ |
||||
SetOffset (triggerOffset); |
||||
var text = GetMemberTextToCaret (); |
||||
var parameter = new Stack<int> (); |
||||
|
||||
bool inSingleComment = false, inString = false, inVerbatimString = false, inChar = false, inMultiLineComment = false; |
||||
|
||||
for (int i = 0; i < text.Item1.Length; i++) { |
||||
char ch = text.Item1 [i]; |
||||
char nextCh = i + 1 < text.Item1.Length ? text.Item1 [i + 1] : '\0'; |
||||
|
||||
switch (ch) { |
||||
case '(': |
||||
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) |
||||
break; |
||||
parameter.Push (0); |
||||
break; |
||||
case ')': |
||||
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) |
||||
break; |
||||
if (parameter.Count > 0) |
||||
parameter.Pop (); |
||||
break; |
||||
case ',': |
||||
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) |
||||
break; |
||||
if (parameter.Count > 0) |
||||
parameter.Push (parameter.Pop () + 1); |
||||
break; |
||||
case '/': |
||||
if (inString || inChar || inVerbatimString) |
||||
break; |
||||
if (nextCh == '/') { |
||||
i++; |
||||
inSingleComment = true; |
||||
} |
||||
if (nextCh == '*') |
||||
inMultiLineComment = true; |
||||
break; |
||||
case '*': |
||||
if (inString || inChar || inVerbatimString || inSingleComment) |
||||
break; |
||||
if (nextCh == '/') { |
||||
i++; |
||||
inMultiLineComment = false; |
||||
} |
||||
break; |
||||
case '@': |
||||
if (inString || inChar || inVerbatimString || inSingleComment || inMultiLineComment) |
||||
break; |
||||
if (nextCh == '"') { |
||||
i++; |
||||
inVerbatimString = true; |
||||
} |
||||
break; |
||||
case '\n': |
||||
case '\r': |
||||
inSingleComment = false; |
||||
inString = false; |
||||
inChar = false; |
||||
break; |
||||
case '\\': |
||||
if (inString || inChar) |
||||
i++; |
||||
break; |
||||
case '"': |
||||
if (inSingleComment || inMultiLineComment || inChar) |
||||
break; |
||||
if (inVerbatimString) { |
||||
if (nextCh == '"') { |
||||
i++; |
||||
break; |
||||
} |
||||
inVerbatimString = false; |
||||
break; |
||||
} |
||||
inString = !inString; |
||||
break; |
||||
case '\'': |
||||
if (inSingleComment || inMultiLineComment || inString || inVerbatimString) |
||||
break; |
||||
inChar = !inChar; |
||||
break; |
||||
} |
||||
} |
||||
if (parameter.Count == 0) |
||||
return -1; |
||||
if (text.Item1.EndsWith ("(")) |
||||
return 1; |
||||
return parameter.Pop () + 1; |
||||
} |
||||
|
||||
/* |
||||
public override bool GetParameterCompletionCommandOffset (out int cpos) |
||||
{ |
||||
// Start calculating the parameter offset from the beginning of the
|
||||
// current member, instead of the beginning of the file.
|
||||
cpos = textEditorData.Caret.Offset - 1; |
||||
var parsedDocument = Document.ParsedDocument; |
||||
if (parsedDocument == null) |
||||
return false; |
||||
IMember mem = currentMember; |
||||
if (mem == null || (mem is IType)) |
||||
return false; |
||||
int startPos = textEditorData.LocationToOffset (mem.Region.BeginLine, mem.Region.BeginColumn); |
||||
int parenDepth = 0; |
||||
int chevronDepth = 0; |
||||
while (cpos > startPos) { |
||||
char c = textEditorData.GetCharAt (cpos); |
||||
if (c == ')') |
||||
parenDepth++; |
||||
if (c == '>') |
||||
chevronDepth++; |
||||
if (parenDepth == 0 && c == '(' || chevronDepth == 0 && c == '<') { |
||||
int p = MethodParameterDataProvider.GetCurrentParameterIndex (CompletionWidget, cpos + 1, startPos); |
||||
if (p != -1) { |
||||
cpos++; |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
if (c == '(') |
||||
parenDepth--; |
||||
if (c == '<') |
||||
chevronDepth--; |
||||
cpos--; |
||||
} |
||||
return false; |
||||
}*/ |
||||
} |
||||
} |
||||
|
@ -0,0 +1,237 @@
@@ -0,0 +1,237 @@
|
||||
//
|
||||
// CompletionDataWrapper.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.NRefactory.Completion; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Completion |
||||
{ |
||||
class CompletionDataWrapper |
||||
{ |
||||
CSharpCompletionEngine completion; |
||||
List<ICompletionData> result = new List<ICompletionData> (); |
||||
|
||||
public List<ICompletionData> Result { |
||||
get { |
||||
return result; |
||||
} |
||||
} |
||||
|
||||
ICompletionDataFactory Factory { |
||||
get { |
||||
return completion.factory; |
||||
} |
||||
} |
||||
|
||||
public CompletionDataWrapper (CSharpCompletionEngine completion) |
||||
{ |
||||
this.completion = completion; |
||||
} |
||||
|
||||
public void Add (ICompletionData data) |
||||
{ |
||||
result.Add (data); |
||||
} |
||||
|
||||
public void AddCustom (string displayText, string description = null, string completionText = null) |
||||
{ |
||||
result.Add (Factory.CreateLiteralCompletionData (displayText, description, completionText)); |
||||
} |
||||
|
||||
HashSet<string> usedNamespaces = new HashSet<string> (); |
||||
|
||||
public void AddNamespace (string name) |
||||
{ |
||||
if (string.IsNullOrEmpty (name) || usedNamespaces.Contains (name)) |
||||
return; |
||||
usedNamespaces.Add (name); |
||||
result.Add (Factory.CreateNamespaceCompletionData (name)); |
||||
} |
||||
|
||||
HashSet<string> usedTypes = new HashSet<string> (); |
||||
|
||||
public void AddType (IType type, string shortType) |
||||
{ |
||||
if (type == null || string.IsNullOrEmpty (shortType) || usedTypes.Contains (shortType)) |
||||
return; |
||||
usedTypes.Add (shortType); |
||||
result.Add (Factory.CreateTypeCompletionData (type, shortType)); |
||||
} |
||||
|
||||
public void AddType (IUnresolvedTypeDefinition type, string shortType) |
||||
{ |
||||
if (type == null || string.IsNullOrEmpty (shortType) || usedTypes.Contains (shortType)) |
||||
return; |
||||
usedTypes.Add (shortType); |
||||
result.Add (Factory.CreateTypeCompletionData (type, shortType)); |
||||
} |
||||
|
||||
Dictionary<string, List<ICompletionData>> data = new Dictionary<string, List<ICompletionData>> (); |
||||
|
||||
public void AddVariable (IVariable variable) |
||||
{ |
||||
if (data.ContainsKey (variable.Name)) |
||||
return; |
||||
data [variable.Name] = new List<ICompletionData> (); |
||||
result.Add (Factory.CreateVariableCompletionData (variable)); |
||||
} |
||||
|
||||
public void AddTypeParameter (IUnresolvedTypeParameter variable) |
||||
{ |
||||
if (data.ContainsKey (variable.Name)) |
||||
return; |
||||
data [variable.Name] = new List<ICompletionData> (); |
||||
result.Add (Factory.CreateVariableCompletionData (variable)); |
||||
} |
||||
|
||||
public ICompletionData AddMember (IUnresolvedMember member) |
||||
{ |
||||
var newData = Factory.CreateEntityCompletionData (member); |
||||
|
||||
// newData.HideExtensionParameter = HideExtensionParameter;
|
||||
string memberKey = newData.DisplayText; |
||||
if (memberKey == null) |
||||
return null; |
||||
if (member is IMember) { |
||||
newData.CompletionCategory = GetCompletionCategory (member.DeclaringTypeDefinition.Resolve (completion.ctx)); |
||||
} |
||||
List<ICompletionData> existingData; |
||||
data.TryGetValue (memberKey, out existingData); |
||||
|
||||
if (existingData != null) { |
||||
var a = member as IEntity; |
||||
foreach (var d in existingData) { |
||||
if (!(d is IEntityCompletionData)) |
||||
continue; |
||||
var b = ((IEntityCompletionData)d).Entity; |
||||
if (a == null || b == null || a.EntityType == b.EntityType) { |
||||
d.AddOverload (newData); |
||||
return d; |
||||
} |
||||
} |
||||
if (newData != null) { |
||||
result.Add (newData); |
||||
data [memberKey].Add (newData); |
||||
} |
||||
} else { |
||||
result.Add (newData); |
||||
data [memberKey] = new List<ICompletionData> (); |
||||
data [memberKey].Add (newData); |
||||
} |
||||
return newData; |
||||
} |
||||
|
||||
public ICompletionData AddMember (IMember member) |
||||
{ |
||||
var newData = Factory.CreateEntityCompletionData (member); |
||||
|
||||
// newData.HideExtensionParameter = HideExtensionParameter;
|
||||
string memberKey = newData.DisplayText; |
||||
if (memberKey == null) |
||||
return null; |
||||
if (member is IMember) { |
||||
newData.CompletionCategory = GetCompletionCategory (member.DeclaringTypeDefinition); |
||||
} |
||||
List<ICompletionData> existingData; |
||||
data.TryGetValue (memberKey, out existingData); |
||||
|
||||
if (existingData != null) { |
||||
var a = member as IEntity; |
||||
foreach (var d in existingData) { |
||||
if (!(d is IEntityCompletionData)) |
||||
continue; |
||||
var b = ((IEntityCompletionData)d).Entity; |
||||
if (a == null || b == null || a.EntityType == b.EntityType) { |
||||
d.AddOverload (newData); |
||||
return d; |
||||
} |
||||
} |
||||
if (newData != null) { |
||||
result.Add (newData); |
||||
data [memberKey].Add (newData); |
||||
} |
||||
} else { |
||||
result.Add (newData); |
||||
data [memberKey] = new List<ICompletionData> (); |
||||
data [memberKey].Add (newData); |
||||
} |
||||
return newData; |
||||
} |
||||
|
||||
internal CompletionCategory GetCompletionCategory (IType type) |
||||
{ |
||||
if (type == null) |
||||
return null; |
||||
if (!completionCategories.ContainsKey (type)) |
||||
completionCategories [type] = new TypeCompletionCategory (type); |
||||
return completionCategories [type]; |
||||
} |
||||
|
||||
Dictionary<IType, CompletionCategory> completionCategories = new Dictionary<IType, CompletionCategory> (); |
||||
class TypeCompletionCategory : CompletionCategory |
||||
{ |
||||
public IType Type { |
||||
get; |
||||
private set; |
||||
} |
||||
|
||||
public TypeCompletionCategory (IType type) : base (type.FullName, null) |
||||
{ |
||||
this.Type = type; |
||||
} |
||||
|
||||
public override int CompareTo (CompletionCategory other) |
||||
{ |
||||
var compareCategory = other as TypeCompletionCategory; |
||||
if (compareCategory == null) |
||||
return 1; |
||||
|
||||
if (Type.ReflectionName == compareCategory.Type.ReflectionName) |
||||
return 0; |
||||
|
||||
// System.Object is always the smallest
|
||||
if (Type.ReflectionName == "System.Object") |
||||
return -1; |
||||
if (compareCategory.Type.ReflectionName == "System.Object") |
||||
return 1; |
||||
|
||||
/* if (Type.GetProjectContent () != null) { |
||||
if (Type.GetProjectContent ().GetInheritanceTree (Type).Any (t => t != null && t.DecoratedFullName == compareCategory.Type.DecoratedFullName)) |
||||
return 1; |
||||
return -1; |
||||
} |
||||
|
||||
// source project dom == null - try to make the opposite comparison
|
||||
if (compareCategory.Type.GetProjectContent () != null && compareCategory.Type.GetProjectContent ().GetInheritanceTree (Type).Any (t => t != null && t.DecoratedFullName == Type.DecoratedFullName)) |
||||
return -1;*/ |
||||
return 1; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// ICompletionDataFactory.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.Completion; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Completion |
||||
{ |
||||
public interface ICompletionDataFactory |
||||
{ |
||||
ICompletionData CreateEntityCompletionData (IUnresolvedEntity entity); |
||||
ICompletionData CreateEntityCompletionData (IUnresolvedEntity entity, string text); |
||||
ICompletionData CreateEntityCompletionData (IEntity entity); |
||||
ICompletionData CreateEntityCompletionData (IEntity entity, string text); |
||||
|
||||
ICompletionData CreateTypeCompletionData (IType type, string shortType); |
||||
ICompletionData CreateTypeCompletionData (IUnresolvedTypeDefinition type, string shortType); |
||||
|
||||
/// <summary>
|
||||
/// Creates a generic completion data.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The title of the completion data
|
||||
/// </param>
|
||||
/// <param name='description'>
|
||||
/// The description of the literal.
|
||||
/// </param>
|
||||
/// <param name='insertText'>
|
||||
/// The insert text. If null, title is taken.
|
||||
/// </param>
|
||||
ICompletionData CreateLiteralCompletionData (string title, string description = null, string insertText = null); |
||||
|
||||
ICompletionData CreateNamespaceCompletionData (string name); |
||||
|
||||
ICompletionData CreateVariableCompletionData (IVariable variable); |
||||
|
||||
ICompletionData CreateVariableCompletionData (IUnresolvedTypeParameter parameter); |
||||
|
||||
ICompletionData CreateEventCreationCompletionData (string varName, IType delegateType, IEvent evt, string parameterDefinition, IUnresolvedMember currentMember, IUnresolvedTypeDefinition currentType); |
||||
|
||||
ICompletionData CreateNewOverrideCompletionData (int declarationBegin, IUnresolvedTypeDefinition type, IMember m); |
||||
|
||||
IEnumerable<ICompletionData> CreateCodeTemplateCompletionData (); |
||||
|
||||
IEnumerable<ICompletionData> CreatePreProcessorDefinesCompletionData (); |
||||
} |
||||
} |
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// IParameterCopmletionFactory.cs
|
||||
//
|
||||
// Author:
|
||||
// Mike Krüger <mkrueger@xamarin.com>
|
||||
//
|
||||
// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.Completion; |
||||
using ICSharpCode.NRefactory.CSharp.Resolver; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Completion |
||||
{ |
||||
public interface IParameterCompletionDataFactory |
||||
{ |
||||
IParameterDataProvider CreateConstructorProvider (IType type); |
||||
|
||||
IParameterDataProvider CreateMethodDataProvider (MethodGroupResolveResult par1); |
||||
|
||||
IParameterDataProvider CreateMethodDataProvider (IMethod method); |
||||
|
||||
IParameterDataProvider CreateDelegateDataProvider (IType type); |
||||
|
||||
IParameterDataProvider CreateIndexerParameterDataProvider (IType type, AstNode resolvedNode); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,239 @@
@@ -0,0 +1,239 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System; |
||||
using System.IO; |
||||
using ICSharpCode.NRefactory.CSharp.Refactoring; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp |
||||
{ |
||||
/// <summary>
|
||||
/// C# ambience.
|
||||
/// </summary>
|
||||
public class CSharpAmbience : IAmbience |
||||
{ |
||||
public ConversionFlags ConversionFlags { get; set; } |
||||
|
||||
#region ConvertEntity
|
||||
public string ConvertEntity(IEntity e) |
||||
{ |
||||
StringWriter writer = new StringWriter(); |
||||
|
||||
if (e.EntityType == EntityType.TypeDefinition) { |
||||
ConvertTypeDeclaration((ITypeDefinition)e, writer); |
||||
} else { |
||||
ConvertMember((IMember)e, writer); |
||||
} |
||||
|
||||
return writer.ToString().TrimEnd(); |
||||
} |
||||
|
||||
void ConvertMember(IMember member, StringWriter writer) |
||||
{ |
||||
TypeSystemAstBuilder astBuilder = CreateAstBuilder(); |
||||
astBuilder.ShowParameterNames = (ConversionFlags & ConversionFlags.ShowParameterNames) == ConversionFlags.ShowParameterNames; |
||||
|
||||
AttributedNode node = (AttributedNode)astBuilder.ConvertEntity(member); |
||||
PrintModifiers(node.Modifiers, writer); |
||||
|
||||
if ((ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) { |
||||
var rt = node.GetChildByRole(AstNode.Roles.Type); |
||||
if (rt != AstNode.Roles.Type.NullObject) { |
||||
writer.Write(rt.AcceptVisitor(CreatePrinter(writer), null)); |
||||
writer.Write(' '); |
||||
} |
||||
} |
||||
|
||||
WriteMemberDeclarationName(member, writer); |
||||
|
||||
if ((ConversionFlags & ConversionFlags.ShowParameterList) == ConversionFlags.ShowParameterList |
||||
&& member is IParameterizedMember && member.EntityType != EntityType.Property) { |
||||
writer.Write((node is IndexerDeclaration) ? '[' : '('); |
||||
bool first = true; |
||||
foreach (var param in node.GetChildrenByRole(AstNode.Roles.Parameter)) { |
||||
if (first) |
||||
first = false; |
||||
else |
||||
writer.Write(", "); |
||||
param.AcceptVisitor(CreatePrinter(writer), null); |
||||
} |
||||
writer.Write((node is IndexerDeclaration) ? ']' : ')'); |
||||
} |
||||
if ((ConversionFlags & ConversionFlags.ShowBody) == ConversionFlags.ShowBody) { |
||||
IProperty property = member as IProperty; |
||||
if (property != null) { |
||||
writer.Write(" { "); |
||||
if (property.CanGet) |
||||
writer.Write("get; "); |
||||
if (property.CanSet) |
||||
writer.Write("set; "); |
||||
writer.Write('}'); |
||||
} else { |
||||
writer.Write(';'); |
||||
} |
||||
} |
||||
} |
||||
|
||||
TypeSystemAstBuilder CreateAstBuilder() |
||||
{ |
||||
TypeSystemAstBuilder astBuilder = new TypeSystemAstBuilder(); |
||||
astBuilder.ShowModifiers = (ConversionFlags & ConversionFlags.ShowModifiers) == ConversionFlags.ShowModifiers; |
||||
astBuilder.ShowAccessibility = (ConversionFlags & ConversionFlags.ShowAccessibility) == ConversionFlags.ShowAccessibility; |
||||
astBuilder.AlwaysUseShortTypeNames = (ConversionFlags & ConversionFlags.UseFullyQualifiedTypeNames) != ConversionFlags.UseFullyQualifiedTypeNames; |
||||
return astBuilder; |
||||
} |
||||
|
||||
void ConvertTypeDeclaration(ITypeDefinition typeDef, StringWriter writer) |
||||
{ |
||||
TypeSystemAstBuilder astBuilder = CreateAstBuilder(); |
||||
TypeDeclaration typeDeclaration = (TypeDeclaration)astBuilder.ConvertEntity(typeDef); |
||||
PrintModifiers(typeDeclaration.Modifiers, writer); |
||||
if ((ConversionFlags & ConversionFlags.ShowDefinitionKeyWord) == ConversionFlags.ShowDefinitionKeyWord) { |
||||
switch (typeDeclaration.ClassType) { |
||||
case ClassType.Class: |
||||
writer.Write("class"); |
||||
break; |
||||
case ClassType.Struct: |
||||
writer.Write("struct"); |
||||
break; |
||||
case ClassType.Interface: |
||||
writer.Write("interface"); |
||||
break; |
||||
case ClassType.Enum: |
||||
writer.Write("enum"); |
||||
break; |
||||
default: |
||||
throw new Exception("Invalid value for ClassType"); |
||||
} |
||||
writer.Write(' '); |
||||
} |
||||
WriteTypeDeclarationName(typeDef, writer); |
||||
} |
||||
|
||||
void WriteTypeDeclarationName(ITypeDefinition typeDef, StringWriter writer) |
||||
{ |
||||
TypeSystemAstBuilder astBuilder = CreateAstBuilder(); |
||||
if (typeDef.DeclaringTypeDefinition != null) { |
||||
WriteTypeDeclarationName(typeDef.DeclaringTypeDefinition, writer); |
||||
writer.Write('.'); |
||||
} else if ((ConversionFlags & ConversionFlags.UseFullyQualifiedMemberNames) == ConversionFlags.UseFullyQualifiedMemberNames) { |
||||
writer.Write(typeDef.Namespace); |
||||
writer.Write('.'); |
||||
} |
||||
writer.Write(typeDef.Name); |
||||
if ((ConversionFlags & ConversionFlags.ShowTypeParameterList) == ConversionFlags.ShowTypeParameterList) { |
||||
CreatePrinter(writer).WriteTypeParameters(((TypeDeclaration)astBuilder.ConvertEntity(typeDef)).TypeParameters); |
||||
} |
||||
} |
||||
|
||||
void WriteMemberDeclarationName(IMember member, StringWriter writer) |
||||
{ |
||||
TypeSystemAstBuilder astBuilder = CreateAstBuilder(); |
||||
if ((ConversionFlags & ConversionFlags.UseFullyQualifiedMemberNames) == ConversionFlags.UseFullyQualifiedMemberNames) { |
||||
writer.Write(ConvertType(member.DeclaringType)); |
||||
writer.Write('.'); |
||||
} |
||||
switch (member.EntityType) { |
||||
case EntityType.Indexer: |
||||
writer.Write("this"); |
||||
break; |
||||
case EntityType.Constructor: |
||||
writer.Write(member.DeclaringType.Name); |
||||
break; |
||||
case EntityType.Destructor: |
||||
writer.Write('~'); |
||||
writer.Write(member.DeclaringType.Name); |
||||
break; |
||||
case EntityType.Operator: |
||||
switch (member.Name) { |
||||
case "op_Implicit": |
||||
writer.Write("implicit operator "); |
||||
writer.Write(ConvertType(member.ReturnType)); |
||||
break; |
||||
case "op_Explicit": |
||||
writer.Write("explicit operator "); |
||||
writer.Write(ConvertType(member.ReturnType)); |
||||
break; |
||||
default: |
||||
writer.Write("operator "); |
||||
var operatorType = OperatorDeclaration.GetOperatorType(member.Name); |
||||
if (operatorType.HasValue) |
||||
writer.Write(OperatorDeclaration.GetToken(operatorType.Value)); |
||||
else |
||||
writer.Write(member.Name); |
||||
break; |
||||
} |
||||
break; |
||||
default: |
||||
writer.Write(member.Name); |
||||
break; |
||||
} |
||||
if ((ConversionFlags & ConversionFlags.ShowTypeParameterList) == ConversionFlags.ShowTypeParameterList && member.EntityType == EntityType.Method) { |
||||
CreatePrinter(writer).WriteTypeParameters(astBuilder.ConvertEntity(member).GetChildrenByRole(AstNode.Roles.TypeParameter)); |
||||
} |
||||
} |
||||
|
||||
CSharpOutputVisitor CreatePrinter(StringWriter writer) |
||||
{ |
||||
return new CSharpOutputVisitor(writer, new CSharpFormattingOptions()); |
||||
} |
||||
|
||||
void PrintModifiers(Modifiers modifiers, StringWriter writer) |
||||
{ |
||||
foreach (var m in CSharpModifierToken.AllModifiers) { |
||||
if ((modifiers & m) == m) { |
||||
writer.Write(CSharpModifierToken.GetModifierName(m)); |
||||
writer.Write(' '); |
||||
} |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
public string ConvertVariable(IVariable v) |
||||
{ |
||||
TypeSystemAstBuilder astBuilder = CreateAstBuilder(); |
||||
AstNode astNode = astBuilder.ConvertVariable(v); |
||||
CSharpFormattingOptions formatting = new CSharpFormattingOptions(); |
||||
StringWriter writer = new StringWriter(); |
||||
astNode.AcceptVisitor(new CSharpOutputVisitor(writer, formatting), null); |
||||
return writer.ToString().TrimEnd(';', '\r', '\n'); |
||||
} |
||||
|
||||
public string ConvertType(IType type) |
||||
{ |
||||
TypeSystemAstBuilder astBuilder = CreateAstBuilder(); |
||||
AstType astType = astBuilder.ConvertType(type); |
||||
CSharpFormattingOptions formatting = new CSharpFormattingOptions(); |
||||
StringWriter writer = new StringWriter(); |
||||
astType.AcceptVisitor(new CSharpOutputVisitor(writer, formatting), null); |
||||
return writer.ToString(); |
||||
} |
||||
|
||||
public string WrapAttribute(string attribute) |
||||
{ |
||||
return "[" + attribute + "]"; |
||||
} |
||||
|
||||
public string WrapComment(string comment) |
||||
{ |
||||
return "// " + comment; |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,161 @@
@@ -0,0 +1,161 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Threading; |
||||
using ICSharpCode.NRefactory.CSharp.TypeSystem; |
||||
using ICSharpCode.NRefactory.Semantics; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
|
||||
namespace ICSharpCode.NRefactory.CSharp.Resolver |
||||
{ |
||||
/// <summary>
|
||||
/// Resolves C# AST nodes.
|
||||
/// </summary>
|
||||
public class CSharpAstResolver |
||||
{ |
||||
readonly CSharpResolver initialResolverState; |
||||
readonly AstNode rootNode; |
||||
readonly CSharpParsedFile parsedFile; |
||||
ResolveVisitor resolveVisitor; |
||||
|
||||
/// <summary>
|
||||
/// Creates a new C# AST resolver.
|
||||
/// </summary>
|
||||
/// <param name="compilation">The current compilation.</param>
|
||||
/// <param name="parsedFile">
|
||||
/// Result of the <see cref="TypeSystemConvertVisitor"/> for the file being passed. This is used for setting up the context on the resolver. The parsed file must be registered in the compilation.
|
||||
/// </param>
|
||||
/// <param name="compilationUnit">The compilation unit corresponding to the specified parsed file.</param>
|
||||
public CSharpAstResolver(ICompilation compilation, CompilationUnit compilationUnit, CSharpParsedFile parsedFile) |
||||
{ |
||||
if (compilation == null) |
||||
throw new ArgumentNullException("compilation"); |
||||
if (parsedFile == null) |
||||
throw new ArgumentNullException("parsedFile"); |
||||
if (compilationUnit == null) |
||||
throw new ArgumentNullException("compilationUnit"); |
||||
this.initialResolverState = new CSharpResolver(compilation); |
||||
this.rootNode = compilationUnit; |
||||
this.parsedFile = parsedFile; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Creates a new C# AST resolver.
|
||||
/// </summary>
|
||||
/// <param name="resolver">The resolver state at the root node.</param>
|
||||
/// <param name="rootNode">The root node of the resolved tree.</param>
|
||||
/// <param name="parsedFile">The parsed file for the nodes being resolved. This parameter is used only
|
||||
/// when the root node is on the type level; it is not necessary when an expression is passed.
|
||||
/// This parameter may be null.</param>
|
||||
public CSharpAstResolver(CSharpResolver resolver, AstNode rootNode, CSharpParsedFile parsedFile = null) |
||||
{ |
||||
if (resolver == null) |
||||
throw new ArgumentNullException("resolver"); |
||||
if (rootNode == null) |
||||
throw new ArgumentNullException("rootNode"); |
||||
this.initialResolverState = resolver.Clone(); |
||||
this.rootNode = rootNode; |
||||
this.parsedFile = parsedFile; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the type resolve context for the root resolver.
|
||||
/// </summary>
|
||||
public CSharpTypeResolveContext TypeResolveContext { |
||||
get { return initialResolverState.CurrentTypeResolveContext; } |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Applies a resolver navigator. This will resolve the nodes requested by the navigator, and will inform the
|
||||
/// navigator of the results.
|
||||
/// This method must be called as the first operation on the CSharpAstResolver, it is invalid to apply a navigator
|
||||
/// after a portion of the file was already resolved.
|
||||
/// </summary>
|
||||
public void ApplyNavigator(IResolveVisitorNavigator navigator, CancellationToken cancellationToken = default(CancellationToken)) |
||||
{ |
||||
if (navigator == null) |
||||
throw new ArgumentNullException("navigator"); |
||||
if (resolveVisitor != null) |
||||
throw new InvalidOperationException("Applying a navigator is only valid as the first operation on the CSharpAstResolver."); |
||||
resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile, navigator); |
||||
lock (resolveVisitor) |
||||
resolveVisitor.Scan(rootNode); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Resolves the specified node.
|
||||
/// </summary>
|
||||
public ResolveResult Resolve(AstNode node, CancellationToken cancellationToken = default(CancellationToken)) |
||||
{ |
||||
if (node == null || node.IsNull) |
||||
return ErrorResolveResult.UnknownError; |
||||
InitResolver(node); |
||||
lock (resolveVisitor) { |
||||
ResolveResult rr = resolveVisitor.GetResolveResult(node); |
||||
Debug.Assert(rr != null); |
||||
return rr; |
||||
} |
||||
} |
||||
|
||||
void InitResolver(AstNode firstNodeToResolve) |
||||
{ |
||||
if (resolveVisitor == null) { |
||||
resolveVisitor = new ResolveVisitor(initialResolverState, parsedFile, new NodeListResolveVisitorNavigator(firstNodeToResolve)); |
||||
resolveVisitor.Scan(rootNode); |
||||
} |
||||
} |
||||
|
||||
public CSharpResolver GetResolverStateBefore(AstNode node, CancellationToken cancellationToken = default(CancellationToken)) |
||||
{ |
||||
if (node == null || node.IsNull) |
||||
throw new ArgumentNullException("node"); |
||||
InitResolver(node); |
||||
lock (resolveVisitor) { |
||||
CSharpResolver resolver = resolveVisitor.GetResolverStateBefore(node); |
||||
Debug.Assert(resolver != null); |
||||
return resolver; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the expected type for the specified node. This is the type being that a node is being converted to.
|
||||
/// </summary>
|
||||
public IType GetExpectedType(Expression expr, CancellationToken cancellationToken = default(CancellationToken)) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the conversion that is being applied to the specified expression.
|
||||
/// </summary>
|
||||
public Conversion GetConversion(Expression expr, CancellationToken cancellationToken = default(CancellationToken)) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets whether the specified node is unresolvable.
|
||||
/// </summary>
|
||||
public static bool IsUnresolvableNode(AstNode node) |
||||
{ |
||||
return (node.NodeType == NodeType.Whitespace || node is ArraySpecifier || node is NamedArgumentExpression); |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue