242 строки
10 KiB
Plaintext
242 строки
10 KiB
Plaintext
Note: There is currently no maintainer for NRefactory.
|
|
|
|
If you need a C# parser / compiler frontend, use Microsoft.CodeAnalysis (Roslyn)
|
|
instead.
|
|
|
|
The refactorings in NRefactory have been ported to Roslyn:
|
|
https://github.com/icsharpcode/RefactoringEssentials/
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
Overview of the NRefactory library:
|
|
|
|
Introductory documentation:
|
|
http://www.codeproject.com/Articles/408663/Using-NRefactory-for-analyzing-Csharp-code
|
|
|
|
How to download:
|
|
- Binaries are provided as a NuGet package (http://nuget.org/packages/ICSharpCode.NRefactory)
|
|
- Sourcecode is available on GitHub (https://github.com/icsharpcode/NRefactory)
|
|
|
|
How to compile:
|
|
1. Get Mono.Cecil 0.9.6
|
|
Get Cecil from https://github.com/jbevain/cecil ('git clone git://github.com/jbevain/cecil.git')
|
|
or download Cecil from https://github.com/jbevain/cecil/ and unzip it into a directory named "cecil"
|
|
next to the directory containing NRefactory.
|
|
2. If you need the IKVM binding get it from https://github.com/mono/ikvm-fork and put it next to the NRefactory directory
|
|
like Mono.Cecil - name it "ikvm".
|
|
3. Open NRefactory.sln in your favorite .NET IDE and compile.
|
|
|
|
Features:
|
|
- C# Parser
|
|
- Abstract Syntax Tree with pattern-matching support
|
|
- Semantic Analysis for C# (supports C# 5.0)
|
|
- Code Completion for C#
|
|
- Pretty Printer for C#
|
|
- Lots of C# refactorings
|
|
|
|
Non-Features:
|
|
- C# 6 is not supported.
|
|
- VB support is not implemented.
|
|
- NRefactory cannot generate IL code -- it's a compiler frontend, not a full compiler
|
|
|
|
Dependencies:
|
|
.NET 4.0
|
|
Mono.Cecil 0.9.6
|
|
NRefactory contains a modified copy of mcs (Mono's C# compiler) for the C# parser.
|
|
|
|
|
|
Namespace overview:
|
|
|
|
ICSharpCode.NRefactory assembly
|
|
ICSharpCode.NRefactory.Editor:
|
|
Interfaces that abstract from the text editor control used.
|
|
Maybe future AvalonEdit versions will directly implement these interfaces, but you could also write adapters for other editors.
|
|
|
|
ICSharpCode.NRefactory.TypeSystem:
|
|
Contains a language-independent representation of the .NET type system.
|
|
The type system is divided into two portions: unresolved and resolved type systems.
|
|
|
|
ICSharpCode.NRefactory.TypeSystem.Implementation:
|
|
Contains default implementations for the type system interfaces.
|
|
|
|
ICSharpCode.NRefactory.Semantics:
|
|
Contains classes (ResolveResults) used to represent the semantics of a language element.
|
|
ResolveResults can have child results, thus forming semantic trees.
|
|
|
|
ICSharpCode.NRefactory.Documentation:
|
|
Classes for working with .xml documentation files.
|
|
See "doc/XML Documentation.html" for details.
|
|
|
|
ICSharpCode.NRefactory.PatternMatching:
|
|
Provides classes for pattern matching over the C# and VB ASTs.
|
|
See "doc/Pattern Matching.html" for details.
|
|
|
|
ICSharpCode.NRefactory.Util:
|
|
Various helper classes.
|
|
|
|
|
|
ICSharpCode.NRefactory.CSharp assembly
|
|
ICSharpCode.NRefactory.CSharp:
|
|
Abstract Syntax Tree for C#
|
|
|
|
ICSharpCode.NRefactory.CSharp.Completion:
|
|
Code completion (IntelliSense) for C#
|
|
|
|
ICSharpCode.NRefactory.CSharp.Resolver:
|
|
Semantic analysis for C# (resolving the meaning of expressions)
|
|
|
|
ICSharpCode.NRefactory.CSharp.Analysis:
|
|
Semantic analysis for C# (additional analysis functionality)
|
|
|
|
ICSharpCode.NRefactory.CSharp.TypeSystem:
|
|
Contains type system implementations specific to C#.
|
|
|
|
ICSharpCode.NRefactory.CSharp.Refactoring:
|
|
Infrastructure for refactorings; and several built-in refactorings.
|
|
|
|
ICSharpCode.NRefactory.VB assembly
|
|
ICSharpCode.NRefactory.VB:
|
|
Abstract Syntax Tree for VB
|
|
|
|
ICSharpCode.NRefactory.Xml assembly
|
|
ICSharpCode.NRefactory.Xml:
|
|
Error-tolerant XML parser. Supports incremental parsing.
|
|
When tags don't match correctly, the parser uses a heuristic to guess the parse tree.
|
|
The heuristic tries to minimize the edit distance from the erroneous document to
|
|
the fixed document, and it also considers the indentation.
|
|
|
|
|
|
|
|
Null-Object pattern:
|
|
The NRefactory library makes extensive use of the null object pattern.
|
|
As a result, NullReferenceExceptions should be very rare when working with this library.
|
|
In the type system, both ITypeReference and IType use SpecialType.UnknownType to represent
|
|
unknown types.
|
|
Unless the XML documentation says otherwise, no method or property returning a ITypeReference
|
|
or IType will return null.
|
|
|
|
Note that the null object pattern is not used for ITypeDefinition:
|
|
IProjectContent.GetClass() returns null when a type is not found. Take care to abort your
|
|
operation or substitute UnknownType instead of passing the null to code expecting an IType.
|
|
|
|
The pattern also extends to the C# resolver, which always produces a ResolveResult, even in
|
|
error cases. Use ResolveResult.IsError to detect resolver errors.
|
|
Also note that many resolver errors still have a meaningful type attached, this allows code
|
|
completion to work in the presence of minor semantic errors.
|
|
|
|
The C# AST makes use of special null nodes when accessing the getter of an AST property and no
|
|
child node with that role exists. Check the IsNull property to test whether a node is a null node.
|
|
Null nodes are not considered to be part of the AST (e.g. they don't have a parent).
|
|
|
|
FAQ:
|
|
Q: What is the difference between NRefactory and Roslyn?
|
|
- NRefactory is ready and stable, Roslyn is only a CTP at this point of time.
|
|
- NRefactory does not have VB support.
|
|
- NRefactory cannot compile code to IL; it's not a full compiler, just a frontend.
|
|
- NRefactory C# AST is mutable and supports pattern matching; Roslyn is immutable and does not have built-in pattern matching.
|
|
|
|
Q: What is the difference between types and type definitions?
|
|
|
|
A: Basically, a type (IType) is any type in the .NET type system:
|
|
- an array (ArrayType)
|
|
- a pointer (PointerType)
|
|
- a managed reference (ByReferenceType)
|
|
- a parameterized type (ParameterizedType, e.g. List<int>)
|
|
- a type parameter (ITypeParameter, e.g. T)
|
|
- or a type definition (ITypeDefiniton)
|
|
|
|
Type definitions are only classes, structs, enums and delegates.
|
|
Every type definition is a type, but not every type is a type definition.
|
|
NRefactory's ITypeDefinition derives from IType, so you can directly use any type definition
|
|
as a type.
|
|
In the other direction, you could try to cast a type to ITypeDefinition, or you can call the
|
|
GetDefinition() method. The GetDefinition() method will also return the underlying
|
|
ITypeDefinition if given a parameterized type, so "List<int>".GetDefinition() is "List<T>".
|
|
|
|
|
|
Q: What is the difference between types and type references?
|
|
I've seen lots of duplicated classes (ArrayType vs. ArrayTypeReference, etc.)
|
|
|
|
A: If you've previously used the .NET Reflection API, the concept of type references will be new
|
|
to you.
|
|
|
|
NRefactory has the concept of the "unresolved type system": every assembly/project is stored
|
|
in unresolved form.
|
|
It is possible to load some source code into a project which contains the type reference
|
|
"int[]" without having to load mscorlib into NRefactory.
|
|
So inside the entities stored for the project, the array type is only referenced using an
|
|
ITypeReference.
|
|
This interface has a single method:
|
|
interface ITypeReference {
|
|
IType Resolve(ITypeResolutionContext context);
|
|
}
|
|
By calling the Resolve()-method, you will get back the actual ArrayType.
|
|
|
|
Not only type references are split up this way; pretty much every class in the type system
|
|
comes in unresolved and resolved forms.
|
|
|
|
|
|
Q: What is a compilation (ICompilation)?
|
|
|
|
A: A compilation serves as the root object of the resolved type system.
|
|
It consists of a main assembly and multiple referenced assemblies,
|
|
and may also contain additional information like compiler options.
|
|
|
|
|
|
Q: What's in an ITypeResolveContext?
|
|
|
|
A: An ITypeResolveContext is an environment for looking up namespaces and types.
|
|
It consists of the current compilation, the current type definition,
|
|
and language-specific implementations may add additional information (e.g. the list of usings).
|
|
|
|
Generally, you cannot resolve a type reference without knowing what kind of context is expected.
|
|
|
|
|
|
Q: How do I get the IType or ITypeReference for a primitive type such as string or int?
|
|
|
|
A: To get an IType for a primitive type, use:
|
|
compilation.FindType(KnownTypeCode.Int32)
|
|
|
|
To get an ITypeReference, use:
|
|
KnownTypeReference.Int32
|
|
|
|
It is also possible to use a System.Type for retrieving a type:
|
|
compilation.FindType(typeof(int))
|
|
or
|
|
typeof(int).ToTypeReference().
|
|
|
|
|
|
Q: Is it thread-safe?
|
|
|
|
A: This question is a bit difficult to answer.
|
|
NRefactory was designed to be usable in a multi-threaded IDE.
|
|
But of course, this does not mean that everything is thread-safe.
|
|
|
|
First off, there's no hidden static state, so any two operations working on independent data
|
|
can be executed concurrently.
|
|
[Actually, sometimes static state is used for caches, but those uses are thread-safe.]
|
|
TODO: what about the C# parser? gmcs is full of static state...
|
|
-> this is being worked on; for the time being, NRefactory uses a global lock during parsing;
|
|
so it's thread-safe but slow.
|
|
|
|
Some instance methods may use hidden instance state, so it is not safe to e.g. use an instance
|
|
of the CSharp.Resolver.TypeInference class concurrently.
|
|
Instead, you need to create an instance on every thread.
|
|
|
|
The type system itself is thread-safe. Both the unresolved and the resolved type systems are
|
|
immutable.
|
|
|
|
When you add to an IProjectContent, the existing project content isn't modified,
|
|
but a new project content is created instead. All implementations of the type system interfaces
|
|
are either immutable or freezable.
|
|
|
|
And on the resolved type system side, ICompilation is immutable as well.
|
|
Internally, the resolved type system will resolve elements only on demand, but this is done
|
|
in a thread-safe manner.
|
|
|
|
|
|
Q: What format do the .ToString() methods use?
|
|
|
|
A: They don't use any particular format. They're merely intended as a debugging aid.
|
|
Currently .ToString() usually matches .ReflectionName, but that may change in the future.
|