This commit is contained in:
de4dot 2016-04-25 07:06:45 +02:00
Коммит ba8481653b
2103 изменённых файлов: 288120 добавлений и 0 удалений

4
.gitattributes поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
* text=auto
*.cs text diff=csharp
*.sln text eol=crlf
*.csproj text eol=crlf

12
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,12 @@
.vs/
bin/
obj/
*.suo
*.user
_ReSharper*/
*.ReSharper
*.patch
/packages
*.ide/
*.tmp_proj
project.lock.json

15
.gitmodules поставляемый Normal file
Просмотреть файл

@ -0,0 +1,15 @@
[submodule "Libraries/dnlib"]
path = Libraries/dnlib
url = https://github.com/0xd4d/dnlib.git
[submodule "Plugins/ILSpy.Decompiler/NRefactory"]
path = Plugins/ILSpy.Decompiler/NRefactory
url = https://github.com/0xd4d/nrefactory.git
[submodule "Libraries/ICSharpCode.AvalonEdit"]
path = Libraries/ICSharpCode.AvalonEdit
url = https://github.com/0xd4d/avalonedit.git
[submodule "Libraries/ICSharpCode.TreeView"]
path = Libraries/ICSharpCode.TreeView
url = git@bitbucket.org:0xd4d/icsharpcode.treeview.git
[submodule "Plugins/ILSpy.Decompiler/ICSharpCode.Decompiler"]
path = Plugins/ILSpy.Decompiler/ICSharpCode.Decompiler
url = git@bitbucket.org:0xd4d/icsharpcode.decompiler.git

@ -0,0 +1 @@
Subproject commit f5647dd96cdf2f15d0dcf487cd267d2c24ec84fb

@ -0,0 +1 @@
Subproject commit d1e06e0c3d03cab3a28f2532e920475a61241923

1
Libraries/dnlib Submodule

@ -0,0 +1 @@
Subproject commit f77429ddcbe7594cf346fc17638a7f2a327aa55f

31
Licenses/CREDITS.txt Normal file
Просмотреть файл

@ -0,0 +1,31 @@
dnSpy credits:
0xd4d
Ki
ILSpy decompiler and analyzer credits:
Daniel Grunwald
David Srbecky
Ed Harvey
Siegfried Pammer
Artur Zgodzinski
Eusebiu Marcu
Pent Ploompuu
Ki
0xd4d
Translators:
Chinese Simplified
Ulysses Wu
YanJun Sun
iFish
SquallATF
linkinshi
Russian
Igor
Konctantin

674
Licenses/GPLv3.txt Normal file
Просмотреть файл

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

18
Licenses/LICENSE.txt Normal file
Просмотреть файл

@ -0,0 +1,18 @@
dnSpy is released under the GPLv3 license, see GPLv3.txt for more information.
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.

Просмотреть файл

@ -0,0 +1,73 @@
Original licenses of code or other libraries used by dnSpy. Some or all of them have been modified and are now released under the GPLv3 license, like dnSpy. The following license info is the original licenses.
***********************************************************************************
dnlib:
Copyright (C) 2012-2016 de4dot@gmail.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.
***********************************************************************************
BAML Decompiler:
Copyright (c) 2015 Ki
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.
***********************************************************************************
Analyzer:
AvalonEdit:
ICSharpCode.Decompiler:
ICSharpCode.NRefactory:
ICSharpCode.TreeView:
Copyright (c) 2011-2014 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.

Просмотреть файл

@ -0,0 +1,168 @@
using System;
using System.ComponentModel.Composition;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using dnlib.DotNet;
using dnSpy.Contracts.Controls;
using dnSpy.Contracts.Files.Tabs.TextEditor;
using dnSpy.Contracts.Menus;
using dnSpy.Contracts.Plugin;
using dnSpy.Shared.Menus;
// Adds menu items to the text editor context menu
// If you have many similar commands, it's better to create a base class and derive from
// MenuItemBase<TContext> instead of MenuItemBase, see TreeViewCtxMenus.cs for an example.
namespace Example1.Plugin {
static class Constants {
//TODO: Use your own guids
// The first number is the order of the group, and the guid is the guid of the group,
// see eg. dnSpy.Contracts.Menus.MenuConstants.GROUP_CTX_CODE_HEX etc
public const string GROUP_TEXTEDITOR = "20000,3567EC95-E68E-44CE-932C-98A686FDCACF";
public const string GROUP_TREEVIEW = "20000,77ACC18E-D8EB-483B-8D93-3581574B8891";
}
// This gets loaded by dnSpy and is used to add the Ctrl+Alt+Q command
[ExportAutoLoaded]
sealed class CommandLoader : IAutoLoaded {
static readonly RoutedCommand Option1Command = new RoutedCommand("Option1Command", typeof(CommandLoader));
[ImportingConstructor]
CommandLoader(IWpfCommandManager wpfCommandManager, MySettings mySettings) {
var cmds = wpfCommandManager.GetCommands(CommandConstants.GUID_TEXTEDITOR_UICONTEXT);
// This command will be added to all text editors
cmds.Add(Option1Command,
(s, e) => mySettings.BoolOption1 = !mySettings.BoolOption1,
(s, e) => e.CanExecute = true,
ModifierKeys.Control | ModifierKeys.Alt, Key.Q);
}
}
[ExportMenuItem(Header = "Option 1", InputGestureText = "Ctrl+Alt+Q", Group = Constants.GROUP_TEXTEDITOR, Order = 0)]
sealed class TextEditorCommand1 : MenuItemBase {
readonly MySettings mySettings;
[ImportingConstructor]
TextEditorCommand1(MySettings mySettings) {
this.mySettings = mySettings;
}
public override bool IsChecked(IMenuItemContext context) {
return mySettings.BoolOption1;
}
public override void Execute(IMenuItemContext context) {
// Toggle value
mySettings.BoolOption1 = !mySettings.BoolOption1;
}
public override bool IsVisible(IMenuItemContext context) {
// Only show this in the text editor
return context.CreatorObject.Guid == new Guid(MenuConstants.GUIDOBJ_TEXTEDITORCONTROL_GUID);
}
}
[ExportMenuItem(Header = "Option 2", Group = Constants.GROUP_TEXTEDITOR, Order = 10)]
sealed class TextEditorCommand2 : MenuItemBase {
readonly MySettings mySettings;
[ImportingConstructor]
TextEditorCommand2(MySettings mySettings) {
this.mySettings = mySettings;
}
public override bool IsChecked(IMenuItemContext context) {
return mySettings.BoolOption2;
}
public override void Execute(IMenuItemContext context) {
// Toggle value
mySettings.BoolOption2 = !mySettings.BoolOption2;
}
public override bool IsVisible(IMenuItemContext context) {
// Only show this in the text editor
return context.CreatorObject.Guid == new Guid(MenuConstants.GUIDOBJ_TEXTEDITORCONTROL_GUID);
}
}
[ExportMenuItem(Group = Constants.GROUP_TEXTEDITOR, Order = 20)]
sealed class TextEditorCommand3 : MenuItemBase {
public override void Execute(IMenuItemContext context) {
var md = GetTokenObj(context);
if (md != null) {
try {
Clipboard.SetText(string.Format("{0:X8}", md.MDToken.Raw));
}
catch (ExternalException) { }
}
}
public override string GetHeader(IMenuItemContext context) {
var md = GetTokenObj(context);
if (md == null)
return "Copy token";
return string.Format("Copy token {0:X8}", md.MDToken.Raw);
}
IMDTokenProvider GetTokenObj(IMenuItemContext context) {
// Only show this in the text editor
if (context.CreatorObject.Guid != new Guid(MenuConstants.GUIDOBJ_TEXTEDITORCONTROL_GUID))
return null;
// All references in the text editor are stored in CodeReferences
var codeRef = context.Find<CodeReference>();
if (codeRef == null)
return null;
return codeRef.Reference as IMDTokenProvider;
}
public override bool IsVisible(IMenuItemContext context) {
// Only show this in the text editor
return context.CreatorObject.Guid == new Guid(MenuConstants.GUIDOBJ_TEXTEDITORCONTROL_GUID);
}
public override bool IsEnabled(IMenuItemContext context) {
return GetTokenObj(context) != null;
}
}
[ExportMenuItem(Group = Constants.GROUP_TEXTEDITOR, Order = 30)]
sealed class TextEditorCommand4 : MenuItemBase {
public override void Execute(IMenuItemContext context) {
var uiContext = GetUIContext(context);
if (uiContext != null) {
try {
Clipboard.SetText(string.Format("Line,col: {0},{1}", uiContext.Location.Line, uiContext.Location.Column));
}
catch (ExternalException) { }
}
}
public override string GetHeader(IMenuItemContext context) {
var uiContext = GetUIContext(context);
if (uiContext == null)
return "Copy line and column";
return string.Format("Copy line,col {0},{1}", uiContext.Location.Line, uiContext.Location.Column);
}
ITextEditorUIContext GetUIContext(IMenuItemContext context) {
// Only show this in the text editor
if (context.CreatorObject.Guid != new Guid(MenuConstants.GUIDOBJ_TEXTEDITORCONTROL_GUID))
return null;
return context.Find<ITextEditorUIContext>();
}
public override bool IsVisible(IMenuItemContext context) {
// Only show this in the text editor
return context.CreatorObject.Guid == new Guid(MenuConstants.GUIDOBJ_TEXTEDITORCONTROL_GUID);
}
public override bool IsEnabled(IMenuItemContext context) {
return GetUIContext(context) != null;
}
}
}

Просмотреть файл

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B24AAB0F-CA85-4D85-8B46-10D634896E2A}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Example1.Plugin</RootNamespace>
<AssemblyName>Example1.Plugin</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>1685</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>1685</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Xaml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="CodeCtxMenus.cs" />
<Compile Include="MainMenuCommands.cs" />
<Compile Include="MiscOptions.cs" />
<Compile Include="MySettings.cs" />
<Compile Include="MySettingsControl.xaml.cs">
<DependentUpon>MySettingsControl.xaml</DependentUpon>
</Compile>
<Compile Include="MySettingsTab.cs" />
<Compile Include="Plugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ToolBarCommands.cs" />
<Compile Include="TreeViewCtxMenus.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Libraries\dnlib\src\dnlib.csproj">
<Project>{fdfc1237-143f-4919-8318-4926901f4639}</Project>
<Name>dnlib</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\dnSpy\dnSpy.Contracts\dnSpy.Contracts.csproj">
<Project>{9b234472-0e22-428c-9345-c8d9ee5e06af}</Project>
<Name>dnSpy.Contracts</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\dnSpy\dnSpy.Shared\dnSpy.Shared.csproj">
<Project>{7e7c2cf8-2057-4eaa-9dad-ab3022cf4037}</Project>
<Name>dnSpy.Shared</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="README.md" />
</ItemGroup>
<ItemGroup>
<Page Include="MySettingsControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Resource Include="Images\Assembly.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Двоичные данные
Plugins/Examples/Example1.Plugin/Images/Assembly.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 153 B

Просмотреть файл

@ -0,0 +1,61 @@
using dnSpy.Contracts.Menus;
using dnSpy.Shared.Menus;
// Adds a new "_Plugin" menu and several commands.
// Adds a command to the View menu
namespace Example1.Plugin {
static class MainMenuConstants {
//TODO: Use your own guids
public const string APP_MENU_PLUGIN = "4E6829A6-AEA0-4803-9344-D19BF0A74DA1";
public const string GROUP_PLUGIN_MENU1 = "0,73BEBC37-387A-4004-8076-A1A90A17611B";
public const string GROUP_PLUGIN_MENU2 = "10,C21B8B99-A2E4-474F-B4BC-4CF348ECBD0A";
}
// Create the Plugin menu and place it right after the Debug menu
[ExportMenu(OwnerGuid = MenuConstants.APP_MENU_GUID, Guid = MainMenuConstants.APP_MENU_PLUGIN, Order = MenuConstants.ORDER_APP_MENU_DEBUG + 0.1, Header = "_Plugin")]
sealed class DebugMenu : IMenu {
}
[ExportMenuItem(OwnerGuid = MainMenuConstants.APP_MENU_PLUGIN, Header = "Command #1", Group = MainMenuConstants.GROUP_PLUGIN_MENU1, Order = 0)]
sealed class PluginCommand1 : MenuItemBase {
public override void Execute(IMenuItemContext context) {
dnSpy.Shared.App.MsgBox.Instance.Show("Command #1");
}
}
[ExportMenuItem(OwnerGuid = MainMenuConstants.APP_MENU_PLUGIN, Header = "Command #2", Group = MainMenuConstants.GROUP_PLUGIN_MENU1, Order = 10)]
sealed class PluginCommand2 : MenuItemBase {
public override void Execute(IMenuItemContext context) {
dnSpy.Shared.App.MsgBox.Instance.Show("Command #2");
}
}
[ExportMenuItem(OwnerGuid = MainMenuConstants.APP_MENU_PLUGIN, Header = "Command #3", Group = MainMenuConstants.GROUP_PLUGIN_MENU2, Order = 0)]
sealed class PluginCommand3 : MenuItemBase {
public override void Execute(IMenuItemContext context) {
dnSpy.Shared.App.MsgBox.Instance.Show("Command #3");
}
}
[ExportMenuItem(OwnerGuid = MainMenuConstants.APP_MENU_PLUGIN, Header = "Command #4", Group = MainMenuConstants.GROUP_PLUGIN_MENU2, Order = 10)]
sealed class PluginCommand4 : MenuItemBase {
public override void Execute(IMenuItemContext context) {
dnSpy.Shared.App.MsgBox.Instance.Show("Command #4");
}
}
[ExportMenuItem(OwnerGuid = MainMenuConstants.APP_MENU_PLUGIN, Header = "Command #5", Group = MainMenuConstants.GROUP_PLUGIN_MENU2, Order = 20)]
sealed class PluginCommand5 : MenuItemBase {
public override void Execute(IMenuItemContext context) {
dnSpy.Shared.App.MsgBox.Instance.Show("Command #5");
}
}
[ExportMenuItem(OwnerGuid = MenuConstants.APP_MENU_VIEW_GUID, Header = "Command #1", Group = MenuConstants.GROUP_APP_MENU_VIEW_WINDOWS, Order = 1000)]
sealed class ViewCommand1 : MenuItemBase {
public override void Execute(IMenuItemContext context) {
dnSpy.Shared.App.MsgBox.Instance.Show("View Command #1");
}
}
}

Просмотреть файл

@ -0,0 +1,37 @@
using System.Collections.Generic;
using System.ComponentModel.Composition;
using dnSpy.Contracts.Settings.Dialog;
using dnSpy.Shared.Settings.Dialog;
// This adds an option to the "Misc" tab. If you don't have enough options to warrant a new tab,
// this can be used to add a few of them to the Misc tab.
namespace Example1.Plugin {
// This class adds a new option to the Misc tab
[ExportSimpleAppOptionCreator(Guid = AppSettingsConstants.GUID_DYNTAB_MISC)]
sealed class MiscOptionCreator : ISimpleAppOptionCreator {
readonly MySettings mySettings;
// This constructor gets the single MySettingsImpl instance exported by MySettingsImpl in MySettings.cs
[ImportingConstructor]
MiscOptionCreator(MySettings mySettings) {
this.mySettings = mySettings;
}
public IEnumerable<ISimpleAppOption> Create() {
// Create a textbox showing our StringOption3 value. Classes that can be used:
// SimpleAppOptionCheckBox
// SimpleAppOptionButton
// SimpleAppOptionTextBox
// SimpleAppOptionUserContent<T>
yield return new SimpleAppOptionTextBox(mySettings.StringOption3, (saveSettings, appRefreshSettings, newValue) => {
// this is false if the user canceled
if (saveSettings)
mySettings.StringOption3 = newValue;
}) {
Order = AppSettingsConstants.ORDER_MISC_USENEWRENDERER + 1,
Text = "Some String",
};
}
}
}

Просмотреть файл

@ -0,0 +1,100 @@
using System;
using System.ComponentModel.Composition;
using dnSpy.Contracts.Settings;
using dnSpy.Shared.MVVM;
// Reads and writes the plugin settings
namespace Example1.Plugin {
class MySettings : ViewModelBase {
// overridden by the global settings class. Hooking the PropertyChanged event could be used too
protected virtual void OnModified() {
}
public bool BoolOption1 {
get { return boolOption1; }
set {
if (boolOption1 != value) {
boolOption1 = value;
OnPropertyChanged("BoolOption1");
OnModified();
}
}
}
bool boolOption1 = true;
public bool BoolOption2 {
get { return boolOption2; }
set {
if (boolOption2 != value) {
boolOption2 = value;
OnPropertyChanged("BoolOption2");
OnModified();
}
}
}
bool boolOption2 = false;
public string StringOption3 {
get { return stringOption3; }
set {
if (stringOption3 != value) {
stringOption3 = value;
OnPropertyChanged("StringOption3");
OnModified();
}
}
}
string stringOption3 = string.Empty;
public MySettings Clone() {
return CopyTo(new MySettings());
}
public MySettings CopyTo(MySettings other) {
other.BoolOption1 = this.BoolOption1;
other.BoolOption2 = this.BoolOption2;
other.StringOption3 = this.StringOption3;
return other;
}
}
// Export this class so it can be imported by other classes in this plugin
[Export(typeof(MySettings))]
sealed class MySettingsImpl : MySettings {
//TODO: Use your own guid
static readonly Guid SETTINGS_GUID = new Guid("A308405D-0DF5-4C56-8B1E-8CE7BA6365E1");
readonly ISettingsManager settingsManager;
// Tell MEF to pass in the required ISettingsManager instance exported by dnSpy
[ImportingConstructor]
MySettingsImpl(ISettingsManager settingsManager) {
this.settingsManager = settingsManager;
// Read the settings from the file or use the default values if our settings haven't
// been saved to it yet.
this.disableSave = true;
var sect = settingsManager.GetOrCreateSection(SETTINGS_GUID);
BoolOption1 = sect.Attribute<bool?>("BoolOption1") ?? BoolOption1;
BoolOption2 = sect.Attribute<bool?>("BoolOption2") ?? BoolOption2;
StringOption3 = sect.Attribute<string>("StringOption3") ?? StringOption3;
this.disableSave = false;
}
readonly bool disableSave;
// Called by the base class
protected override void OnModified() {
if (disableSave)
return;
// Save the settings
var sect = settingsManager.RecreateSection(SETTINGS_GUID);
sect.Attribute("BoolOption1", BoolOption1);
sect.Attribute("BoolOption2", BoolOption2);
sect.Attribute("StringOption3", StringOption3);
}
}
}

Просмотреть файл

@ -0,0 +1,13 @@
<UserControl x:Class="Example1.Plugin.MySettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Example1.Plugin"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
<CheckBox Content="Option #1" IsChecked="{Binding BoolOption1}" />
<CheckBox Content="Option #2" IsChecked="{Binding BoolOption2}" />
</StackPanel>
</UserControl>

Просмотреть файл

@ -0,0 +1,9 @@
using System.Windows.Controls;
namespace Example1.Plugin {
public partial class MySettingsControl : UserControl {
public MySettingsControl() {
InitializeComponent();
}
}
}

Просмотреть файл

@ -0,0 +1,65 @@
using System.Collections.Generic;
using System.ComponentModel.Composition;
using dnSpy.Contracts.Settings.Dialog;
// Adds an options dialog box tab showing settings saved in MySettings
namespace Example1.Plugin {
// This instance gets called by dnSpy to create the tab each time the user opens the options dialog
[Export(typeof(IAppSettingsTabCreator))] // Tell MEF we're exporting this instance
sealed class MyAppSettingsTabCreator : IAppSettingsTabCreator {
readonly MySettings mySettings;
// This constructor gets the single MySettingsImpl instance exported by MySettingsImpl in MySettings.cs
[ImportingConstructor]
MyAppSettingsTabCreator(MySettings mySettings) {
this.mySettings = mySettings;
}
public IEnumerable<IAppSettingsTab> Create() {
// We only create one tab
yield return new MyAppSettingsTab(mySettings);
}
}
sealed class MyAppSettingsTab : IAppSettingsTab {
// The order of the tab, let's place it after the debugger tab
public double Order {
get { return AppSettingsConstants.ORDER_DEBUGGER_TAB_DISPLAY + 0.1; }
}
public string Title {
get { return "MySettings"; }
}
// This is the content shown in the tab. It should be a WPF object (eg. a UserControl) or a
// ViewModel with a DataTemplate defined in a resource dictionary.
public object UIObject {
get {
if (uiObject == null) {
uiObject = new MySettingsControl();
uiObject.DataContext = newSettings;
}
return uiObject;
}
}
MySettingsControl uiObject;
readonly MySettings globalSettings;
readonly MySettings newSettings;
public MyAppSettingsTab(MySettings mySettings) {
this.globalSettings = mySettings;
this.newSettings = mySettings.Clone();
}
public void OnClosed(bool saveSettings, IAppRefreshSettings appRefreshSettings) {
// Check if user canceled
if (!saveSettings)
return;
// OK was pressed, save the settings
newSettings.CopyTo(globalSettings);
}
}
}

Просмотреть файл

@ -0,0 +1,28 @@
using System.Collections.Generic;
using dnSpy.Contracts.Plugin;
// Each plugin should export one class implementing IPlugin
namespace Example1.Plugin {
[ExportPlugin]
sealed class Plugin : IPlugin {
public IEnumerable<string> MergedResourceDictionaries {
get {
// We don't have any extra resource dictionaries
yield break;
}
}
public PluginInfo PluginInfo {
get {
return new PluginInfo {
ShortDescription = "Example1 plugin",
};
}
}
public void OnEvent(PluginEvent @event, object obj) {
// We don't care about any events
}
}
}

Просмотреть файл

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Example1.Plugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Example1.Plugin")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b24aab0f-ca85-4d85-8b46-10d634896e2a")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,10 @@
This plugin shows how to do the basic things. It:
- Reads and writes settings (MySettings.cs)
- Adds a tab to the options dialog box showing some of the options (MySettingsTab.cs)
- Adds a textbox to the Misc tab (MiscOptions.cs)
- Adds options to the text editor's context menu and a Ctrl+Alt+Q keyboard shortcut (CodeCtxMenus.cs)
- Adds treeview context menus (TreeViewCtxMenus.cs)
- Adds a "_Plugin" menu and menu items and a View menu command (MainMenuCommands.cs)
- Adds a button and a combobox to the toolbar (ToolBarCommands.cs)

Просмотреть файл

@ -0,0 +1,42 @@
using System.Windows;
using System.Windows.Controls;
using dnSpy.Contracts.ToolBars;
using dnSpy.Shared.ToolBars;
// Adds a toolbar button and combobox between the asm editor and debugger toolbar items
namespace Example1.Plugin {
static class TBConstants {
//TODO: Use your own guid
// Place it between the asm editor and debugger, see dnSpy.Contracts.ToolBars.ToolBarConstants:
// GROUP_APP_TB_MAIN_ASMED_UNDO = "4000,6351DBFC-6D8D-4847-B3F2-BC376912B9C2"
// GROUP_APP_TB_MAIN_DEBUG = "5000,A0AFBC69-B6D1-46FE-96C8-EC380DEBE9AA"
public const string GROUP_APP_TB_PLUGIN = "4500,AF461C50-6E91-41B8-9771-0BAE9B77BC69";
}
[ExportToolBarButton(Icon = "Assembly", ToolTip = "Click Me", Group = TBConstants.GROUP_APP_TB_PLUGIN, Order = 0)]
sealed class TBCommand1 : ToolBarButtonBase {
public override void Execute(IToolBarItemContext context) {
dnSpy.Shared.App.MsgBox.Instance.Show("Command #1");
}
}
[ExportToolBarObject(Group = TBConstants.GROUP_APP_TB_PLUGIN, Order = 10)]
sealed class TBCommand2 : ToolBarObjectBase {
readonly ComboBox comboBox;
TBCommand2() {
this.comboBox = new ComboBox();
this.comboBox.Width = 100;
this.comboBox.Items.Add("Item #1");
this.comboBox.Items.Add("Item #2");
this.comboBox.Items.Add("Item #3");
this.comboBox.Items.Add("Item #4");
this.comboBox.SelectedIndex = 1;
}
public override object GetUIObject(IToolBarItemContext context, IInputElement commandTarget) {
return comboBox;
}
}
}

Просмотреть файл

@ -0,0 +1,160 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using dnlib.DotNet.Emit;
using dnSpy.Contracts.Files.TreeView;
using dnSpy.Contracts.Menus;
using dnSpy.Contracts.TreeView;
using dnSpy.Shared.Menus;
// Adds a couple of commands to the file treeview context menu.
// Since there are several commands using the same state, MenuItemBase<TContext> is used
// as the base class so the context is created once and shared by all commands.
namespace Example1.Plugin {
sealed class TVContext {
public readonly bool SomeValue;
public readonly IFileTreeNodeData[] Nodes;
public TVContext(bool someValue, IEnumerable<IFileTreeNodeData> nodes) {
this.SomeValue = someValue;
this.Nodes = nodes.ToArray();
}
}
abstract class TVCtxMenuCommand : MenuItemBase<TVContext> {
protected sealed override object CachedContextKey {
get { return ContextKey; }
}
static readonly object ContextKey = new object();
protected sealed override TVContext CreateContext(IMenuItemContext context) {
// Make sure it's the file treeview
if (context.CreatorObject.Guid != new Guid(MenuConstants.GUIDOBJ_FILES_TREEVIEW_GUID))
return null;
// Extract the data needed by the context
var nodes = context.Find<ITreeNodeData[]>();
if (nodes == null)
return null;
var newNodes = nodes.OfType<IFileTreeNodeData>();
bool someValue = true;
return new TVContext(someValue, newNodes);
}
}
[ExportMenuItem(Header = "Command #1", Group = Constants.GROUP_TREEVIEW, Order = 0)]
sealed class TVCommand1 : TVCtxMenuCommand {
public override void Execute(TVContext context) {
dnSpy.Shared.App.MsgBox.Instance.Show("Command #1");
}
public override bool IsEnabled(TVContext context) {
return context.Nodes.Length > 1;
}
}
[ExportMenuItem(Header = "Command #2", Group = Constants.GROUP_TREEVIEW, Order = 10)]
sealed class TVCommand2 : TVCtxMenuCommand {
public override void Execute(TVContext context) {
dnSpy.Shared.App.MsgBox.Instance.Show("Command #2");
}
public override bool IsVisible(TVContext context) {
return context.Nodes.Length > 0;
}
}
[ExportMenuItem(Header = "Command #3", Group = Constants.GROUP_TREEVIEW, Order = 20)]
sealed class TVCommand3 : TVCtxMenuCommand {
public override void Execute(TVContext context) {
int secretNum = new Random().Next() % 10;
dnSpy.Shared.App.MsgBox.Instance.Ask<int?>("Number", null, "Guess a number", null, s => {
int num;
if (string.IsNullOrWhiteSpace(s))
return "Enter a number";
if (!int.TryParse(s, out num))
return "Not an integer";
if (num == 42)
return "Nope!";
if (num != secretNum)
return "WRONG!!!";
return string.Empty;
});
}
}
[ExportMenuItem(Header = "Command #4", Group = Constants.GROUP_TREEVIEW, Order = 30)]
sealed class TVCommand4 : TVCtxMenuCommand {
public override void Execute(TVContext context) {
dnSpy.Shared.App.MsgBox.Instance.Show("Command #4");
}
public override bool IsEnabled(TVContext context) {
return context.Nodes.Length == 1 &&
context.Nodes[0] is IModuleFileNode;
}
}
[ExportMenuItem(Group = Constants.GROUP_TREEVIEW, Order = 40)]
sealed class TVCommand5 : TVCtxMenuCommand {
public override void Execute(TVContext context) {
var node = GetTokenNode(context);
if (node != null) {
try {
Clipboard.SetText(string.Format("{0:X8}", node.Reference.MDToken.Raw));
}
catch (ExternalException) { }
}
}
IMDTokenNode GetTokenNode(TVContext context) {
if (context.Nodes.Length == 0)
return null;
return context.Nodes[0] as IMDTokenNode;
}
public override string GetHeader(TVContext context) {
var node = GetTokenNode(context);
if (node == null)
return string.Empty;
return string.Format("Copy token {0:X8}", node.Reference.MDToken.Raw);
}
public override bool IsVisible(TVContext context) {
return GetTokenNode(context) != null;
}
}
[ExportMenuItem(Header = "Copy Second Instruction", Group = Constants.GROUP_TREEVIEW, Order = 50)]
sealed class TVCommand6 : TVCtxMenuCommand {
public override void Execute(TVContext context) {
var instr = GetSecondInstruction(context);
if (instr != null) {
try {
Clipboard.SetText(string.Format("Second instruction: {0}", instr));
}
catch (ExternalException) { }
}
}
Instruction GetSecondInstruction(TVContext context) {
if (context.Nodes.Length == 0)
return null;
var methNode = context.Nodes[0] as IMethodNode;
if (methNode == null)
return null;
var body = methNode.MethodDef.Body;
if (body == null || body.Instructions.Count < 2)
return null;
return body.Instructions[1];
}
public override bool IsEnabled(TVContext context) {
return GetSecondInstruction(context) != null;
}
}
}

Просмотреть файл

@ -0,0 +1,211 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using dnSpy.Contracts.Files.Tabs;
using dnSpy.Contracts.Files.TreeView;
using dnSpy.Contracts.Settings;
using dnSpy.Shared.MVVM;
// This file adds custom file tab content when the user clicks on our new AssemblyChildNode tree node.
// This node is created by TreeNodeDataCreator.cs.
namespace Example2.Plugin {
[ExportFileTabContentFactory]
sealed class AssemblyChildNodeTabContentFactory : IFileTabContentFactory {
// Called to create a new IFileTabContent. If it's our new tree node, create a new IFileTabContent for it
public IFileTabContent Create(IFileTabContentFactoryContext context) {
if (context.Nodes.Length == 1 && context.Nodes[0] is AssemblyChildNode)
return new AssemblyChildNodeTabContent((AssemblyChildNode)context.Nodes[0]);
return null;
}
//TODO: Use your own guid
static readonly Guid GUID_SerializedContent = new Guid("FC6D2EC8-6FF8-4071-928E-EB07735A6402");
public IFileTabContent Deserialize(Guid guid, ISettingsSection section, IFileTabContentFactoryContext context) {
if (guid == GUID_SerializedContent) {
// Serialize() doesn't add anything extra to 'section', but if it did, you'd have to
// get that info here and return null if the serialized data wasn't found.
var node = context.Nodes.Length == 1 ? context.Nodes[0] as AssemblyChildNode : null;
if (node != null)
return new AssemblyChildNodeTabContent(node);
}
return null;
}
public Guid? Serialize(IFileTabContent content, ISettingsSection section) {
if (content is AssemblyChildNodeTabContent) {
// There's nothing else we need to serialize it, but if there were, use 'section'
// to write the info needed by Deserialize() above.
return GUID_SerializedContent;
}
return null;
}
}
sealed class AssemblyChildNodeTabContent : IFileTabContent {
// Initialized by the owner
public IFileTab FileTab { get; set; }
// Returns all nodes used to generate the content
public IEnumerable<IFileTreeNodeData> Nodes {
get { yield return node; }
}
public string Title {
get { return node.ToString(); }
}
public object ToolTip {
get { return node.ToString(); }
}
readonly AssemblyChildNode node;
public AssemblyChildNodeTabContent(AssemblyChildNode node) {
this.node = node;
}
// Called when the user opens a new tab
public IFileTabContent Clone() {
return new AssemblyChildNodeTabContent(node);
}
// Gets called to create the UI context. It can be shared by any IFileTabContent in this tab.
// Eg. there's only one text editor per tab, shared by all IFileTabContents that need a text
// editor.
public IFileTabUIContext CreateUIContext(IFileTabUIContextLocator locator) {
// This custom view object is shared by all nodes of the same type. If we didn't want it
// to be shared, we could use 'node' or 'this' as the key.
var key = node.GetType();
// var key = node; // uncomment to not share it
// If the UI object has already been created, use it, else create it. The object is
// stored in a weak reference.
return locator.Get(key, () => new AssemblyChildNodeUIContext());
}
public void OnShow(IShowContext ctx) {
// Get the real type, created by CreateUIContext() above.
var uiCtx = (AssemblyChildNodeUIContext)ctx.UIContext;
// You could initialize some stuff, eg. update its DataContext or whatever
uiCtx.Initialize("some input"); // pretend we need to initialize something
}
public void OnHide() {
}
public void OnSelected() {
}
public void OnUnselected() {
}
}
sealed class AssemblyChildNodeUIContext : IFileTabUIContext {
// Initialized by the owner
public IFileTab FileTab { get; set; }
// The element inside UIObject that gets the focus when the tool window should be focused.
// If it's not as easy as calling FocusedElement.Focus() to focus it, you must implement
// dnSpy.Contracts.Controls.IFocusable.
public IInputElement FocusedElement {
get { return content; }
}
// The element in UIObject that gets the scale transform. null can be returned to disable scaling.
public FrameworkElement ScaleElement {
get { return content; }
}
// The UI object shown in the tab. Should be a WPF control (eg. UserControl) or a .NET object
// with a DataTemplate.
public object UIObject {
get { return content; }
}
public void OnHide() {
}
public void OnShow() {
}
readonly ContentPresenter content;
readonly AssemblyChildNodeVM vm;
public AssemblyChildNodeUIContext() {
this.vm = new AssemblyChildNodeVM();
// A ContentPresenter + DataTemplate is used to show the VM, but you could of course use
// a UserControl.
this.content = new ContentPresenter {
Focusable = true,
Content = this.vm,
};
}
sealed class MySerializedData {
public string Value1;
public bool Value2;
public MySerializedData(string value1, bool value2) {
this.Value1 = value1;
this.Value2 = value2;
}
}
// Called to create a value that can be used by Deserialize(). It's read from the settings file.
public object CreateSerialized(ISettingsSection section) {
var value1 = section.Attribute<string>("Value1");
var value2 = section.Attribute<bool?>("Value2");
if (value1 == null || value2 == null)
return null;
return new MySerializedData(value1, value2.Value);
}
// Saves the value returned by Serialize(). It's saved in the settings file.
public void SaveSerialized(ISettingsSection section, object obj) {
var d = obj as MySerializedData;
if (d == null)
return;
section.Attribute("Value1", d.Value1);
section.Attribute("Value2", d.Value2);
}
// Serializes the UI state
public object Serialize() {
// This is where you'd normally serialize the UI state, eg. position etc, but we'll just save random data
return new MySerializedData("Some string", true);
}
// Deserializes the UI state created by Serialize()
public void Deserialize(object obj) {
var d = obj as MySerializedData;
if (d == null)
return;
// Here's where you'd restore the UI state, eg position etc.
}
// Called by AssemblyChildNodeTabContent above to initialize it before it's shown again
public void Initialize(string s) {
// here we could initialize something before it's shown again, eg. initialize the DataContext
}
}
sealed class AssemblyChildNodeVM : ViewModelBase {
public string SomeMessage {
get { return someMessage; }
set {
if (someMessage != value) {
someMessage = value;
OnPropertyChanged("SomeMessage");
}
}
}
string someMessage = "Hello World";
}
}

Просмотреть файл

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4613C8A1-28DC-4586-9F9B-D201864CFE1A}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Example2.Plugin</RootNamespace>
<AssemblyName>Example2.Plugin</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>1685</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>1685</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Xaml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyChildNodeTabContent.cs" />
<Compile Include="NewDnSpyFile.cs" />
<Compile Include="Plugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ToolTipContentCreator.cs" />
<Compile Include="ToolWindowContent.cs" />
<Compile Include="ToolWindowControl.xaml.cs">
<DependentUpon>ToolWindowControl.xaml</DependentUpon>
</Compile>
<Compile Include="TreeNodeDataCreator.cs" />
</ItemGroup>
<ItemGroup>
<None Include="README.md" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Libraries\dnlib\src\dnlib.csproj">
<Project>{fdfc1237-143f-4919-8318-4926901f4639}</Project>
<Name>dnlib</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\dnSpy\dnSpy.Contracts\dnSpy.Contracts.csproj">
<Project>{9b234472-0e22-428c-9345-c8d9ee5e06af}</Project>
<Name>dnSpy.Contracts</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\dnSpy\dnSpy.Decompiler.Shared\dnSpy.Decompiler.Shared.csproj">
<Project>{a027546a-cf4b-47f9-bc53-ee1ad424ee41}</Project>
<Name>dnSpy.Decompiler.Shared</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\dnSpy\dnSpy.Shared\dnSpy.Shared.csproj">
<Project>{7e7c2cf8-2057-4eaa-9dad-ab3022cf4037}</Project>
<Name>dnSpy.Shared</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Page Include="Themes\resourcedict.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="ToolWindowControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Resource Include="Images\EntryPoint.png" />
<Resource Include="Images\Strings.png" />
<Resource Include="Images\TextFile.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Двоичные данные
Plugins/Examples/Example2.Plugin/Images/EntryPoint.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 221 B

Двоичные данные
Plugins/Examples/Example2.Plugin/Images/Strings.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 154 B

Двоичные данные
Plugins/Examples/Example2.Plugin/Images/TextFile.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 239 B

Просмотреть файл

@ -0,0 +1,148 @@
using System;
using System.ComponentModel.Composition;
using System.IO;
using dnSpy.Contracts.Files;
using dnSpy.Contracts.Files.Tabs.TextEditor;
using dnSpy.Contracts.Files.TreeView;
using dnSpy.Contracts.Highlighting;
using dnSpy.Contracts.Images;
using dnSpy.Contracts.Languages;
using dnSpy.Decompiler.Shared;
using dnSpy.Shared.Files;
using dnSpy.Shared.Files.TreeView;
using dnSpy.Shared.Highlighting;
// Adds a new IDnSpyFile that can be loaded into the file treeview. It gets its own IDnSpyFileNode.
// Open a .txt/.xml/.cs/.vb (see supportedExtensions) file to trigger this code.
namespace Example2.Plugin {
// All root nodes in the file treeview contain a IDnSpyFile instance. They don't need to be
// .NET files or even PE files, they can be any file or even non-file (eg. in-memory data).
sealed class MyDnSpyFile : DnSpyFile {
//TODO: Use your own guid
public static readonly Guid THE_GUID = new Guid("9058B02C-1FE0-4EC4-93D3-A378D4B6FCE1");
// We support serialization, so return a non-null value
public override DnSpyFileInfo? SerializedFile {
get { return new DnSpyFileInfo(Filename, THE_GUID); }
}
// Since we open files from disk, we return a FilenameKey.
// If this gets changed, also update MyDnSpyFileCreator.CreateKey()
public override IDnSpyFilenameKey Key {
get { return new FilenameKey(Filename); }
}
// Used by MyDnSpyFileNode.Decompile() to show the file in the text editor
public string Text {
get {
if (text != null)
return text;
try {
return text = File.ReadAllText(Filename);
}
catch {
return text = string.Format("Couldn't read the file: {0}", Filename);
}
}
}
string text;
public static MyDnSpyFile TryCreate(string filename) {
if (!File.Exists(filename))
return null;
return new MyDnSpyFile(filename);
}
MyDnSpyFile(string filename) {
this.Filename = filename;
}
}
// Gets called by the IFileManager instance to create IDnSpyFile instances. If it's a .txt file
// or our MyDnSpyFile.THE_GUID, then create a MyDnSpyFile instance.
[Export(typeof(IDnSpyFileCreator))]
sealed class MyDnSpyFileCreator : IDnSpyFileCreator {
public double Order {
get { return 0; }
}
public IDnSpyFile Create(IFileManager fileManager, DnSpyFileInfo fileInfo) {
if (fileInfo.Type == MyDnSpyFile.THE_GUID)
return MyDnSpyFile.TryCreate(fileInfo.Name);
// Also check for normal files
if (fileInfo.Type == FileConstants.FILETYPE_FILE && IsSupportedFile(fileInfo.Name))
return MyDnSpyFile.TryCreate(fileInfo.Name);
return null;
}
public IDnSpyFilenameKey CreateKey(IFileManager fileManager, DnSpyFileInfo fileInfo) {
if (fileInfo.Type == MyDnSpyFile.THE_GUID)
return new FilenameKey(fileInfo.Name); // Must match the key in MyDnSpyFile.Key
// Also check for normal files
if (fileInfo.Type == FileConstants.FILETYPE_FILE && IsSupportedFile(fileInfo.Name))
return new FilenameKey(fileInfo.Name); // Must match the key in MyDnSpyFile.Key
return null;
}
static bool IsSupportedFile(string filename) {
foreach (var ext in supportedExtensions) {
if (filename.EndsWith(ext, StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
}
static readonly string[] supportedExtensions = new string[] {
".txt", ".xml", ".cs", ".vb",
};
}
// Gets called by dnSpy to create a IDnSpyFileNode
[ExportDnSpyFileNodeCreator]
sealed class MyDnSpyFileNodeCreator : IDnSpyFileNodeCreator {
public IDnSpyFileNode Create(IFileTreeView fileTreeView, IDnSpyFileNode owner, IDnSpyFile file) {
var myFile = file as MyDnSpyFile;
if (myFile != null)
return new MyDnSpyFileNode(myFile);
return null;
}
}
// Our MyDnSpyFile tree node class. It implements IDecompileSelf to "decompile" itself. You could
// also export a IDecompileNode instance to do it, see TreeNodeDataCreator.cs for an example.
// Or you could create a completely new IFileTabContent for these nodes, see AssemblyChildNodeTabContent.cs
sealed class MyDnSpyFileNode : FileTreeNodeData, IDnSpyFileNode, IDecompileSelf {
//TODO: Use your own guid
public static readonly Guid THE_GUID = new Guid("4174A21D-D746-4658-9A44-DB8235EE5186");
public IDnSpyFile DnSpyFile {
get { return file; }
}
readonly MyDnSpyFile file;
public override Guid Guid {
get { return THE_GUID; }
}
public override NodePathName NodePathName {
get { return new NodePathName(Guid, file.Filename.ToUpperInvariant()); }
}
public MyDnSpyFileNode(MyDnSpyFile file) {
this.file = file;
}
protected override ImageReference GetIcon(IDotNetImageManager dnImgMgr) {
return new ImageReference(GetType().Assembly, "TextFile");
}
protected override void Write(ISyntaxHighlightOutput output, ILanguage language) {
output.WriteFilename(Path.GetFileName(file.Filename));
}
public bool Decompile(IDecompileNodeContext context) {
context.Output.Write(file.Text, TextTokenKind.Text);
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,27 @@
using System.Collections.Generic;
using dnSpy.Contracts.Plugin;
// Each plugin should export one class implementing IPlugin
namespace Example2.Plugin {
[ExportPlugin]
sealed class Plugin : IPlugin {
public IEnumerable<string> MergedResourceDictionaries {
get {
yield return "Themes/resourcedict.xaml";
}
}
public PluginInfo PluginInfo {
get {
return new PluginInfo {
ShortDescription = "Example2 plugin",
};
}
}
public void OnEvent(PluginEvent @event, object obj) {
// We don't care about any events
}
}
}

Просмотреть файл

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Example2.Plugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Example2.Plugin")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4613c8a1-28dc-4586-9f9b-d201864cfe1a")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,8 @@
This plugin shows how to do more advanced stuff. It:
- Adds a tool window (ToolWindowContent.cs)
- Adds new tree nodes (TreeNodeDataCreator.cs)
- Adds custom tab content for the new AssemblyChildNode tree node (AssemblyChildNodeTabContent.cs). ModuleChildNode implements IDecompileSelf to decompile itself.
- Shows tooltips when hovering over custom references added to the text editor (ToolTipContentCreator.cs)
- Adds a new IDnSpyFile instance and IDnSpyFileNode node (NewDnSpyFile.cs). It opens .txt files and shows the output in the text editor.

Просмотреть файл

@ -0,0 +1,24 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="clr-namespace:Example2.Plugin"
xmlns:mvvm="clr-namespace:dnSpy.Shared.MVVM;assembly=dnSpy.Shared"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DataTemplate DataType="{x:Type local:AssemblyChildNodeVM}">
<!-- InitDataTemplateAP.Initialize will initialize the context menu to prevent the default
tool window context menu from showing. -->
<Border Background="{DynamicResource EnvironmentBackground}" TextBlock.Foreground="{DynamicResource EnvironmentForeground}"
BorderThickness="1" BorderBrush="Red"
mvvm:InitDataTemplateAP.Initialize="True"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding SomeMessage}" />
<TextBlock Grid.Row="1" Text="That's it, there's nothing more to see here" />
</Grid>
</Border>
</DataTemplate>
</ResourceDictionary>

Просмотреть файл

@ -0,0 +1,32 @@
using dnSpy.Contracts.Files.Tabs.TextEditor.ToolTips;
using dnSpy.Decompiler.Shared;
namespace Example2.Plugin {
// This reference is added to the "decompiled" code by ModuleChildNode.Decompile()
sealed class StringInfoReference {
public string Message {
get { return msg; }
}
readonly string msg;
public StringInfoReference(string msg) {
this.msg = msg;
}
}
// Called by dnSpy to create a tooltip when hovering over a reference in the text editor
[ExportToolTipContentCreator(Order = 0)]
sealed class ToolTipContentCreator : IToolTipContentCreator {
public object Create(IToolTipContentCreatorContext context, object @ref) {
// This reference is added to the "decompiled" code by ModuleChildNode.Decompile()
var sref = @ref as StringInfoReference;
if (sref != null) {
var creator = context.Create();
creator.Output.Write(sref.Message, TextTokenKind.String);
return creator.Create();
}
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,190 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Windows;
using System.Windows.Input;
using dnSpy.Contracts.Controls;
using dnSpy.Contracts.Menus;
using dnSpy.Contracts.Plugin;
using dnSpy.Contracts.ToolWindows;
using dnSpy.Contracts.ToolWindows.App;
using dnSpy.Shared.Menus;
using dnSpy.Shared.MVVM;
// Adds a tool window and a command that will show it. The command is added to the View menu and a
// keyboard shortcut is added to the main window. Keyboard shortcut Ctrl+Alt+Z shows the tool window.
namespace Example2.Plugin {
// Adds the 'OpenToolWindow' command to the main window and sets keyboard shortcut to Ctrl+Alt+Z
[ExportAutoLoaded]
sealed class ToolWindowLoader : IAutoLoaded {
public static readonly RoutedCommand OpenToolWindow = new RoutedCommand("OpenToolWindow", typeof(ToolWindowLoader));
[ImportingConstructor]
ToolWindowLoader(IWpfCommandManager wpfCommandManager, IMainToolWindowManager mainToolWindowManager) {
var cmds = wpfCommandManager.GetCommands(CommandConstants.GUID_MAINWINDOW);
cmds.Add(OpenToolWindow, new RelayCommand(a => mainToolWindowManager.Show(ToolWindowContent.THE_GUID)));
cmds.Add(OpenToolWindow, ModifierKeys.Control | ModifierKeys.Alt, Key.Z);
}
}
// Adds a menu item to the View menu to show the tool window
[ExportMenuItem(OwnerGuid = MenuConstants.APP_MENU_VIEW_GUID, Header = "Plugin Tool Window", InputGestureText = "Ctrl+Alt+Z", Group = MenuConstants.GROUP_APP_MENU_VIEW_WINDOWS, Order = 2000)]
sealed class ViewCommand1 : MenuItemCommand {
ViewCommand1()
: base(ToolWindowLoader.OpenToolWindow) {
}
}
// Dummy dependency "needed" by MainToolWindowContentCreator
[Export]
sealed class DeppDep {
public void Hello() {
}
}
// Called by dnSpy to create the tool window
[Export(typeof(IMainToolWindowContentCreator))]
sealed class MainToolWindowContentCreator : IMainToolWindowContentCreator {
// Caches the created tool window
ToolWindowContent ToolWindowContent {
get { return myToolWindowContent ?? (myToolWindowContent = new ToolWindowContent()); }
}
ToolWindowContent myToolWindowContent;
// Add any deps to the constructor if needed, else remove the constructor
[ImportingConstructor]
MainToolWindowContentCreator(DeppDep deppDep) {
deppDep.Hello();
}
// Lets dnSpy know which tool windows it can create and their default locations
public IEnumerable<ToolWindowContentInfo> ContentInfos {
get { yield return new ToolWindowContentInfo(ToolWindowContent.THE_GUID, ToolWindowContent.DEFAULT_LOCATION, 0, false); }
}
// Called by dnSpy. If it's your tool window guid, return the instance. Make sure it's
// cached since it can be called multiple times.
public IToolWindowContent GetOrCreate(Guid guid) {
if (guid == ToolWindowContent.THE_GUID)
return ToolWindowContent;
return null;
}
}
sealed class ToolWindowContent : IToolWindowContent {
//TODO: Use your own guid
public static readonly Guid THE_GUID = new Guid("18785447-21A8-41DB-B8AD-0F166AEC0D08");
public const AppToolWindowLocation DEFAULT_LOCATION = AppToolWindowLocation.DefaultHorizontal;
public Guid Guid {
get { return THE_GUID; }
}
public string Title {
get { return "Plugin Example"; }
}
public object ToolTip {
get { return null; }
}
// This is the object shown in the UI. Return a WPF object or a .NET object with a DataTemplate
public object UIObject {
get { return toolWindowControl; }
}
// The element inside UIObject that gets the focus when the tool window should be focused.
// If it's not as easy as calling FocusedElement.Focus() to focus it, you must implement
// dnSpy.Contracts.Controls.IFocusable.
public IInputElement FocusedElement {
get { return toolWindowControl.option1TextBox; }
}
// The element that gets scaled when the user zooms in or out. Return null if zooming isn't
// possible
public FrameworkElement ScaleElement {
get { return toolWindowControl; }
}
readonly ToolWindowControl toolWindowControl;
readonly ToolWindowVM toolWindowVM;
public ToolWindowContent() {
this.toolWindowControl = new ToolWindowControl();
this.toolWindowVM = new ToolWindowVM();
this.toolWindowControl.DataContext = this.toolWindowVM;
}
// Gets notified when the content gets hidden, visible, etc. Can be used to tell the view
// model to stop doing stuff when it gets hidden in case it does a lot of work.
public void OnVisibilityChanged(ToolWindowContentVisibilityEvent visEvent) {
switch (visEvent) {
case ToolWindowContentVisibilityEvent.Added:
toolWindowVM.IsEnabled = true;
break;
case ToolWindowContentVisibilityEvent.Removed:
toolWindowVM.IsEnabled = false;
break;
case ToolWindowContentVisibilityEvent.Visible:
toolWindowVM.IsVisible = true;
break;
case ToolWindowContentVisibilityEvent.Hidden:
toolWindowVM.IsVisible = false;
break;
}
}
}
sealed class ToolWindowVM : ViewModelBase {
public string StringOption1 {
get { return stringOption1; }
set {
if (stringOption1 != value) {
stringOption1 = value;
OnPropertyChanged("StringOption1");
}
}
}
string stringOption1 = string.Empty;
public string StringOption2 {
get { return stringOption2; }
set {
if (stringOption2 != value) {
stringOption2 = value;
OnPropertyChanged("StringOption2");
}
}
}
string stringOption2 = string.Empty;
public string StringOption3 {
get { return stringOption3; }
set {
if (stringOption3 != value) {
stringOption3 = value;
OnPropertyChanged("StringOption3");
}
}
}
string stringOption3 = string.Empty;
public string StringOption4 {
get { return stringOption4; }
set {
if (stringOption4 != value) {
stringOption4 = value;
OnPropertyChanged("StringOption4");
}
}
}
string stringOption4 = string.Empty;
public bool IsEnabled { get; set; }
public bool IsVisible { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,35 @@
<UserControl x:Class="Example2.Plugin.ToolWindowControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Example2.Plugin"
xmlns:mvvm="clr-namespace:dnSpy.Shared.MVVM;assembly=dnSpy.Shared"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<!-- InitDataTemplateAP.Initialize will initialize the context menu to prevent the default
tool window context menu from showing. -->
<Grid
mvvm:InitDataTemplateAP.Initialize="True"
Background="Transparent"
>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Option #1" />
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding StringOption1}" Name="option1TextBox" />
<Label Grid.Row="1" Grid.Column="0" Content="Option #2" />
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding StringOption2}" />
<Label Grid.Row="2" Grid.Column="0" Content="Option #3" />
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding StringOption3}" />
<Label Grid.Row="3" Grid.Column="0" Content="Option #4" />
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding StringOption4}" />
</Grid>
</UserControl>

Просмотреть файл

@ -0,0 +1,9 @@
using System.Windows.Controls;
namespace Example2.Plugin {
public partial class ToolWindowControl : UserControl {
public ToolWindowControl() {
InitializeComponent();
}
}
}

Просмотреть файл

@ -0,0 +1,266 @@
using System;
using System.Collections.Generic;
using System.Threading;
using dnSpy.Contracts.Files.Tabs.TextEditor;
using dnSpy.Contracts.Files.TreeView;
using dnSpy.Contracts.Highlighting;
using dnSpy.Contracts.Images;
using dnSpy.Contracts.Languages;
using dnSpy.Contracts.TreeView;
using dnSpy.Decompiler.Shared;
using dnSpy.Shared.Decompiler;
using dnSpy.Shared.Files.TreeView;
// This file contains classes that create new child nodes of IAssemblyFileNode and IModuleFileNode
namespace Example2.Plugin {
// This class adds a new child node to all assembly nodes
[ExportTreeNodeDataCreator(Guid = FileTVConstants.ASSEMBLY_NODE_GUID)]
sealed class AssemblyTreeNodeDataCreator : ITreeNodeDataCreator {
public IEnumerable<ITreeNodeData> Create(TreeNodeDataCreatorContext context) {
yield return new AssemblyChildNode();
}
}
// This class adds a new child node to all module nodes
[ExportTreeNodeDataCreator(Guid = FileTVConstants.MODULE_NODE_GUID)]
sealed class ModuleTreeNodeDataCreator : ITreeNodeDataCreator {
public IEnumerable<ITreeNodeData> Create(TreeNodeDataCreatorContext context) {
yield return new ModuleChildNode();
}
}
sealed class AssemblyChildNode : FileTreeNodeData { // All file tree nodes should implement IFileTreeNodeData or derive from FileTreeNodeData
//TODO: Use your own guid
public static readonly Guid THE_GUID = new Guid("6CF91674-16CE-44EA-B9E8-80B68C327D30");
public override Guid Guid {
get { return THE_GUID; }
}
public override NodePathName NodePathName {
// If there could be more instances of this class with the same parent, add a second
// argument to the NodePathName constructor, eg. an index or some other unique string.
// Eg. IMethodNode uses the name of the method.
get { return new NodePathName(Guid); }
}
protected override ImageReference GetIcon(IDotNetImageManager dnImgMgr) {
// The image must be in an Images folder (in the resources) and have a .png extension
return new ImageReference(GetType().Assembly, "EntryPoint");
}
protected override void Write(ISyntaxHighlightOutput output, ILanguage language) {
output.Write("Assembly Child", TextTokenKind.Text);
}
// If you don't want the node to be appended to the children, override this
public override ITreeNodeGroup TreeNodeGroup {
get { return TreeNodeGroupImpl.Instance; }
}
sealed class TreeNodeGroupImpl : ITreeNodeGroup {
public static readonly TreeNodeGroupImpl Instance = new TreeNodeGroupImpl(1);
public TreeNodeGroupImpl(double order) {
this.order = order;
}
public double Order {
get { return order; }
set { order = value; }
}
double order;
public int Compare(ITreeNodeData x, ITreeNodeData y) {
if (x == y)
return 0;
var a = x as AssemblyChildNode;
var b = y as AssemblyChildNode;
if (a == null) return -1;
if (b == null) return 1;
// More checks can be added here...
return 0;
}
}
}
// This class can decompile its own output and implements IDecompileSelf
sealed class ModuleChildNode : FileTreeNodeData, IDecompileSelf { // All file tree nodes should implement IFileTreeNodeData or derive from FileTreeNodeData
//TODO: Use your own guid
public static readonly Guid THE_GUID = new Guid("C8892F6C-6A49-4537-AAA0-D0DEF1E87277");
public override Guid Guid {
get { return THE_GUID; }
}
public override NodePathName NodePathName {
// If there could be more instances of this class with the same parent, add a second
// argument to the NodePathName constructor, eg. an index or some other unique string.
// Eg. IMethodNode uses the name of the method.
get { return new NodePathName(Guid); }
}
// Initialize() is called after the constructor has been called, and after the TreeNode prop
// has been initialized
public override void Initialize() {
// Set LazyLoading if creating the children could take a while
TreeNode.LazyLoading = true;
}
// If TreeNode.LazyLoading is false, CreateChildren() is called after Initialize(), else it's
// called when this node gets expanded.
public override IEnumerable<ITreeNodeData> CreateChildren() {
// Add some children in random order. They will be sorted because SomeMessageNode
// overrides the TreeNodeGroup prop.
yield return new SomeMessageNode("ZZZZZZZZZZZZZ");
yield return new SomeMessageNode("AAAAaaaaaAAAAAAA");
yield return new SomeMessageNode("SAY");
}
protected override ImageReference GetIcon(IDotNetImageManager dnImgMgr) {
// The image must be in an Images folder (in the resources) and have a .png extension
return new ImageReference(GetType().Assembly, "Strings");
}
protected override void Write(ISyntaxHighlightOutput output, ILanguage language) {
output.Write("Module Child", TextTokenKind.Text);
}
// Gets called by dnSpy if there's only one node to decompile. This method gets called in a
// worker thread. The output is also cached unless you call AvalonEditTextOutput.DontCacheOutput().
public bool Decompile(IDecompileNodeContext context) {
// Pretend we actually do something...
Thread.Sleep(2000);
// If you don't want the output to be cached, call DontCacheOutput()
bool cacheOutput = true;
if (!cacheOutput) {
var avOutput = context.Output as AvalonEditTextOutput;
if (avOutput != null)
avOutput.DontCacheOutput();
}
// Create the output and a few references that other code in this plugin will use, eg.
// to show a tooltip when hovering over the reference.
context.HighlightingExtension = ".cs";
context.Language.WriteCommentLine(context.Output, "Initialize it to the secret key");
context.Output.WriteReference("int", new StringInfoReference("This is a reference added by the code"), TextTokenKind.Keyword);
context.Output.WriteSpace();
context.Output.WriteReference("secret", new StringInfoReference("The real secret is actually 42 not 1234"), TextTokenKind.Local);
context.Output.WriteSpace();
context.Output.Write("=", TextTokenKind.Operator);
context.Output.WriteSpace();
context.Output.Write("1234", TextTokenKind.Number);
context.Output.Write(";", TextTokenKind.Operator);
context.Output.WriteLine();
// We decompiled ourselves so return true
return true;
}
// If you don't want the node to be appended to the children, override this
public override ITreeNodeGroup TreeNodeGroup {
get { return TreeNodeGroupImpl.Instance; }
}
sealed class TreeNodeGroupImpl : ITreeNodeGroup {
// Make sure the order is unique. 0 is already used by the PE node, so use 1
public static readonly TreeNodeGroupImpl Instance = new TreeNodeGroupImpl(1);
public TreeNodeGroupImpl(double order) {
this.order = order;
}
public double Order {
get { return order; }
set { order = value; }
}
double order;
public int Compare(ITreeNodeData x, ITreeNodeData y) {
if (x == y)
return 0;
var a = x as ModuleChildNode;
var b = y as ModuleChildNode;
if (a == null) return -1;
if (b == null) return 1;
// More checks can be added here...
return 0;
}
}
}
sealed class SomeMessageNode : FileTreeNodeData {
//TODO: Use your own guid
public static readonly Guid THE_GUID = new Guid("1751CD40-68CE-4F8A-84AF-99371B6FD843");
public string Message {
get { return msg; }
}
readonly string msg;
public SomeMessageNode(string msg) {
this.msg = msg;
}
public override Guid Guid {
get { return THE_GUID; }
}
public override NodePathName NodePathName {
get { return new NodePathName(THE_GUID, msg); }
}
protected override ImageReference GetIcon(IDotNetImageManager dnImgMgr) {
return new ImageReference(GetType().Assembly, "Strings");
}
protected override void Write(ISyntaxHighlightOutput output, ILanguage language) {
output.Write(msg, TextTokenKind.Comment);
}
public override ITreeNodeGroup TreeNodeGroup {
get { return TreeNodeGroupImpl.Instance; }
}
sealed class TreeNodeGroupImpl : ITreeNodeGroup {
public static readonly TreeNodeGroupImpl Instance = new TreeNodeGroupImpl(0);
public TreeNodeGroupImpl(double order) {
this.order = order;
}
public double Order {
get { return order; }
set { order = value; }
}
double order;
public int Compare(ITreeNodeData x, ITreeNodeData y) {
if (x == y)
return 0;
var a = x as SomeMessageNode;
var b = y as SomeMessageNode;
if (a == null) return -1;
if (b == null) return 1;
return StringComparer.OrdinalIgnoreCase.Compare(a.msg, b.msg);
}
}
}
// SomeMessageNode doesn't implement IDecompileSelf, so we add a "decompiler" that can "decompile"
// those nodes.
[ExportDecompileNode]
sealed class SomeMessageNodeDecompiler : IDecompileNode {
public bool Decompile(IDecompileNodeContext context, IFileTreeNodeData node) {
var msgNode = node as SomeMessageNode;
if (msgNode == null)
return false;
context.Language.WriteCommentLine(context.Output, "The secret message has been decrypted.");
context.Language.WriteCommentLine(context.Output, string.Format("The message is: {0}", msgNode.Message));
return true;
}
}
}

@ -0,0 +1 @@
Subproject commit e0adc32662935c90ad494d499033c4c781029da5

@ -0,0 +1 @@
Subproject commit a1a3f83bf62dda9c9232e5311e0dedefe4ce11bb

Просмотреть файл

@ -0,0 +1,62 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Diagnostics;
using System.Linq;
using dnlib.DotNet;
using ICSharpCode.Decompiler.Ast.Transforms;
using ICSharpCode.NRefactory.CSharp;
namespace dnSpy.Languages.ILSpy.CSharp {
sealed class AssemblyInfoTransform : IAstTransform {
public void Run(AstNode compilationUnit) {
foreach (var attrSect in compilationUnit.Descendants.OfType<AttributeSection>()) {
var attr = attrSect.Descendants.OfType<Attribute>().FirstOrDefault();
Debug.Assert(attr != null);
if (attr == null)
continue;
var ca = attr.Annotation<CustomAttribute>();
if (ca == null)
continue;
if (!Compare(ca.AttributeType, systemRuntimeVersioningString, targetFrameworkAttributeString) &&
!Compare(ca.AttributeType, systemSecurityString, unverifiableCodeAttributeString))
continue;
attrSect.Remove();
}
}
static readonly UTF8String systemRuntimeVersioningString = new UTF8String("System.Runtime.Versioning");
static readonly UTF8String targetFrameworkAttributeString = new UTF8String("TargetFrameworkAttribute");
static readonly UTF8String systemSecurityString = new UTF8String("System.Security");
static readonly UTF8String unverifiableCodeAttributeString = new UTF8String("UnverifiableCodeAttribute");
static bool Compare(ITypeDefOrRef type, UTF8String expNs, UTF8String expName) {
if (type == null)
return false;
var tr = type as TypeRef;
if (tr != null)
return tr.Namespace == expNs && tr.Name == expName;
var td = type as TypeDef;
if (td != null)
return td.Namespace == expNs && td.Name == expName;
return false;
}
}
}

Просмотреть файл

@ -0,0 +1,76 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Text;
using dnSpy.Contracts.Languages;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
namespace dnSpy.Languages.ILSpy.CSharp {
/// <summary>
/// State for one decompiler thread. There should be at most one of these per CPU. This class
/// is not thread safe and must only be accessed by the owner thread.
/// </summary>
sealed class AstBuilderState {
public readonly AstBuilder AstBuilder;
/// <summary>
/// <see cref="StringBuilder"/> instance used by XML doc code. This is always in a random
/// state (random text) and caller must Clear() it before use.
/// </summary>
public readonly StringBuilder XmlDoc_StringBuilder;
public AstBuilderState() {
this.AstBuilder = new AstBuilder(new DecompilerContext(null, true));
this.XmlDoc_StringBuilder = new StringBuilder();
}
/// <summary>
/// Called to re-use this instance for another decompilation. Only the fields that need
/// resetting will be reset.
/// </summary>
public void Reset() {
AstBuilder.Reset();
}
}
/// <summary>
/// One instance is created and stored in <see cref="DecompilationContext"/>. It's used by the
/// decompiler threads to get an <see cref="AstBuilderState"/> instance.
/// </summary>
sealed class BuilderCache {
readonly ThreadSafeObjectPool<AstBuilderState> astBuilderStatePool;
public BuilderCache() {
this.astBuilderStatePool = new ThreadSafeObjectPool<AstBuilderState>(Environment.ProcessorCount, createAstBuilderState, resetAstBuilderState);
}
static readonly Func<AstBuilderState> createAstBuilderState = () => new AstBuilderState();
static readonly Action<AstBuilderState> resetAstBuilderState = abs => abs.Reset();
public AstBuilderState AllocateAstBuilderState() {
return astBuilderStatePool.Allocate();
}
public void Free(AstBuilderState state) {
astBuilderStatePool.Free(state);
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using dnSpy.Contracts.Languages;
using ICSharpCode.Decompiler.Ast;
namespace dnSpy.Languages.ILSpy.CSharp {
/// <summary>
/// Gets the <see cref="AstBuilderState"/> from the pool and returns it when <see cref="Dispose"/>
/// gets called.
/// </summary>
struct BuilderState : IDisposable {
public AstBuilder AstBuilder {
get { return State.AstBuilder; }
}
public readonly AstBuilderState State;
readonly DecompilationContext ctx;
readonly BuilderCache cache;
public BuilderState(DecompilationContext ctx, BuilderCache cache) {
this.ctx = ctx;
this.cache = cache;
this.State = cache.AllocateAstBuilderState();
this.State.AstBuilder.Context.CalculateILRanges = ctx.CalculateILRanges;
}
public void Dispose() {
cache.Free(State);
}
}
}

Просмотреть файл

@ -0,0 +1,515 @@
// Copyright (c) 2011 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.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Xml;
using dnlib.DotNet;
using dnSpy.Contracts.Languages;
using dnSpy.Decompiler.Shared;
using dnSpy.Languages.ILSpy.Settings;
using dnSpy.Languages.ILSpy.XmlDoc;
using dnSpy.Shared.Highlighting;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Ast.Transforms;
using ICSharpCode.NRefactory.CSharp;
namespace dnSpy.Languages.ILSpy.CSharp {
sealed class LanguageProvider : ILanguageProvider {
readonly LanguageSettingsManager languageSettingsManager;
// Keep the default ctor. It's used by dnSpy.Console.exe
public LanguageProvider()
: this(LanguageSettingsManager.__Instance_DONT_USE) {
}
public LanguageProvider(LanguageSettingsManager languageSettingsManager) {
Debug.Assert(languageSettingsManager != null);
if (languageSettingsManager == null)
throw new ArgumentNullException();
this.languageSettingsManager = languageSettingsManager;
}
public IEnumerable<ILanguage> Languages {
get {
yield return new CSharpLanguage(languageSettingsManager.LanguageDecompilerSettings, LanguageConstants.CSHARP_ILSPY_ORDERUI);
#if DEBUG
foreach (var l in CSharpLanguage.GetDebugLanguages(languageSettingsManager.LanguageDecompilerSettings))
yield return l;
#endif
}
}
}
[Export(typeof(ILanguageCreator))]
sealed class MyLanguageCreator : ILanguageCreator {
readonly LanguageSettingsManager languageSettingsManager;
[ImportingConstructor]
MyLanguageCreator(LanguageSettingsManager languageSettingsManager) {
this.languageSettingsManager = languageSettingsManager;
}
public IEnumerable<ILanguage> Create() {
return new LanguageProvider(languageSettingsManager).Languages;
}
}
/// <summary>
/// Decompiler logic for C#.
/// </summary>
sealed class CSharpLanguage : Language {
string uniqueNameUI = "C#";
Guid uniqueGuid = LanguageConstants.LANGUAGE_CSHARP_ILSPY;
bool showAllMembers = false;
Predicate<IAstTransform> transformAbortCondition = null;
public override IDecompilerSettings Settings {
get { return langSettings; }
}
readonly LanguageDecompilerSettings langSettings;
public CSharpLanguage(LanguageDecompilerSettings langSettings, double orderUI) {
this.langSettings = langSettings;
this.orderUI = orderUI;
}
#if DEBUG
internal static IEnumerable<CSharpLanguage> GetDebugLanguages(LanguageDecompilerSettings langSettings) {
DecompilerContext context = new DecompilerContext(new ModuleDefUser("dummy"));
string lastTransformName = "no transforms";
double orderUI = LanguageConstants.CSHARP_ILSPY_DEBUG_ORDERUI;
uint id = 0xBF67AF3F;
foreach (Type _transformType in TransformationPipeline.CreatePipeline(context).Select(v => v.GetType()).Distinct()) {
Type transformType = _transformType; // copy for lambda
yield return new CSharpLanguage(langSettings, orderUI++) {
transformAbortCondition = v => transformType.IsInstanceOfType(v),
uniqueNameUI = "C# - " + lastTransformName,
uniqueGuid = new Guid(string.Format("203F702E-7E87-4F01-84CD-B0E8{0:X8}", id++)),
showAllMembers = true
};
lastTransformName = "after " + transformType.Name;
}
yield return new CSharpLanguage(langSettings, orderUI++) {
uniqueNameUI = "C# - " + lastTransformName,
uniqueGuid = new Guid(string.Format("203F702E-7E87-4F01-84CD-B0E8{0:X8}", id++)),
showAllMembers = true
};
}
#endif
public override string GenericNameUI {
get { return LanguageConstants.GENERIC_NAMEUI_CSHARP; }
}
public override string UniqueNameUI {
get { return uniqueNameUI; }
}
public override double OrderUI {
get { return orderUI; }
}
readonly double orderUI;
public override Guid GenericGuid {
get { return LanguageConstants.LANGUAGE_CSHARP; }
}
public override Guid UniqueGuid {
get { return uniqueGuid; }
}
public override string FileExtension {
get { return ".cs"; }
}
public override string ProjectFileExtension {
get { return ".csproj"; }
}
public override void Decompile(MethodDef method, ITextOutput output, DecompilationContext ctx) {
WriteCommentLineDeclaringType(output, method);
var state = CreateAstBuilder(ctx, langSettings.Settings, currentType: method.DeclaringType, isSingleMember: true);
try {
if (method.IsConstructor && !method.IsStatic && !method.DeclaringType.IsValueType) {
// also fields and other ctors so that the field initializers can be shown as such
AddFieldsAndCtors(state.AstBuilder, method.DeclaringType, method.IsStatic);
RunTransformsAndGenerateCode(ref state, output, ctx, new SelectCtorTransform(method));
}
else {
state.AstBuilder.AddMethod(method);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
}
finally {
state.Dispose();
}
}
class SelectCtorTransform : IAstTransform {
readonly MethodDef ctorDef;
public SelectCtorTransform(MethodDef ctorDef) {
this.ctorDef = ctorDef;
}
public void Run(AstNode compilationUnit) {
ConstructorDeclaration ctorDecl = null;
foreach (var node in compilationUnit.Children) {
ConstructorDeclaration ctor = node as ConstructorDeclaration;
if (ctor != null) {
if (ctor.Annotation<MethodDef>() == ctorDef) {
ctorDecl = ctor;
}
else {
// remove other ctors
ctor.Remove();
}
}
// Remove any fields without initializers
FieldDeclaration fd = node as FieldDeclaration;
if (fd != null && fd.Variables.All(v => v.Initializer.IsNull))
fd.Remove();
}
if (ctorDecl.Initializer.ConstructorInitializerType == ConstructorInitializerType.This) {
// remove all fields
foreach (var node in compilationUnit.Children)
if (node is FieldDeclaration)
node.Remove();
}
}
}
public override void Decompile(PropertyDef property, ITextOutput output, DecompilationContext ctx) {
WriteCommentLineDeclaringType(output, property);
var state = CreateAstBuilder(ctx, langSettings.Settings, currentType: property.DeclaringType, isSingleMember: true);
try {
state.AstBuilder.AddProperty(property);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
public override void Decompile(FieldDef field, ITextOutput output, DecompilationContext ctx) {
WriteCommentLineDeclaringType(output, field);
var state = CreateAstBuilder(ctx, langSettings.Settings, currentType: field.DeclaringType, isSingleMember: true);
try {
if (field.IsLiteral) {
state.AstBuilder.AddField(field);
}
else {
// also decompile ctors so that the field initializer can be shown
AddFieldsAndCtors(state.AstBuilder, field.DeclaringType, field.IsStatic);
}
RunTransformsAndGenerateCode(ref state, output, ctx, new SelectFieldTransform(field));
}
finally {
state.Dispose();
}
}
/// <summary>
/// Removes all top-level members except for the specified fields.
/// </summary>
sealed class SelectFieldTransform : IAstTransform {
readonly FieldDef field;
public SelectFieldTransform(FieldDef field) {
this.field = field;
}
public void Run(AstNode compilationUnit) {
foreach (var child in compilationUnit.Children) {
if (child is EntityDeclaration) {
if (child.Annotation<FieldDef>() != field)
child.Remove();
}
}
}
}
void AddFieldsAndCtors(AstBuilder codeDomBuilder, TypeDef declaringType, bool isStatic) {
foreach (var field in declaringType.Fields) {
if (field.IsStatic == isStatic)
codeDomBuilder.AddField(field);
}
foreach (var ctor in declaringType.Methods) {
if (ctor.IsConstructor && ctor.IsStatic == isStatic)
codeDomBuilder.AddMethod(ctor);
}
}
public override void Decompile(EventDef ev, ITextOutput output, DecompilationContext ctx) {
WriteCommentLineDeclaringType(output, ev);
var state = CreateAstBuilder(ctx, langSettings.Settings, currentType: ev.DeclaringType, isSingleMember: true);
try {
state.AstBuilder.AddEvent(ev);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
public override void Decompile(TypeDef type, ITextOutput output, DecompilationContext ctx) {
var state = CreateAstBuilder(ctx, langSettings.Settings, currentType: type);
try {
state.AstBuilder.AddType(type);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
void RunTransformsAndGenerateCode(ref BuilderState state, ITextOutput output, DecompilationContext ctx, IAstTransform additionalTransform = null) {
var astBuilder = state.AstBuilder;
astBuilder.RunTransformations(transformAbortCondition);
if (additionalTransform != null) {
additionalTransform.Run(astBuilder.SyntaxTree);
}
AddXmlDocumentation(ref state, langSettings.Settings, astBuilder);
astBuilder.GenerateCode(output);
}
internal static void AddXmlDocumentation(ref BuilderState state, DecompilerSettings settings, AstBuilder astBuilder) {
if (settings.ShowXmlDocumentation) {
try {
new AddXmlDocTransform(state.State.XmlDoc_StringBuilder).Run(astBuilder.SyntaxTree);
}
catch (XmlException ex) {
string[] msg = (" Exception while reading XmlDoc: " + ex.ToString()).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
var insertionPoint = astBuilder.SyntaxTree.FirstChild;
for (int i = 0; i < msg.Length; i++)
astBuilder.SyntaxTree.InsertChildBefore(insertionPoint, new Comment(msg[i], CommentType.Documentation), Roles.Comment);
}
}
}
public override void Decompile(AssemblyDef asm, ITextOutput output, DecompilationContext ctx) {
WriteAssembly(asm, output, ctx);
using (ctx.DisableAssemblyLoad()) {
var state = CreateAstBuilder(ctx, langSettings.Settings, currentModule: asm.ManifestModule);
try {
state.AstBuilder.AddAssembly(asm.ManifestModule, true, true, false);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
}
public override void Decompile(ModuleDef mod, ITextOutput output, DecompilationContext ctx) {
WriteModule(mod, output, ctx);
using (ctx.DisableAssemblyLoad()) {
var state = CreateAstBuilder(ctx, langSettings.Settings, currentModule: mod);
try {
state.AstBuilder.AddAssembly(mod, true, false, true);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
}
BuilderState CreateAstBuilder(DecompilationContext ctx, DecompilerSettings settings, ModuleDef currentModule = null, TypeDef currentType = null, bool isSingleMember = false) {
if (currentModule == null)
currentModule = currentType.Module;
if (isSingleMember) {
settings = settings.Clone();
settings.UsingDeclarations = false;
}
var cache = ctx.GetOrCreate<BuilderCache>();
var state = new BuilderState(ctx, cache);
state.AstBuilder.Context.CurrentModule = currentModule;
state.AstBuilder.Context.CancellationToken = ctx.CancellationToken;
state.AstBuilder.Context.CurrentType = currentType;
state.AstBuilder.Context.Settings = settings;
return state;
}
protected override void TypeToString(ITextOutput output, ITypeDefOrRef type, bool includeNamespace, IHasCustomAttribute typeAttributes = null) {
ConvertTypeOptions options = ConvertTypeOptions.IncludeTypeParameterDefinitions;
if (includeNamespace)
options |= ConvertTypeOptions.IncludeNamespace;
TypeToString(output, options, type, typeAttributes);
}
bool WriteRefIfByRef(ITextOutput output, TypeSig typeSig, ParamDef pd) {
if (typeSig.RemovePinnedAndModifiers() is ByRefSig) {
if (pd != null && (!pd.IsIn && pd.IsOut)) {
output.Write("out", TextTokenKind.Keyword);
output.WriteSpace();
}
else {
output.Write("ref", TextTokenKind.Keyword);
output.WriteSpace();
}
return true;
}
return false;
}
void TypeToString(ITextOutput output, ConvertTypeOptions options, ITypeDefOrRef type, IHasCustomAttribute typeAttributes = null) {
if (type == null)
return;
AstType astType = AstBuilder.ConvertType(type, new StringBuilder(), typeAttributes, options);
if (WriteRefIfByRef(output, type.TryGetByRefSig(), typeAttributes as ParamDef)) {
if (astType is ComposedType && ((ComposedType)astType).PointerRank > 0)
((ComposedType)astType).PointerRank--;
}
var module = type.Module;
if (module == null && type is TypeSpec && ((TypeSpec)type).TypeSig.RemovePinnedAndModifiers() is GenericSig) {
var sig = (GenericSig)((TypeSpec)type).TypeSig.RemovePinnedAndModifiers();
if (sig.OwnerType != null)
module = sig.OwnerType.Module;
if (module == null && sig.OwnerMethod != null && sig.OwnerMethod.DeclaringType != null)
module = sig.OwnerMethod.DeclaringType.Module;
}
var ctx = new DecompilerContext(type.Module);
astType.AcceptVisitor(new CSharpOutputVisitor(new TextTokenWriter(output, ctx), FormattingOptionsFactory.CreateAllman()));
}
protected override void FormatPropertyName(ITextOutput output, PropertyDef property, bool? isIndexer) {
if (property == null)
throw new ArgumentNullException("property");
if (!isIndexer.HasValue) {
isIndexer = property.IsIndexer();
}
if (isIndexer.Value) {
var accessor = property.GetMethod ?? property.SetMethod;
if (accessor != null && accessor.HasOverrides) {
var methDecl = accessor.Overrides.First().MethodDeclaration;
var declaringType = methDecl == null ? null : methDecl.DeclaringType;
TypeToString(output, declaringType, includeNamespace: true);
output.Write(".", TextTokenKind.Operator);
}
output.Write("this", TextTokenKind.Keyword);
output.Write("[", TextTokenKind.Operator);
bool addSeparator = false;
foreach (var p in property.PropertySig.GetParams()) {
if (addSeparator) {
output.Write(",", TextTokenKind.Operator);
output.WriteSpace();
}
else
addSeparator = true;
TypeToString(output, p.ToTypeDefOrRef(), includeNamespace: true);
}
output.Write("]", TextTokenKind.Operator);
}
else
WriteIdentifier(output, property.Name, TextTokenKindUtils.GetTextTokenKind(property));
}
static readonly HashSet<string> isKeyword = new HashSet<string>(StringComparer.Ordinal) {
"abstract", "as", "base", "bool", "break", "byte", "case", "catch",
"char", "checked", "class", "const", "continue", "decimal", "default", "delegate",
"do", "double", "else", "enum", "event", "explicit", "extern", "false",
"finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit",
"in", "int", "interface", "internal", "is", "lock", "long", "namespace",
"new", "null", "object", "operator", "out", "override", "params", "private",
"protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short",
"sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw",
"true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort",
"using", "virtual", "void", "volatile", "while",
};
static void WriteIdentifier(ITextOutput output, string id, TextTokenKind tokenKind) {
if (isKeyword.Contains(id))
output.Write("@", TextTokenKind.Operator);
output.Write(IdentifierEscaper.Escape(id), tokenKind);
}
protected override void FormatTypeName(ITextOutput output, TypeDef type) {
if (type == null)
throw new ArgumentNullException("type");
TypeToString(output, ConvertTypeOptions.DoNotUsePrimitiveTypeNames | ConvertTypeOptions.IncludeTypeParameterDefinitions | ConvertTypeOptions.DoNotIncludeEnclosingType, type);
}
public override bool ShowMember(IMemberRef member) {
return showAllMembers || !AstBuilder.MemberIsHidden(member, langSettings.Settings);
}
public override bool CanDecompile(DecompilationType decompilationType) {
switch (decompilationType) {
case DecompilationType.PartialType:
case DecompilationType.AssemblyInfo:
return true;
}
return base.CanDecompile(decompilationType);
}
public override void Decompile(DecompilationType decompilationType, object data) {
switch (decompilationType) {
case DecompilationType.PartialType:
DecompilePartial((DecompilePartialType)data);
return;
case DecompilationType.AssemblyInfo:
DecompileAssemblyInfo((DecompileAssemblyInfo)data);
return;
}
base.Decompile(decompilationType, data);
}
void DecompilePartial(DecompilePartialType info) {
var state = CreateAstBuilder(info.Context, CreateDecompilerSettings(langSettings.Settings, info.UseUsingDeclarations), currentType: info.Type);
try {
state.AstBuilder.AddType(info.Type);
RunTransformsAndGenerateCode(ref state, info.Output, info.Context, new DecompilePartialTransform(info.Type, info.Definitions, info.ShowDefinitions, info.AddPartialKeyword, info.InterfacesToRemove));
}
finally {
state.Dispose();
}
}
internal static DecompilerSettings CreateDecompilerSettings(DecompilerSettings settings, bool useUsingDeclarations) {
var newOne = settings.Clone();
newOne.UsingDeclarations = useUsingDeclarations;
newOne.FullyQualifyAllTypes = !useUsingDeclarations;
return newOne;
}
void DecompileAssemblyInfo(DecompileAssemblyInfo info) {
var state = CreateAstBuilder(info.Context, langSettings.Settings, currentModule: info.Module);
try {
state.AstBuilder.AddAssembly(info.Module, true, info.Module.IsManifestModule, true);
RunTransformsAndGenerateCode(ref state, info.Output, info.Context, new AssemblyInfoTransform());
}
finally {
state.Dispose();
}
}
}
}

Просмотреть файл

@ -0,0 +1,75 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using dnlib.DotNet;
using ICSharpCode.Decompiler.Ast.Transforms;
using ICSharpCode.NRefactory.CSharp;
namespace dnSpy.Languages.ILSpy.CSharp {
sealed class DecompilePartialTransform : IAstTransform {
readonly TypeDef type;
readonly HashSet<IMemberDef> definitions;
readonly bool showDefinitions;
readonly bool addPartialKeyword;
readonly HashSet<ITypeDefOrRef> ifacesToRemove;
public DecompilePartialTransform(TypeDef type, HashSet<IMemberDef> definitions, bool showDefinitions, bool addPartialKeyword, IEnumerable<ITypeDefOrRef> ifacesToRemove) {
this.type = type;
this.definitions = definitions;
this.showDefinitions = showDefinitions;
this.addPartialKeyword = addPartialKeyword;
this.ifacesToRemove = new HashSet<ITypeDefOrRef>(ifacesToRemove, TypeEqualityComparer.Instance);
}
public void Run(AstNode compilationUnit) {
foreach (var en in compilationUnit.Descendants.OfType<EntityDeclaration>()) {
var def = en.Annotation<IMemberDef>();
Debug.Assert(def != null);
if (def == null)
continue;
if (def == type) {
var tdecl = en as TypeDeclaration;
Debug.Assert(tdecl != null);
if (tdecl != null) {
if (addPartialKeyword)
tdecl.Modifiers |= Modifiers.Partial;
foreach (var iface in tdecl.BaseTypes) {
var tdr = iface.Annotation<ITypeDefOrRef>();
if (tdr != null && ifacesToRemove.Contains(tdr))
iface.Remove();
}
}
}
else {
if (showDefinitions) {
if (!definitions.Contains(def))
en.Remove();
}
else {
if (definitions.Contains(def))
en.Remove();
}
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,57 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
namespace dnSpy.Languages.ILSpy.CSharp {
sealed class ThreadSafeObjectPool<T> where T : class {
readonly List<T> freeObjs;
readonly Func<T> createObject;
readonly Action<T> resetObject;
readonly object lockObj = new object();
public ThreadSafeObjectPool(int size, Func<T> createObject, Action<T> resetObject) {
if (size <= 0)
throw new ArgumentException();
this.freeObjs = new List<T>(size);
this.createObject = createObject;
this.resetObject = resetObject;
}
public T Allocate() {
lock (lockObj) {
if (freeObjs.Count > 0) {
int i = freeObjs.Count - 1;
var o = freeObjs[i];
freeObjs.RemoveAt(i);
return o;
}
return createObject();
}
}
public void Free(T obj) {
resetObject(obj);
lock (lockObj)
freeObjs.Add(obj);
}
}
}

Просмотреть файл

@ -0,0 +1,289 @@
// Copyright (c) 2011 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.ComponentModel.Composition;
using dnlib.DotNet;
using dnSpy.Contracts.Highlighting;
using dnSpy.Contracts.Languages;
using dnSpy.Languages.IL;
using dnSpy.Shared.Languages.XmlDoc;
using ICSharpCode.Decompiler.Disassembler;
using dnSpy.Decompiler.Shared;
using dnSpy.Languages.ILSpy.XmlDoc;
using dnSpy.Languages.ILSpy.Settings;
using System.Diagnostics;
using System.Text;
namespace dnSpy.Languages.ILSpy.IL {
sealed class LanguageProvider : ILanguageProvider {
readonly LanguageSettingsManager languageSettingsManager;
// Keep the default ctor. It's used by dnSpy.Console.exe
public LanguageProvider()
: this(LanguageSettingsManager.__Instance_DONT_USE) {
}
public LanguageProvider(LanguageSettingsManager languageSettingsManager) {
Debug.Assert(languageSettingsManager != null);
if (languageSettingsManager == null)
throw new ArgumentNullException();
this.languageSettingsManager = languageSettingsManager;
}
public IEnumerable<ILanguage> Languages {
get { yield return new ILLanguage(languageSettingsManager.ILLanguageDecompilerSettings); }
}
}
[Export(typeof(ILanguageCreator))]
sealed class MyLanguageCreator : ILanguageCreator {
readonly LanguageSettingsManager languageSettingsManager;
[ImportingConstructor]
MyLanguageCreator(LanguageSettingsManager languageSettingsManager) {
this.languageSettingsManager = languageSettingsManager;
}
public IEnumerable<ILanguage> Create() {
return new LanguageProvider(languageSettingsManager).Languages;
}
}
/// <summary>
/// IL language support.
/// </summary>
/// <remarks>
/// Currently comes in two versions:
/// flat IL (detectControlStructure=false) and structured IL (detectControlStructure=true).
/// </remarks>
sealed class ILLanguage : Language {
readonly bool detectControlStructure;
public override IDecompilerSettings Settings {
get { return langSettings; }
}
readonly ILLanguageDecompilerSettings langSettings;
public ILLanguage(ILLanguageDecompilerSettings langSettings)
: this(langSettings, true) {
}
public ILLanguage(ILLanguageDecompilerSettings langSettings, bool detectControlStructure) {
this.langSettings = langSettings;
this.detectControlStructure = detectControlStructure;
}
public override double OrderUI {
get { return LanguageConstants.IL_ILSPY_ORDERUI; }
}
public override string GenericNameUI {
get { return LanguageConstants.GENERIC_NAMEUI_IL; }
}
public override string UniqueNameUI {
get { return "IL"; }
}
public override Guid GenericGuid {
get { return LanguageConstants.LANGUAGE_IL; }
}
public override Guid UniqueGuid {
get { return LanguageConstants.LANGUAGE_IL_ILSPY; }
}
public override string FileExtension {
get { return ".il"; }
}
ReflectionDisassembler CreateReflectionDisassembler(ITextOutput output, DecompilationContext ctx, IMemberDef member) {
return CreateReflectionDisassembler(output, ctx, member.Module);
}
ReflectionDisassembler CreateReflectionDisassembler(ITextOutput output, DecompilationContext ctx, ModuleDef ownerModule) {
var disOpts = new DisassemblerOptions(ctx.CancellationToken, ownerModule);
if (langSettings.Settings.ShowILComments)
disOpts.GetOpCodeDocumentation = ILLanguageHelper.GetOpCodeDocumentation;
var sb = new StringBuilder();
if (langSettings.Settings.ShowXmlDocumentation)
disOpts.GetXmlDocComments = a => GetXmlDocComments(a, sb);
disOpts.CreateInstructionBytesReader = m => InstructionBytesReader.Create(m, ctx.IsBodyModified != null && ctx.IsBodyModified(m));
disOpts.ShowTokenAndRvaComments = langSettings.Settings.ShowTokenAndRvaComments;
disOpts.ShowILBytes = langSettings.Settings.ShowILBytes;
disOpts.SortMembers = langSettings.Settings.SortMembers;
return new ReflectionDisassembler(output, detectControlStructure, disOpts);
}
static IEnumerable<string> GetXmlDocComments(IMemberRef mr, StringBuilder sb) {
if (mr == null || mr.Module == null)
yield break;
var xmldoc = XmlDocLoader.LoadDocumentation(mr.Module);
if (xmldoc == null)
yield break;
string doc = xmldoc.GetDocumentation(XmlDocKeyProvider.GetKey(mr, sb));
if (string.IsNullOrEmpty(doc))
yield break;
foreach (var info in new XmlDocLine(doc)) {
sb.Clear();
if (info != null) {
sb.Append(' ');
info.Value.WriteTo(sb);
}
yield return sb.ToString();
}
}
public override void Decompile(MethodDef method, ITextOutput output, DecompilationContext ctx) {
var dis = CreateReflectionDisassembler(output, ctx, method);
dis.DisassembleMethod(method);
}
public override void Decompile(FieldDef field, ITextOutput output, DecompilationContext ctx) {
var dis = CreateReflectionDisassembler(output, ctx, field);
dis.DisassembleField(field);
}
public override void Decompile(PropertyDef property, ITextOutput output, DecompilationContext ctx) {
ReflectionDisassembler rd = CreateReflectionDisassembler(output, ctx, property);
rd.DisassembleProperty(property);
if (property.GetMethod != null) {
output.WriteLine();
rd.DisassembleMethod(property.GetMethod);
}
if (property.SetMethod != null) {
output.WriteLine();
rd.DisassembleMethod(property.SetMethod);
}
foreach (var m in property.OtherMethods) {
output.WriteLine();
rd.DisassembleMethod(m);
}
}
public override void Decompile(EventDef ev, ITextOutput output, DecompilationContext ctx) {
ReflectionDisassembler rd = CreateReflectionDisassembler(output, ctx, ev);
rd.DisassembleEvent(ev);
if (ev.AddMethod != null) {
output.WriteLine();
rd.DisassembleMethod(ev.AddMethod);
}
if (ev.RemoveMethod != null) {
output.WriteLine();
rd.DisassembleMethod(ev.RemoveMethod);
}
foreach (var m in ev.OtherMethods) {
output.WriteLine();
rd.DisassembleMethod(m);
}
}
public override void Decompile(TypeDef type, ITextOutput output, DecompilationContext ctx) {
var dis = CreateReflectionDisassembler(output, ctx, type);
dis.DisassembleType(type);
}
public override void Decompile(AssemblyDef asm, ITextOutput output, DecompilationContext ctx) {
output.WriteLine("// " + asm.ManifestModule.Location, TextTokenKind.Comment);
PrintEntryPoint(asm.ManifestModule, output);
output.WriteLine();
ReflectionDisassembler rd = CreateReflectionDisassembler(output, ctx, asm.ManifestModule);
rd.WriteAssemblyHeader(asm);
}
public override void Decompile(ModuleDef mod, ITextOutput output, DecompilationContext ctx) {
output.WriteLine("// " + mod.Location, TextTokenKind.Comment);
PrintEntryPoint(mod, output);
output.WriteLine();
ReflectionDisassembler rd = CreateReflectionDisassembler(output, ctx, mod);
output.WriteLine();
rd.WriteModuleHeader(mod);
}
protected override void TypeToString(ITextOutput output, ITypeDefOrRef t, bool includeNamespace, IHasCustomAttribute attributeProvider = null) {
t.WriteTo(output, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName);
}
public override void WriteToolTip(ISyntaxHighlightOutput output, IMemberRef member, IHasCustomAttribute typeAttributes) {
if (!(member is ITypeDefOrRef) && ILLanguageUtils.Write(SyntaxHighlightOutputToTextOutput.Create(output), member))
return;
base.WriteToolTip(output, member, typeAttributes);
}
}
[Export(typeof(ISimpleILPrinter))]
sealed class ILLanguageUtils : ISimpleILPrinter {
double ISimpleILPrinter.Order {
get { return -100; }
}
bool ISimpleILPrinter.Write(ITextOutput output, IMemberRef member) {
return Write(output, member);
}
void ISimpleILPrinter.Write(ITextOutput output, MethodSig sig) {
output.Write(sig);
}
void ISimpleILPrinter.Write(ITextOutput output, TypeSig type) {
type.WriteTo(output);
}
public static bool Write(ITextOutput output, IMemberRef member) {
var method = member as IMethod;
if (method != null && method.IsMethod) {
method.WriteMethodTo(output);
return true;
}
var field = member as IField;
if (field != null && field.IsField) {
field.WriteFieldTo(output);
return true;
}
var prop = member as PropertyDef;
if (prop != null) {
var dis = new ReflectionDisassembler(output, false, new DisassemblerOptions(new System.Threading.CancellationToken(), null));
dis.DisassembleProperty(prop, false);
return true;
}
var evt = member as EventDef;
if (evt != null) {
var dis = new ReflectionDisassembler(output, false, new DisassemblerOptions(new System.Threading.CancellationToken(), null));
dis.DisassembleEvent(evt, false);
return true;
}
var type = member as ITypeDefOrRef;
if (type != null) {
type.WriteTo(output, ILNameSyntax.TypeName);
return true;
}
return false;
}
}
}

Просмотреть файл

@ -0,0 +1,349 @@
// Copyright (c) 2011 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.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using dnlib.DotNet;
using dnSpy.Contracts.Languages;
using dnSpy.Decompiler.Shared;
using dnSpy.Languages.ILSpy.Settings;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.ILAst;
namespace dnSpy.Languages.ILSpy.ILAst {
sealed class LanguageProvider : ILanguageProvider {
readonly LanguageSettingsManager languageSettingsManager;
// Keep the default ctor. It's used by dnSpy.Console.exe
public LanguageProvider()
: this(LanguageSettingsManager.__Instance_DONT_USE) {
}
public LanguageProvider(LanguageSettingsManager languageSettingsManager) {
Debug.Assert(languageSettingsManager != null);
if (languageSettingsManager == null)
throw new ArgumentNullException();
this.languageSettingsManager = languageSettingsManager;
}
public IEnumerable<ILanguage> Languages {
get {
#if DEBUG
foreach (var l in ILAstLanguage.GetDebugLanguages(languageSettingsManager))
yield return l;
#endif
yield break;
}
}
}
[Export(typeof(ILanguageCreator))]
sealed class MyLanguageCreator : ILanguageCreator {
readonly LanguageSettingsManager languageSettingsManager;
[ImportingConstructor]
MyLanguageCreator(LanguageSettingsManager languageSettingsManager) {
this.languageSettingsManager = languageSettingsManager;
}
public IEnumerable<ILanguage> Create() {
return new LanguageProvider(languageSettingsManager).Languages;
}
}
#if DEBUG
/// <summary>
/// Represents the ILAst "language" used for debugging purposes.
/// </summary>
sealed class ILAstLanguage : Language {
string uniqueNameUI;
Guid uniqueGuid;
bool inlineVariables = true;
ILAstOptimizationStep? abortBeforeStep;
public override IDecompilerSettings Settings {
get { return langSettings; }
}
readonly IDecompilerSettings langSettings;
ILAstLanguage(ILAstLanguageDecompilerSettings langSettings, double orderUI) {
this.langSettings = langSettings;
this.orderUI = orderUI;
}
public override double OrderUI {
get { return orderUI; }
}
readonly double orderUI;
public override string GenericNameUI {
get { return "ILAst"; }
}
public override string UniqueNameUI {
get { return uniqueNameUI; }
}
public override Guid GenericGuid {
get { return LanguageConstants.LANGUAGE_ILAST_ILSPY; }
}
public override Guid UniqueGuid {
get { return uniqueGuid; }
}
public override void Decompile(MethodDef method, ITextOutput output, DecompilationContext ctx) {
WriteCommentBegin(output, true);
output.Write("Method: ", TextTokenKind.Comment);
output.WriteDefinition(IdentifierEscaper.Escape(method.FullName), method, TextTokenKind.Comment, false);
WriteCommentEnd(output, true);
output.WriteLine();
if (!method.HasBody) {
return;
}
StartKeywordBlock(output, ".body", method);
ILAstBuilder astBuilder = new ILAstBuilder();
ILBlock ilMethod = new ILBlock();
DecompilerContext context = new DecompilerContext(method.Module) { CurrentType = method.DeclaringType, CurrentMethod = method };
ilMethod.Body = astBuilder.Build(method, inlineVariables, context);
if (abortBeforeStep != null) {
new ILAstOptimizer().Optimize(context, ilMethod, abortBeforeStep.Value);
}
if (context.CurrentMethodIsAsync) {
output.Write("async", TextTokenKind.Keyword);
output.Write("/", TextTokenKind.Operator);
output.WriteLine("await", TextTokenKind.Keyword);
}
var allVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable)
.Where(v => v != null && !v.IsParameter).Distinct();
foreach (ILVariable v in allVariables) {
output.WriteDefinition(IdentifierEscaper.Escape(v.Name), v, v.IsParameter ? TextTokenKind.Parameter : TextTokenKind.Local);
if (v.Type != null) {
output.WriteSpace();
output.Write(":", TextTokenKind.Operator);
output.WriteSpace();
if (v.IsPinned) {
output.Write("pinned", TextTokenKind.Keyword);
output.WriteSpace();
}
v.Type.WriteTo(output, ILNameSyntax.ShortTypeName);
}
if (v.GeneratedByDecompiler) {
output.WriteSpace();
output.Write("[", TextTokenKind.Operator);
output.Write("generated", TextTokenKind.Keyword);
output.Write("]", TextTokenKind.Operator);
}
output.WriteLine();
}
var memberMapping = new MemberMapping(method);
foreach (ILNode node in ilMethod.Body) {
node.WriteTo(output, memberMapping);
if (!node.WritesNewLine)
output.WriteLine();
}
output.AddDebugSymbols(memberMapping);
EndKeywordBlock(output);
}
void StartKeywordBlock(ITextOutput output, string keyword, IMemberDef member) {
output.Write(keyword, TextTokenKind.Keyword);
output.WriteSpace();
output.WriteDefinition(IdentifierEscaper.Escape(member.Name), member, TextTokenKindUtils.GetTextTokenKind(member), false);
output.WriteSpace();
output.WriteLeftBrace();
output.WriteLine();
output.Indent();
}
void EndKeywordBlock(ITextOutput output) {
output.Unindent();
output.WriteRightBrace();
output.WriteLine();
}
public override void Decompile(EventDef ev, ITextOutput output, DecompilationContext ctx) {
StartKeywordBlock(output, ".event", ev);
if (ev.AddMethod != null) {
StartKeywordBlock(output, ".add", ev.AddMethod);
EndKeywordBlock(output);
}
if (ev.InvokeMethod != null) {
StartKeywordBlock(output, ".invoke", ev.InvokeMethod);
EndKeywordBlock(output);
}
if (ev.RemoveMethod != null) {
StartKeywordBlock(output, ".remove", ev.RemoveMethod);
EndKeywordBlock(output);
}
EndKeywordBlock(output);
}
public override void Decompile(FieldDef field, ITextOutput output, DecompilationContext ctx) {
output.WriteReference(IdentifierEscaper.Escape(field.FieldType.GetFullName()), field.FieldType.ToTypeDefOrRef(), TextTokenKindUtils.GetTextTokenKind(field.FieldType));
output.WriteSpace();
output.WriteDefinition(IdentifierEscaper.Escape(field.Name), field, TextTokenKindUtils.GetTextTokenKind(field), false);
var c = field.Constant;
if (c != null) {
output.WriteSpace();
output.Write("=", TextTokenKind.Operator);
output.WriteSpace();
if (c.Value == null)
output.Write("null", TextTokenKind.Keyword);
else {
switch (c.Type) {
case ElementType.Boolean:
if (c.Value is bool)
output.Write((bool)c.Value ? "true" : "false", TextTokenKind.Keyword);
else
goto default;
break;
case ElementType.Char:
output.Write(string.Format("'{0}'", c.Value), TextTokenKind.Char);
break;
case ElementType.I1:
case ElementType.U1:
case ElementType.I2:
case ElementType.U2:
case ElementType.I4:
case ElementType.U4:
case ElementType.I8:
case ElementType.U8:
case ElementType.R4:
case ElementType.R8:
case ElementType.I:
case ElementType.U:
output.Write(string.Format("{0}", c.Value), TextTokenKind.Number);
break;
case ElementType.String:
output.Write(string.Format("{0}", c.Value), TextTokenKind.String);
break;
default:
output.Write(string.Format("{0}", c.Value), TextTokenKind.Text);
break;
}
}
}
}
public override void Decompile(PropertyDef property, ITextOutput output, DecompilationContext ctx) {
StartKeywordBlock(output, ".property", property);
foreach (var getter in property.GetMethods) {
StartKeywordBlock(output, ".get", getter);
EndKeywordBlock(output);
}
foreach (var setter in property.SetMethods) {
StartKeywordBlock(output, ".set", setter);
EndKeywordBlock(output);
}
foreach (var other in property.OtherMethods) {
StartKeywordBlock(output, ".other", other);
EndKeywordBlock(output);
}
EndKeywordBlock(output);
}
public override void Decompile(TypeDef type, ITextOutput output, DecompilationContext ctx) {
this.WriteCommentLine(output, string.Format("Type: {0}", type.FullName));
if (type.BaseType != null) {
WriteCommentBegin(output, true);
output.Write("Base type: ", TextTokenKind.Comment);
output.WriteReference(IdentifierEscaper.Escape(type.BaseType.FullName), type.BaseType, TextTokenKind.Comment);
WriteCommentEnd(output, true);
output.WriteLine();
}
foreach (var nested in type.NestedTypes) {
Decompile(nested, output, ctx);
output.WriteLine();
}
foreach (var field in type.Fields) {
Decompile(field, output, ctx);
output.WriteLine();
}
foreach (var property in type.Properties) {
Decompile(property, output, ctx);
output.WriteLine();
}
foreach (var @event in type.Events) {
Decompile(@event, output, ctx);
output.WriteLine();
}
foreach (var method in type.Methods) {
Decompile(method, output, ctx);
output.WriteLine();
}
}
internal static IEnumerable<ILAstLanguage> GetDebugLanguages(LanguageSettingsManager languageSettingsManager) {
double orderUI = LanguageConstants.ILAST_ILSPY_DEBUG_ORDERUI;
uint id = 0x64A926A5;
yield return new ILAstLanguage(languageSettingsManager.ILAstLanguageDecompilerSettings, orderUI++) {
uniqueNameUI = "ILAst (unoptimized)",
uniqueGuid = new Guid(string.Format("CB470049-6AFB-4BDB-93DC-1BB9{0:X8}", id++)),
inlineVariables = false
};
string nextName = "ILAst (variable splitting)";
foreach (ILAstOptimizationStep step in Enum.GetValues(typeof(ILAstOptimizationStep))) {
yield return new ILAstLanguage(languageSettingsManager.ILAstLanguageDecompilerSettings, orderUI++) {
uniqueNameUI = nextName,
uniqueGuid = new Guid(string.Format("CB470049-6AFB-4BDB-93DC-1BB9{0:X8}", id++)),
abortBeforeStep = step
};
nextName = "ILAst (after " + step + ")";
}
}
public override string FileExtension {
get {
return ".il";
}
}
protected override void TypeToString(ITextOutput output, ITypeDefOrRef t, bool includeNamespace, IHasCustomAttribute attributeProvider = null) {
t.WriteTo(output, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName);
}
}
#endif
}

Просмотреть файл

@ -0,0 +1,47 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
using System.ComponentModel.Composition;
using dnSpy.Contracts.Plugin;
using dnSpy.Languages.ILSpy.Properties;
namespace dnSpy.Languages.ILSpy {
[ExportPlugin]
sealed class Plugin : IPlugin {
[ImportingConstructor]
Plugin() {
}
public IEnumerable<string> MergedResourceDictionaries {
get { yield return "Themes/wpf.styles.templates.xaml"; }
}
public PluginInfo PluginInfo {
get {
return new PluginInfo {
ShortDescription = dnSpy_Languages_ILSpy_Resources.Plugin_ShortDescription,
};
}
}
public void OnEvent(PluginEvent @event, object obj) {
}
}
}

Просмотреть файл

@ -0,0 +1,14 @@
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Languages.ILSpy.Plugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Languages.ILSpy.Plugin")]
[assembly: AssemblyCopyright("Copyright 2011-2014 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: NeutralResourcesLanguage("en")]

Просмотреть файл

@ -0,0 +1,396 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace dnSpy.Languages.ILSpy.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class dnSpy_Languages_ILSpy_Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal dnSpy_Languages_ILSpy_Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("dnSpy.Languages.ILSpy.Properties.dnSpy.Languages.ILSpy.Resources", typeof(dnSpy_Languages_ILSpy_Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to C# / VB.
/// </summary>
public static string CSharpDecompilerSettingsTabName {
get {
return ResourceManager.GetString("CSharpDecompilerSettingsTabName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Events.
/// </summary>
public static string DecompilationOrder_Events {
get {
return ResourceManager.GetString("DecompilationOrder_Events", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Fields.
/// </summary>
public static string DecompilationOrder_Fields {
get {
return ResourceManager.GetString("DecompilationOrder_Fields", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Methods.
/// </summary>
public static string DecompilationOrder_Methods {
get {
return ResourceManager.GetString("DecompilationOrder_Methods", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Nested Types.
/// </summary>
public static string DecompilationOrder_NestedTypes {
get {
return ResourceManager.GetString("DecompilationOrder_NestedTypes", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Properties.
/// </summary>
public static string DecompilationOrder_Properties {
get {
return ResourceManager.GetString("DecompilationOrder_Properties", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Add using declarations.
/// </summary>
public static string DecompilerSettings_AddUsingDeclarations {
get {
return ResourceManager.GetString("DecompilerSettings_AddUsingDeclarations", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Always generate exception variables in catch blocks.
/// </summary>
public static string DecompilerSettings_AlwaysGenerateExceptionVariableForCatchBlocks {
get {
return ResourceManager.GetString("DecompilerSettings_AlwaysGenerateExceptionVariableForCatchBlocks", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompilation order.
/// </summary>
public static string DecompilerSettings_DecompilationOrder {
get {
return ResourceManager.GetString("DecompilerSettings_DecompilationOrder", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile anonymous methods/lambdas.
/// </summary>
public static string DecompilerSettings_DecompileAnonMethods {
get {
return ResourceManager.GetString("DecompilerSettings_DecompileAnonMethods", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile async methods (async/await).
/// </summary>
public static string DecompilerSettings_DecompileAsyncMethods {
get {
return ResourceManager.GetString("DecompilerSettings_DecompileAsyncMethods", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile automatic events.
/// </summary>
public static string DecompilerSettings_DecompileAutoEvents {
get {
return ResourceManager.GetString("DecompilerSettings_DecompileAutoEvents", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile automatic properties.
/// </summary>
public static string DecompilerSettings_DecompileAutoProps {
get {
return ResourceManager.GetString("DecompilerSettings_DecompileAutoProps", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile enumerators (yield return).
/// </summary>
public static string DecompilerSettings_DecompileEnumerators {
get {
return ResourceManager.GetString("DecompilerSettings_DecompileEnumerators", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile expression trees.
/// </summary>
public static string DecompilerSettings_DecompileExprTrees {
get {
return ResourceManager.GetString("DecompilerSettings_DecompileExprTrees", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile foreach statements.
/// </summary>
public static string DecompilerSettings_DecompileForeachStatements {
get {
return ResourceManager.GetString("DecompilerSettings_DecompileForeachStatements", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile lock statements.
/// </summary>
public static string DecompilerSettings_DecompileLockStatements {
get {
return ResourceManager.GetString("DecompilerSettings_DecompileLockStatements", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile query expressions.
/// </summary>
public static string DecompilerSettings_DecompileQueryExpr {
get {
return ResourceManager.GetString("DecompilerSettings_DecompileQueryExpr", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile switch on string.
/// </summary>
public static string DecompilerSettings_DecompileSwitchOnString {
get {
return ResourceManager.GetString("DecompilerSettings_DecompileSwitchOnString", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile using statements.
/// </summary>
public static string DecompilerSettings_DecompileUsingStatements {
get {
return ResourceManager.GetString("DecompilerSettings_DecompileUsingStatements", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Add namespaces to all types.
/// </summary>
public static string DecompilerSettings_FullyQualifyAllTypes {
get {
return ResourceManager.GetString("DecompilerSettings_FullyQualifyAllTypes", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Add a namespace to types with the same name.
/// </summary>
public static string DecompilerSettings_FullyQualifyAmbiguousTypeNames {
get {
return ResourceManager.GetString("DecompilerSettings_FullyQualifyAmbiguousTypeNames", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use increment and decrement operators.
/// </summary>
public static string DecompilerSettings_IntroduceIncrementAndDecrement {
get {
return ResourceManager.GetString("DecompilerSettings_IntroduceIncrementAndDecrement", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use assignment expressions such as in while ((count = Do()) != 0) ;.
/// </summary>
public static string DecompilerSettings_MakeAssignmentExpressions {
get {
return ResourceManager.GetString("DecompilerSettings_MakeAssignmentExpressions", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Max number of array elements to show.
/// </summary>
public static string DecompilerSettings_MaxArrayElements {
get {
return ResourceManager.GetString("DecompilerSettings_MaxArrayElements", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Decompile object or collection initializers.
/// </summary>
public static string DecompilerSettings_ObjectOrCollectionInitializers {
get {
return ResourceManager.GetString("DecompilerSettings_ObjectOrCollectionInitializers", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Remove empty default constructors.
/// </summary>
public static string DecompilerSettings_RemoveEmptyDefaultCtors {
get {
return ResourceManager.GetString("DecompilerSettings_RemoveEmptyDefaultCtors", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show hidden compiler generated types and methods.
/// </summary>
public static string DecompilerSettings_ShowCompilerGeneratedTypes {
get {
return ResourceManager.GetString("DecompilerSettings_ShowCompilerGeneratedTypes", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show IL opcode comments.
/// </summary>
public static string DecompilerSettings_ShowILComments {
get {
return ResourceManager.GetString("DecompilerSettings_ShowILComments", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show IL instruction bytes.
/// </summary>
public static string DecompilerSettings_ShowILInstrBytes {
get {
return ResourceManager.GetString("DecompilerSettings_ShowILInstrBytes", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show tokens, RVAs and file offsets.
/// </summary>
public static string DecompilerSettings_ShowTokensRvasOffsets {
get {
return ResourceManager.GetString("DecompilerSettings_ShowTokensRvasOffsets", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show XML documentation in decompiled code.
/// </summary>
public static string DecompilerSettings_ShowXMLDocComments {
get {
return ResourceManager.GetString("DecompilerSettings_ShowXMLDocComments", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sort methods, fields, properties, events and types.
/// </summary>
public static string DecompilerSettings_SortMethods {
get {
return ResourceManager.GetString("DecompilerSettings_SortMethods", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Place &apos;System&apos; directives first when sorting usings.
/// </summary>
public static string DecompilerSettings_SortSystemFirst {
get {
return ResourceManager.GetString("DecompilerSettings_SortSystemFirst", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use variable names from debug symbols, if available.
/// </summary>
public static string DecompilerSettings_UseLocalNameFromSyms {
get {
return ResourceManager.GetString("DecompilerSettings_UseLocalNameFromSyms", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to IL.
/// </summary>
public static string ILDecompilerSettingsTabName {
get {
return ResourceManager.GetString("ILDecompilerSettingsTabName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ILSpy decompiler.
/// </summary>
public static string Plugin_ShortDescription {
get {
return ResourceManager.GetString("Plugin_ShortDescription", resourceCulture);
}
}
}
}

Просмотреть файл

@ -0,0 +1,231 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CSharpDecompilerSettingsTabName" xml:space="preserve">
<value>C# / VB</value>
</data>
<data name="DecompilationOrder_Events" xml:space="preserve">
<value>Events</value>
</data>
<data name="DecompilationOrder_Fields" xml:space="preserve">
<value>Fields</value>
</data>
<data name="DecompilationOrder_Methods" xml:space="preserve">
<value>Methods</value>
</data>
<data name="DecompilationOrder_NestedTypes" xml:space="preserve">
<value>Nested Types</value>
</data>
<data name="DecompilationOrder_Properties" xml:space="preserve">
<value>Properties</value>
</data>
<data name="DecompilerSettings_AddUsingDeclarations" xml:space="preserve">
<value>Add using declarations</value>
</data>
<data name="DecompilerSettings_AlwaysGenerateExceptionVariableForCatchBlocks" xml:space="preserve">
<value>Always generate exception variables in catch blocks</value>
</data>
<data name="DecompilerSettings_DecompilationOrder" xml:space="preserve">
<value>Decompilation order</value>
</data>
<data name="DecompilerSettings_DecompileAnonMethods" xml:space="preserve">
<value>Decompile anonymous methods/lambdas</value>
</data>
<data name="DecompilerSettings_DecompileAsyncMethods" xml:space="preserve">
<value>Decompile async methods (async/await)</value>
</data>
<data name="DecompilerSettings_DecompileAutoEvents" xml:space="preserve">
<value>Decompile automatic events</value>
</data>
<data name="DecompilerSettings_DecompileAutoProps" xml:space="preserve">
<value>Decompile automatic properties</value>
</data>
<data name="DecompilerSettings_DecompileEnumerators" xml:space="preserve">
<value>Decompile enumerators (yield return)</value>
</data>
<data name="DecompilerSettings_DecompileExprTrees" xml:space="preserve">
<value>Decompile expression trees</value>
</data>
<data name="DecompilerSettings_DecompileForeachStatements" xml:space="preserve">
<value>Decompile foreach statements</value>
</data>
<data name="DecompilerSettings_DecompileLockStatements" xml:space="preserve">
<value>Decompile lock statements</value>
</data>
<data name="DecompilerSettings_DecompileQueryExpr" xml:space="preserve">
<value>Decompile query expressions</value>
</data>
<data name="DecompilerSettings_DecompileSwitchOnString" xml:space="preserve">
<value>Decompile switch on string</value>
</data>
<data name="DecompilerSettings_DecompileUsingStatements" xml:space="preserve">
<value>Decompile using statements</value>
</data>
<data name="DecompilerSettings_FullyQualifyAllTypes" xml:space="preserve">
<value>Add namespaces to all types</value>
</data>
<data name="DecompilerSettings_FullyQualifyAmbiguousTypeNames" xml:space="preserve">
<value>Add a namespace to types with the same name</value>
</data>
<data name="DecompilerSettings_IntroduceIncrementAndDecrement" xml:space="preserve">
<value>Use increment and decrement operators</value>
</data>
<data name="DecompilerSettings_MakeAssignmentExpressions" xml:space="preserve">
<value>Use assignment expressions such as in while ((count = Do()) != 0) ;</value>
</data>
<data name="DecompilerSettings_MaxArrayElements" xml:space="preserve">
<value>Max number of array elements to show</value>
</data>
<data name="DecompilerSettings_ObjectOrCollectionInitializers" xml:space="preserve">
<value>Decompile object or collection initializers</value>
</data>
<data name="DecompilerSettings_RemoveEmptyDefaultCtors" xml:space="preserve">
<value>Remove empty default constructors</value>
</data>
<data name="DecompilerSettings_ShowCompilerGeneratedTypes" xml:space="preserve">
<value>Show hidden compiler generated types and methods</value>
</data>
<data name="DecompilerSettings_ShowILComments" xml:space="preserve">
<value>Show IL opcode comments</value>
</data>
<data name="DecompilerSettings_ShowILInstrBytes" xml:space="preserve">
<value>Show IL instruction bytes</value>
</data>
<data name="DecompilerSettings_ShowTokensRvasOffsets" xml:space="preserve">
<value>Show tokens, RVAs and file offsets</value>
</data>
<data name="DecompilerSettings_ShowXMLDocComments" xml:space="preserve">
<value>Show XML documentation in decompiled code</value>
</data>
<data name="DecompilerSettings_SortMethods" xml:space="preserve">
<value>Sort methods, fields, properties, events and types</value>
</data>
<data name="DecompilerSettings_SortSystemFirst" xml:space="preserve">
<value>Place 'System' directives first when sorting usings</value>
</data>
<data name="DecompilerSettings_UseLocalNameFromSyms" xml:space="preserve">
<value>Use variable names from debug symbols, if available</value>
</data>
<data name="ILDecompilerSettingsTabName" xml:space="preserve">
<value>IL</value>
</data>
<data name="Plugin_ShortDescription" xml:space="preserve">
<value>ILSpy decompiler</value>
</data>
</root>

Просмотреть файл

@ -0,0 +1,231 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CSharpDecompilerSettingsTabName" xml:space="preserve">
<value>С# / VB</value>
</data>
<data name="DecompilationOrder_Events" xml:space="preserve">
<value>События</value>
</data>
<data name="DecompilationOrder_Fields" xml:space="preserve">
<value>Поля</value>
</data>
<data name="DecompilationOrder_Methods" xml:space="preserve">
<value>Методы</value>
</data>
<data name="DecompilationOrder_NestedTypes" xml:space="preserve">
<value>Вложенные типы</value>
</data>
<data name="DecompilationOrder_Properties" xml:space="preserve">
<value>Свойства</value>
</data>
<data name="DecompilerSettings_AddUsingDeclarations" xml:space="preserve">
<value>Добавить определения using</value>
</data>
<data name="DecompilerSettings_AlwaysGenerateExceptionVariableForCatchBlocks" xml:space="preserve">
<value>Всегда создавать переменные исключений в блоках catch</value>
</data>
<data name="DecompilerSettings_DecompilationOrder" xml:space="preserve">
<value>Порядок декомпиляции</value>
</data>
<data name="DecompilerSettings_DecompileAnonMethods" xml:space="preserve">
<value>Декомпилировать анонимные методы/лямбды</value>
</data>
<data name="DecompilerSettings_DecompileAsyncMethods" xml:space="preserve">
<value>Декомпилировать асинхронные методы (async/await)</value>
</data>
<data name="DecompilerSettings_DecompileAutoEvents" xml:space="preserve">
<value>Декомпилировать автоматические события</value>
</data>
<data name="DecompilerSettings_DecompileAutoProps" xml:space="preserve">
<value>Декомпилировать автоматические свойства</value>
</data>
<data name="DecompilerSettings_DecompileEnumerators" xml:space="preserve">
<value>Декомпилировать перечислители (yield return)</value>
</data>
<data name="DecompilerSettings_DecompileExprTrees" xml:space="preserve">
<value>Декомпилировать деревья выражений</value>
</data>
<data name="DecompilerSettings_DecompileForeachStatements" xml:space="preserve">
<value>Декомпилировать операторы foreach</value>
</data>
<data name="DecompilerSettings_DecompileLockStatements" xml:space="preserve">
<value>Декомпилировать операторы lock</value>
</data>
<data name="DecompilerSettings_DecompileQueryExpr" xml:space="preserve">
<value>Декомпилировать выражения запросов</value>
</data>
<data name="DecompilerSettings_DecompileSwitchOnString" xml:space="preserve">
<value>Декомпилировать switch по строкам</value>
</data>
<data name="DecompilerSettings_DecompileUsingStatements" xml:space="preserve">
<value>Декомпилировать операторы using</value>
</data>
<data name="DecompilerSettings_FullyQualifyAllTypes" xml:space="preserve">
<value>Добавить пространства имен во все типы</value>
</data>
<data name="DecompilerSettings_FullyQualifyAmbiguousTypeNames" xml:space="preserve">
<value>Добавить пространство имен в типы с таким же именем</value>
</data>
<data name="DecompilerSettings_IntroduceIncrementAndDecrement" xml:space="preserve">
<value>Использовать операторы инкремента и декремента</value>
</data>
<data name="DecompilerSettings_MakeAssignmentExpressions" xml:space="preserve">
<value>Использовать выражения присваивания, такие как в while ((count = Do()) != 0);</value>
</data>
<data name="DecompilerSettings_MaxArrayElements" xml:space="preserve">
<value>Максимальное количество отображаемых элементов массива</value>
</data>
<data name="DecompilerSettings_ObjectOrCollectionInitializers" xml:space="preserve">
<value>Декомпилировать инициализаторы объекта или коллекции</value>
</data>
<data name="DecompilerSettings_RemoveEmptyDefaultCtors" xml:space="preserve">
<value>Удалить пустые конструкторы по умолчанию</value>
</data>
<data name="DecompilerSettings_ShowCompilerGeneratedTypes" xml:space="preserve">
<value>Показать скрытые типы и методы, созданные компилятором</value>
</data>
<data name="DecompilerSettings_ShowILComments" xml:space="preserve">
<value>Показать комментарии к IL инструкциям</value>
</data>
<data name="DecompilerSettings_ShowILInstrBytes" xml:space="preserve">
<value>Показывать байты инструкций IL</value>
</data>
<data name="DecompilerSettings_ShowTokensRvasOffsets" xml:space="preserve">
<value>Показывать токены, RVA и смещения в файле</value>
</data>
<data name="DecompilerSettings_ShowXMLDocComments" xml:space="preserve">
<value>Показать документацию XML в декомпилированном коде</value>
</data>
<data name="DecompilerSettings_SortMethods" xml:space="preserve">
<value>Сортировать методы, поля, свойства, события и типы</value>
</data>
<data name="DecompilerSettings_SortSystemFirst" xml:space="preserve">
<value>Поместить директивы 'System' в начало при сортировке</value>
</data>
<data name="DecompilerSettings_UseLocalNameFromSyms" xml:space="preserve">
<value>Использовать имена переменных из отладочных символов, при наличии</value>
</data>
<data name="ILDecompilerSettingsTabName" xml:space="preserve">
<value>IL</value>
</data>
<data name="Plugin_ShortDescription" xml:space="preserve">
<value>Декомпилятор ILSpy</value>
</data>
</root>

Просмотреть файл

@ -0,0 +1,231 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CSharpDecompilerSettingsTabName" xml:space="preserve">
<value>C# / VB</value>
</data>
<data name="DecompilationOrder_Events" xml:space="preserve">
<value>事件</value>
</data>
<data name="DecompilationOrder_Fields" xml:space="preserve">
<value>字段</value>
</data>
<data name="DecompilationOrder_Methods" xml:space="preserve">
<value>方法</value>
</data>
<data name="DecompilationOrder_NestedTypes" xml:space="preserve">
<value>嵌套类</value>
</data>
<data name="DecompilationOrder_Properties" xml:space="preserve">
<value>属性</value>
</data>
<data name="DecompilerSettings_AddUsingDeclarations" xml:space="preserve">
<value>添加using声明</value>
</data>
<data name="DecompilerSettings_AlwaysGenerateExceptionVariableForCatchBlocks" xml:space="preserve">
<value>在catch块中总是生成异常变量</value>
</data>
<data name="DecompilerSettings_DecompilationOrder" xml:space="preserve">
<value>反编译顺序</value>
</data>
<data name="DecompilerSettings_DecompileAnonMethods" xml:space="preserve">
<value>反编译匿名方法/lambda方法</value>
</data>
<data name="DecompilerSettings_DecompileAsyncMethods" xml:space="preserve">
<value>反编译异步方法 (async/await)</value>
</data>
<data name="DecompilerSettings_DecompileAutoEvents" xml:space="preserve">
<value>反编译自动生成的事件</value>
</data>
<data name="DecompilerSettings_DecompileAutoProps" xml:space="preserve">
<value>反编译自动生成的属性</value>
</data>
<data name="DecompilerSettings_DecompileEnumerators" xml:space="preserve">
<value>反编译枚举器yield return</value>
</data>
<data name="DecompilerSettings_DecompileExprTrees" xml:space="preserve">
<value>反编译表达式树Expression Trees</value>
</data>
<data name="DecompilerSettings_DecompileForeachStatements" xml:space="preserve">
<value>反编译foreach语句</value>
</data>
<data name="DecompilerSettings_DecompileLockStatements" xml:space="preserve">
<value>反编译lock语句</value>
</data>
<data name="DecompilerSettings_DecompileQueryExpr" xml:space="preserve">
<value>反编译查询表达式</value>
</data>
<data name="DecompilerSettings_DecompileSwitchOnString" xml:space="preserve">
<value>Decompile switch on string</value>
</data>
<data name="DecompilerSettings_DecompileUsingStatements" xml:space="preserve">
<value>反编译using语句</value>
</data>
<data name="DecompilerSettings_FullyQualifyAllTypes" xml:space="preserve">
<value>将命名空间名添加到所有类型</value>
</data>
<data name="DecompilerSettings_FullyQualifyAmbiguousTypeNames" xml:space="preserve">
<value>将命名空间名添加到具有相同名称的类型</value>
</data>
<data name="DecompilerSettings_IntroduceIncrementAndDecrement" xml:space="preserve">
<value>使用增量和减量运算符</value>
</data>
<data name="DecompilerSettings_MakeAssignmentExpressions" xml:space="preserve">
<value>在流程控制语句中使用赋值表达式如while ((count = Do()) != 0) ;</value>
</data>
<data name="DecompilerSettings_MaxArrayElements" xml:space="preserve">
<value>要显示的数组元素最大数量</value>
</data>
<data name="DecompilerSettings_ObjectOrCollectionInitializers" xml:space="preserve">
<value>反编译对象或集合的初始值设定项</value>
</data>
<data name="DecompilerSettings_RemoveEmptyDefaultCtors" xml:space="preserve">
<value>删除空的默认构造函数</value>
</data>
<data name="DecompilerSettings_ShowCompilerGeneratedTypes" xml:space="preserve">
<value>显示编译器生成的隐藏类型和方法</value>
</data>
<data name="DecompilerSettings_ShowILComments" xml:space="preserve">
<value>显示IL操作码注释</value>
</data>
<data name="DecompilerSettings_ShowILInstrBytes" xml:space="preserve">
<value>显示IL指令字节</value>
</data>
<data name="DecompilerSettings_ShowTokensRvasOffsets" xml:space="preserve">
<value>显示tokenRVA和file offset</value>
</data>
<data name="DecompilerSettings_ShowXMLDocComments" xml:space="preserve">
<value>在反编译的代码中显示 XML 文档</value>
</data>
<data name="DecompilerSettings_SortMethods" xml:space="preserve">
<value>排序方法、 字段、 属性、 事件和类型</value>
</data>
<data name="DecompilerSettings_SortSystemFirst" xml:space="preserve">
<value>在排序using时将System系列置于首位</value>
</data>
<data name="DecompilerSettings_UseLocalNameFromSyms" xml:space="preserve">
<value>如果可用使用debug symbols声明的变量名称</value>
</data>
<data name="ILDecompilerSettingsTabName" xml:space="preserve">
<value>IL</value>
</data>
<data name="Plugin_ShortDescription" xml:space="preserve">
<value>ILSpy 反编译器</value>
</data>
</root>

Просмотреть файл

@ -0,0 +1,220 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using dnSpy.Contracts.Languages;
using dnSpy.Contracts.Settings.Dialog;
using dnSpy.Languages.ILSpy.Properties;
using dnSpy.Shared.MVVM;
using ICSharpCode.Decompiler;
namespace dnSpy.Languages.ILSpy.Settings {
sealed class CSharpDecompilerSettingsTab : IDecompilerSettingsTab, INotifyPropertyChanged {
readonly DecompilerSettings _global_decompilerSettings;
readonly DecompilerSettings decompilerSettings;
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName) {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public double Order {
get { return LanguageConstants.ORDER_DECOMPILER_SETTINGS_ILSPY_CSHARP; }
}
public string Name {
get { return dnSpy_Languages_ILSpy_Resources.CSharpDecompilerSettingsTabName; }
}
public DecompilerSettings Settings {
get { return decompilerSettings; }
}
public object UIObject {
get { return this; }
}
public DecompilationObjectVM[] DecompilationObjectsArray {
get { return decompilationObjectVMs2; }
}
readonly DecompilationObjectVM[] decompilationObjectVMs;
readonly DecompilationObjectVM[] decompilationObjectVMs2;
public DecompilationObjectVM DecompilationObject0 {
get { return decompilationObjectVMs[0]; }
set { SetDecompilationObject(0, value); }
}
public DecompilationObjectVM DecompilationObject1 {
get { return decompilationObjectVMs[1]; }
set { SetDecompilationObject(1, value); }
}
public DecompilationObjectVM DecompilationObject2 {
get { return decompilationObjectVMs[2]; }
set { SetDecompilationObject(2, value); }
}
public DecompilationObjectVM DecompilationObject3 {
get { return decompilationObjectVMs[3]; }
set { SetDecompilationObject(3, value); }
}
public DecompilationObjectVM DecompilationObject4 {
get { return decompilationObjectVMs[4]; }
set { SetDecompilationObject(4, value); }
}
void SetDecompilationObject(int index, DecompilationObjectVM newValue) {
Debug.Assert(newValue != null);
if (newValue == null)
throw new ArgumentNullException();
if (decompilationObjectVMs[index] == newValue)
return;
int otherIndex = Array.IndexOf(decompilationObjectVMs, newValue);
Debug.Assert(otherIndex >= 0);
if (otherIndex >= 0) {
decompilationObjectVMs[otherIndex] = decompilationObjectVMs[index];
decompilationObjectVMs[index] = newValue;
OnPropertyChanged(string.Format("DecompilationObject{0}", otherIndex));
}
OnPropertyChanged(string.Format("DecompilationObject{0}", index));
}
public CSharpDecompilerSettingsTab(DecompilerSettings decompilerSettings) {
this._global_decompilerSettings = decompilerSettings;
this.decompilerSettings = decompilerSettings.Clone();
var defObjs = typeof(DecompilationObject).GetEnumValues().Cast<DecompilationObject>().ToArray();
this.decompilationObjectVMs = new DecompilationObjectVM[defObjs.Length];
for (int i = 0; i < defObjs.Length; i++)
this.decompilationObjectVMs[i] = new DecompilationObjectVM(defObjs[i], ToString(defObjs[i]));
this.decompilationObjectVMs2 = this.decompilationObjectVMs.ToArray();
this.DecompilationObject0 = this.decompilationObjectVMs.First(a => a.Object == decompilerSettings.DecompilationObject0);
this.DecompilationObject1 = this.decompilationObjectVMs.First(a => a.Object == decompilerSettings.DecompilationObject1);
this.DecompilationObject2 = this.decompilationObjectVMs.First(a => a.Object == decompilerSettings.DecompilationObject2);
this.DecompilationObject3 = this.decompilationObjectVMs.First(a => a.Object == decompilerSettings.DecompilationObject3);
this.DecompilationObject4 = this.decompilationObjectVMs.First(a => a.Object == decompilerSettings.DecompilationObject4);
}
static string ToString(DecompilationObject o) {
switch (o) {
case DecompilationObject.NestedTypes: return dnSpy_Languages_ILSpy_Resources.DecompilationOrder_NestedTypes;
case DecompilationObject.Fields: return dnSpy_Languages_ILSpy_Resources.DecompilationOrder_Fields;
case DecompilationObject.Events: return dnSpy_Languages_ILSpy_Resources.DecompilationOrder_Events;
case DecompilationObject.Properties: return dnSpy_Languages_ILSpy_Resources.DecompilationOrder_Properties;
case DecompilationObject.Methods: return dnSpy_Languages_ILSpy_Resources.DecompilationOrder_Methods;
default:
Debug.Fail("Shouldn't be here");
return "???";
}
}
[Flags]
public enum RefreshFlags {
ShowMember = 0x00000001,
ILAst = 0x00000002,
CSharp = 0x00000004,
VB = 0x00000008,
DecompileAll = ILAst | CSharp | VB,
}
public void OnClosed(bool saveSettings, IAppRefreshSettings appRefreshSettings) {
if (!saveSettings)
return;
RefreshFlags flags = 0;
var g = _global_decompilerSettings;
var d = decompilerSettings;
d.DecompilationObject0 = DecompilationObject0.Object;
d.DecompilationObject1 = DecompilationObject1.Object;
d.DecompilationObject2 = DecompilationObject2.Object;
d.DecompilationObject3 = DecompilationObject3.Object;
d.DecompilationObject4 = DecompilationObject4.Object;
if (g.AnonymousMethods != d.AnonymousMethods) flags |= RefreshFlags.ILAst | RefreshFlags.ShowMember;
if (g.ExpressionTrees != d.ExpressionTrees) flags |= RefreshFlags.ILAst;
if (g.YieldReturn != d.YieldReturn) flags |= RefreshFlags.ILAst | RefreshFlags.ShowMember;
if (g.AsyncAwait != d.AsyncAwait) flags |= RefreshFlags.ILAst | RefreshFlags.ShowMember;
if (g.AutomaticProperties != d.AutomaticProperties) flags |= RefreshFlags.CSharp | RefreshFlags.ShowMember;
if (g.AutomaticEvents != d.AutomaticEvents) flags |= RefreshFlags.CSharp | RefreshFlags.ShowMember;
if (g.UsingStatement != d.UsingStatement) flags |= RefreshFlags.CSharp;
if (g.ForEachStatement != d.ForEachStatement) flags |= RefreshFlags.CSharp;
if (g.LockStatement != d.LockStatement) flags |= RefreshFlags.CSharp;
if (g.SwitchStatementOnString != d.SwitchStatementOnString) flags |= RefreshFlags.CSharp | RefreshFlags.ShowMember;
if (g.UsingDeclarations != d.UsingDeclarations) flags |= RefreshFlags.CSharp;
if (g.QueryExpressions != d.QueryExpressions) flags |= RefreshFlags.CSharp;
if (g.FullyQualifyAmbiguousTypeNames != d.FullyQualifyAmbiguousTypeNames) flags |= RefreshFlags.CSharp;
if (g.FullyQualifyAllTypes != d.FullyQualifyAllTypes) flags |= RefreshFlags.CSharp;
if (g.UseDebugSymbols != d.UseDebugSymbols) flags |= RefreshFlags.DecompileAll;
if (g.ObjectOrCollectionInitializers != d.ObjectOrCollectionInitializers) flags |= RefreshFlags.ILAst;
if (g.ShowXmlDocumentation != d.ShowXmlDocumentation) flags |= RefreshFlags.DecompileAll;
if (g.RemoveEmptyDefaultConstructors != d.RemoveEmptyDefaultConstructors) flags |= RefreshFlags.CSharp;
if (g.IntroduceIncrementAndDecrement != d.IntroduceIncrementAndDecrement) flags |= RefreshFlags.ILAst;
if (g.MakeAssignmentExpressions != d.MakeAssignmentExpressions) flags |= RefreshFlags.ILAst;
if (g.AlwaysGenerateExceptionVariableForCatchBlocks != d.AlwaysGenerateExceptionVariableForCatchBlocks) flags |= RefreshFlags.ILAst;
if (g.ShowTokenAndRvaComments != d.ShowTokenAndRvaComments) flags |= RefreshFlags.DecompileAll;
if (g.DecompilationObject0 != d.DecompilationObject0) flags |= RefreshFlags.CSharp;
if (g.DecompilationObject1 != d.DecompilationObject1) flags |= RefreshFlags.CSharp;
if (g.DecompilationObject2 != d.DecompilationObject2) flags |= RefreshFlags.CSharp;
if (g.DecompilationObject3 != d.DecompilationObject3) flags |= RefreshFlags.CSharp;
if (g.DecompilationObject4 != d.DecompilationObject4) flags |= RefreshFlags.CSharp;
if (g.SortMembers != d.SortMembers) flags |= RefreshFlags.CSharp;
if (g.ForceShowAllMembers != d.ForceShowAllMembers) flags |= RefreshFlags.CSharp | RefreshFlags.ShowMember;
if (g.SortSystemUsingStatementsFirst != d.SortSystemUsingStatementsFirst) flags |= RefreshFlags.CSharp;
if (g.MaxArrayElements != d.MaxArrayElements) flags |= RefreshFlags.CSharp;
if ((flags & RefreshFlags.ShowMember) != 0)
appRefreshSettings.Add(AppSettingsConstants.REFRESH_LANGUAGE_SHOWMEMBER);
if ((flags & RefreshFlags.ILAst) != 0)
appRefreshSettings.Add(SettingsConstants.REDECOMPILE_ILAST_ILSPY_CODE);
if ((flags & RefreshFlags.CSharp) != 0)
appRefreshSettings.Add(SettingsConstants.REDECOMPILE_CSHARP_ILSPY_CODE);
if ((flags & RefreshFlags.VB) != 0)
appRefreshSettings.Add(SettingsConstants.REDECOMPILE_VB_ILSPY_CODE);
decompilerSettings.CopyTo(_global_decompilerSettings);
}
}
sealed class DecompilationObjectVM : ViewModelBase {
public DecompilationObject Object {
get { return decompilationObject; }
}
readonly DecompilationObject decompilationObject;
public string Text {
get { return text; }
}
readonly string text;
public DecompilationObjectVM(DecompilationObject decompilationObject, string text) {
this.decompilationObject = decompilationObject;
this.text = text;
}
}
}

Просмотреть файл

@ -0,0 +1,75 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using dnSpy.Contracts.Files.Tabs;
using dnSpy.Contracts.Languages;
using dnSpy.Contracts.Settings.Dialog;
namespace dnSpy.Languages.ILSpy.Settings {
[ExportAppSettingsModifiedListener(Order = AppSettingsConstants.ORDER_SETTINGS_LISTENER_DECOMPILER)]
sealed class DecompilerAppSettingsModifiedListener : IAppSettingsModifiedListener {
readonly IFileTabManager fileTabManager;
[ImportingConstructor]
DecompilerAppSettingsModifiedListener(IFileTabManager fileTabManager) {
this.fileTabManager = fileTabManager;
}
public void OnSettingsModified(IAppRefreshSettings appRefreshSettings) {
bool refreshIL = appRefreshSettings.Has(SettingsConstants.REDISASSEMBLE_IL_ILSPY_CODE);
bool refreshILAst = appRefreshSettings.Has(SettingsConstants.REDECOMPILE_ILAST_ILSPY_CODE);
bool refreshCSharp = appRefreshSettings.Has(SettingsConstants.REDECOMPILE_CSHARP_ILSPY_CODE);
bool refreshVB = appRefreshSettings.Has(SettingsConstants.REDECOMPILE_VB_ILSPY_CODE);
if (refreshILAst)
refreshCSharp = refreshVB = true;
if (refreshCSharp)
refreshVB = true;
if (refreshIL)
RefreshCode<IL.ILLanguage>();
#if DEBUG
if (refreshILAst)
RefreshCode<ILAst.ILAstLanguage>();
#endif
if (refreshCSharp)
RefreshCode<CSharp.CSharpLanguage>();
if (refreshVB)
RefreshCode<VB.VBLanguage>();
}
IEnumerable<Tuple<IFileTab, ILanguage>> LanguageTabs {
get {
foreach (var tab in fileTabManager.VisibleFirstTabs) {
var langContent = tab.Content as ILanguageTabContent;
var lang = langContent == null ? null : langContent.Language;
if (lang != null)
yield return Tuple.Create(tab, lang);
}
}
}
void RefreshCode<T>() {
fileTabManager.Refresh(LanguageTabs.Where(t => t.Item2 is T).Select(a => a.Item1).ToArray());
}
}
}

Просмотреть файл

@ -0,0 +1,115 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.ComponentModel.Composition;
using dnSpy.Contracts.Settings;
using ICSharpCode.Decompiler;
namespace dnSpy.Languages.ILSpy.Settings {
[Export, PartCreationPolicy(CreationPolicy.Shared)]
sealed class DecompilerSettingsImpl : DecompilerSettings {
static readonly Guid SETTINGS_GUID = new Guid("6745457F-254B-4B7B-90F1-F948F0721C3B");
readonly ISettingsManager settingsManager;
[ImportingConstructor]
DecompilerSettingsImpl(ISettingsManager settingsManager) {
this.settingsManager = settingsManager;
this.disableSave = true;
var sect = settingsManager.GetOrCreateSection(SETTINGS_GUID);
// Only read those settings that can be changed in the dialog box
this.DecompilationObject0 = sect.Attribute<DecompilationObject?>("DecompilationObject0") ?? this.DecompilationObject0;
this.DecompilationObject1 = sect.Attribute<DecompilationObject?>("DecompilationObject1") ?? this.DecompilationObject1;
this.DecompilationObject2 = sect.Attribute<DecompilationObject?>("DecompilationObject2") ?? this.DecompilationObject2;
this.DecompilationObject3 = sect.Attribute<DecompilationObject?>("DecompilationObject3") ?? this.DecompilationObject3;
this.DecompilationObject4 = sect.Attribute<DecompilationObject?>("DecompilationObject4") ?? this.DecompilationObject4;
this.AnonymousMethods = sect.Attribute<bool?>("AnonymousMethods") ?? this.AnonymousMethods;
this.ExpressionTrees = sect.Attribute<bool?>("ExpressionTrees") ?? this.ExpressionTrees;
this.YieldReturn = sect.Attribute<bool?>("YieldReturn") ?? this.YieldReturn;
this.AsyncAwait = sect.Attribute<bool?>("AsyncAwait") ?? this.AsyncAwait;
// this.AutomaticProperties = sect.Attribute<bool?>("AutomaticProperties") ?? this.AutomaticProperties;
// this.AutomaticEvents = sect.Attribute<bool?>("AutomaticEvents") ?? this.AutomaticEvents;
// this.UsingStatement = sect.Attribute<bool?>("UsingStatement") ?? this.UsingStatement;
// this.ForEachStatement = sect.Attribute<bool?>("ForEachStatement") ?? this.ForEachStatement;
// this.LockStatement = sect.Attribute<bool?>("LockStatement") ?? this.LockStatement;
// this.SwitchStatementOnString = sect.Attribute<bool?>("SwitchStatementOnString") ?? this.SwitchStatementOnString;
// this.UsingDeclarations = sect.Attribute<bool?>("UsingDeclarations") ?? this.UsingDeclarations;
this.QueryExpressions = sect.Attribute<bool?>("QueryExpressions") ?? this.QueryExpressions;
// this.FullyQualifyAmbiguousTypeNames = sect.Attribute<bool?>("FullyQualifyAmbiguousTypeNames") ?? this.FullyQualifyAmbiguousTypeNames;
// this.FullyQualifyAllTypes = sect.Attribute<bool?>("FullyQualifyAllTypes") ?? this.FullyQualifyAllTypes;
this.UseDebugSymbols = sect.Attribute<bool?>("UseDebugSymbols") ?? this.UseDebugSymbols;
// this.ObjectOrCollectionInitializers = sect.Attribute<bool?>("ObjectOrCollectionInitializers") ?? this.ObjectOrCollectionInitializers;
this.ShowXmlDocumentation = sect.Attribute<bool?>("ShowXmlDocumentation") ?? this.ShowXmlDocumentation;
this.RemoveEmptyDefaultConstructors = sect.Attribute<bool?>("RemoveEmptyDefaultConstructors") ?? this.RemoveEmptyDefaultConstructors;
// this.IntroduceIncrementAndDecrement = sect.Attribute<bool?>("IntroduceIncrementAndDecrement") ?? this.IntroduceIncrementAndDecrement;
// this.MakeAssignmentExpressions = sect.Attribute<bool?>("MakeAssignmentExpressions") ?? this.MakeAssignmentExpressions;
// this.AlwaysGenerateExceptionVariableForCatchBlocks = sect.Attribute<bool?>("AlwaysGenerateExceptionVariableForCatchBlocks") ?? this.AlwaysGenerateExceptionVariableForCatchBlocks;
this.ShowTokenAndRvaComments = sect.Attribute<bool?>("ShowTokenAndRvaComments") ?? this.ShowTokenAndRvaComments;
this.SortMembers = sect.Attribute<bool?>("SortMembers") ?? this.SortMembers;
this.ForceShowAllMembers = sect.Attribute<bool?>("ForceShowAllMembers") ?? this.ForceShowAllMembers;
this.SortSystemUsingStatementsFirst = sect.Attribute<bool?>("SortSystemUsingStatementsFirst") ?? this.SortSystemUsingStatementsFirst;
// this.MaxArrayElements = sect.Attribute<int?>("MaxArrayElements") ?? this.MaxArrayElements;
//TODO: CSharpFormattingOptions
this.disableSave = false;
}
readonly bool disableSave;
protected override void OnModified() {
if (disableSave)
return;
var sect = settingsManager.RecreateSection(SETTINGS_GUID);
// Only save those settings that can be changed in the dialog box
sect.Attribute("DecompilationObject0", DecompilationObject0);
sect.Attribute("DecompilationObject1", DecompilationObject1);
sect.Attribute("DecompilationObject2", DecompilationObject2);
sect.Attribute("DecompilationObject3", DecompilationObject3);
sect.Attribute("DecompilationObject4", DecompilationObject4);
sect.Attribute("AnonymousMethods", AnonymousMethods);
sect.Attribute("ExpressionTrees", ExpressionTrees);
sect.Attribute("YieldReturn", YieldReturn);
sect.Attribute("AsyncAwait", AsyncAwait);
// sect.Attribute("AutomaticProperties", AutomaticProperties);
// sect.Attribute("AutomaticEvents", AutomaticEvents);
// sect.Attribute("UsingStatement", UsingStatement);
// sect.Attribute("ForEachStatement", ForEachStatement);
// sect.Attribute("LockStatement", LockStatement);
// sect.Attribute("SwitchStatementOnString", SwitchStatementOnString);
// sect.Attribute("UsingDeclarations", UsingDeclarations);
sect.Attribute("QueryExpressions", QueryExpressions);
// sect.Attribute("FullyQualifyAmbiguousTypeNames", FullyQualifyAmbiguousTypeNames);
// sect.Attribute("FullyQualifyAllTypes", FullyQualifyAllTypes);
sect.Attribute("UseDebugSymbols", UseDebugSymbols);
// sect.Attribute("ObjectOrCollectionInitializers", ObjectOrCollectionInitializers);
sect.Attribute("ShowXmlDocumentation", ShowXmlDocumentation);
sect.Attribute("RemoveEmptyDefaultConstructors", RemoveEmptyDefaultConstructors);
// sect.Attribute("IntroduceIncrementAndDecrement", IntroduceIncrementAndDecrement);
// sect.Attribute("MakeAssignmentExpressions", MakeAssignmentExpressions);
// sect.Attribute("AlwaysGenerateExceptionVariableForCatchBlocks", AlwaysGenerateExceptionVariableForCatchBlocks);
sect.Attribute("ShowTokenAndRvaComments", ShowTokenAndRvaComments);
sect.Attribute("SortMembers", SortMembers);
sect.Attribute("ForceShowAllMembers", ForceShowAllMembers);
sect.Attribute("SortSystemUsingStatementsFirst", SortSystemUsingStatementsFirst);
// sect.Attribute("MaxArrayElements", MaxArrayElements);
//TODO: CSharpFormattingOptions
}
}
}

Просмотреть файл

@ -0,0 +1,42 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
using System.ComponentModel.Composition;
using dnSpy.Contracts.Languages;
using ICSharpCode.Decompiler;
namespace dnSpy.Languages.ILSpy.Settings {
[Export(typeof(IDecompilerSettingsTabCreator))]
sealed class DecompilerSettingsTabCreator : IDecompilerSettingsTabCreator {
readonly DecompilerSettings decompilerSettings;
readonly ILSettingsImpl ilSettings;
[ImportingConstructor]
DecompilerSettingsTabCreator(DecompilerSettingsImpl decompilerSettings, ILSettingsImpl ilSettings) {
this.decompilerSettings = decompilerSettings;
this.ilSettings = ilSettings;
}
public IEnumerable<IDecompilerSettingsTab> Create() {
yield return new CSharpDecompilerSettingsTab(decompilerSettings);
yield return new ILDecompilerSettingsTab(ilSettings);
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
#if DEBUG
using System.Collections.Generic;
using dnSpy.Contracts.Languages;
namespace dnSpy.Languages.ILSpy.Settings {
sealed class ILAstLanguageDecompilerSettings : IDecompilerSettings {
public ILAstLanguageDecompilerSettings() {
}
ILAstLanguageDecompilerSettings(ILAstLanguageDecompilerSettings other) {
}
public IDecompilerSettings Clone() {
return new ILAstLanguageDecompilerSettings(this);
}
public IEnumerable<IDecompilerOption> Options {
get { yield break; }
}
public override bool Equals(object obj) {
return obj is ILAstLanguageDecompilerSettings;
}
public override int GetHashCode() {
return 0;
}
}
}
#endif

Просмотреть файл

@ -0,0 +1,67 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel;
using dnSpy.Contracts.Languages;
using dnSpy.Contracts.Settings.Dialog;
using dnSpy.Languages.ILSpy.Properties;
namespace dnSpy.Languages.ILSpy.Settings {
sealed class ILDecompilerSettingsTab : IDecompilerSettingsTab, INotifyPropertyChanged {
readonly ILSettings _global_ilSettings;
readonly ILSettings ilSettings;
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName) {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public double Order {
get { return LanguageConstants.ORDER_DECOMPILER_SETTINGS_ILSPY_IL; }
}
public string Name {
get { return dnSpy_Languages_ILSpy_Resources.ILDecompilerSettingsTabName; }
}
public ILSettings Settings {
get { return ilSettings; }
}
public object UIObject {
get { return this; }
}
public ILDecompilerSettingsTab(ILSettings ilSettings) {
this._global_ilSettings = ilSettings;
this.ilSettings = ilSettings.Clone();
}
public void OnClosed(bool saveSettings, IAppRefreshSettings appRefreshSettings) {
if (!saveSettings)
return;
if (!_global_ilSettings.Equals(ilSettings))
appRefreshSettings.Add(SettingsConstants.REDISASSEMBLE_IL_ILSPY_CODE);
ilSettings.CopyTo(_global_ilSettings);
}
}
}

Просмотреть файл

@ -0,0 +1,84 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
using System.Linq;
using dnSpy.Contracts.Languages;
using dnSpy.Languages.ILSpy.Properties;
using dnSpy.Languages.Settings;
namespace dnSpy.Languages.ILSpy.Settings {
sealed class ILLanguageDecompilerSettings : IDecompilerSettings {
public ILSettings Settings {
get { return ilSettings; }
}
readonly ILSettings ilSettings;
public ILLanguageDecompilerSettings(ILSettings ilSettings = null) {
this.ilSettings = ilSettings ?? new ILSettings();
this.options = CreateOptions().ToArray();
}
public IDecompilerSettings Clone() {
return new ILLanguageDecompilerSettings(this.ilSettings.Clone());
}
public IEnumerable<IDecompilerOption> Options {
get { return options.AsEnumerable(); }
}
readonly IDecompilerOption[] options;
IEnumerable<IDecompilerOption> CreateOptions() {
yield return new DecompilerOption<bool>(DecompilerOptionConstants.ShowILComments_GUID,
() => ilSettings.ShowILComments, a => ilSettings.ShowILComments = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowILComments,
Name = DecompilerOptionConstants.ShowILComments_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.ShowXmlDocumentation_GUID,
() => ilSettings.ShowXmlDocumentation, a => ilSettings.ShowXmlDocumentation = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowXMLDocComments,
Name = DecompilerOptionConstants.ShowXmlDocumentation_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.ShowTokenAndRvaComments_GUID,
() => ilSettings.ShowTokenAndRvaComments, a => ilSettings.ShowTokenAndRvaComments = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowTokensRvasOffsets,
Name = DecompilerOptionConstants.ShowTokenAndRvaComments_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.ShowILBytes_GUID,
() => ilSettings.ShowILBytes, a => ilSettings.ShowILBytes = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowILInstrBytes,
Name = DecompilerOptionConstants.ShowILBytes_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.SortMembers_GUID,
() => ilSettings.SortMembers, a => ilSettings.SortMembers = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_SortMethods,
Name = DecompilerOptionConstants.SortMembers_NAME,
};
}
public override bool Equals(object obj) {
return obj is ILLanguageDecompilerSettings &&
ilSettings.Equals(((ILLanguageDecompilerSettings)obj).ilSettings);
}
public override int GetHashCode() {
return ilSettings.GetHashCode();
}
}
}

Просмотреть файл

@ -0,0 +1,159 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.ComponentModel.Composition;
using dnSpy.Contracts.Settings;
using dnSpy.Shared.MVVM;
namespace dnSpy.Languages.ILSpy.Settings {
class ILSettings : ViewModelBase {
protected virtual void OnModified() {
}
public bool ShowILComments {
get { return showILComments; }
set {
if (showILComments != value) {
showILComments = value;
OnPropertyChanged("ShowILComments");
OnModified();
}
}
}
bool showILComments = false;
public bool ShowXmlDocumentation {
get { return showXmlDocumentation; }
set {
if (showXmlDocumentation != value) {
showXmlDocumentation = value;
OnPropertyChanged("ShowXmlDocumentation");
OnModified();
}
}
}
bool showXmlDocumentation = true;
public bool ShowTokenAndRvaComments {
get { return showTokenAndRvaComments; }
set {
if (showTokenAndRvaComments != value) {
showTokenAndRvaComments = value;
OnPropertyChanged("ShowTokenAndRvaComments");
OnModified();
}
}
}
bool showTokenAndRvaComments = true;
public bool ShowILBytes {
get { return showILBytes; }
set {
if (showILBytes != value) {
showILBytes = value;
OnPropertyChanged("ShowILBytes");
OnModified();
}
}
}
bool showILBytes = true;
public bool SortMembers {
get { return sortMembers; }
set {
if (sortMembers != value) {
sortMembers = value;
OnPropertyChanged("SortMembers");
OnModified();
}
}
}
bool sortMembers = true;
public ILSettings Clone() {
return CopyTo(new ILSettings());
}
public ILSettings CopyTo(ILSettings other) {
other.ShowILComments = this.ShowILComments;
other.ShowXmlDocumentation = this.ShowXmlDocumentation;
other.ShowTokenAndRvaComments = this.ShowTokenAndRvaComments;
other.ShowILBytes = this.ShowILBytes;
other.SortMembers = this.SortMembers;
return other;
}
public override bool Equals(object obj) {
var other = obj as ILSettings;
return other != null &&
ShowILComments == other.ShowILComments &&
ShowXmlDocumentation == other.ShowXmlDocumentation &&
ShowTokenAndRvaComments == other.ShowTokenAndRvaComments &&
ShowILBytes == other.ShowILBytes &&
SortMembers == other.SortMembers;
}
public override int GetHashCode() {
uint h = 0;
if (ShowILComments) h ^= 0x80000000;
if (ShowXmlDocumentation) h ^= 0x40000000;
if (ShowTokenAndRvaComments) h ^= 0x20000000;
if (ShowILBytes) h ^= 0x10000000;
if (SortMembers) h ^= 0x08000000;
return (int)h;
}
}
[Export, PartCreationPolicy(CreationPolicy.Shared)]
sealed class ILSettingsImpl : ILSettings {
static readonly Guid SETTINGS_GUID = new Guid("DD6752B1-5336-4601-A9B2-0879E18AE9F3");
readonly ISettingsManager settingsManager;
[ImportingConstructor]
ILSettingsImpl(ISettingsManager settingsManager) {
this.settingsManager = settingsManager;
this.disableSave = true;
var sect = settingsManager.GetOrCreateSection(SETTINGS_GUID);
this.ShowILComments = sect.Attribute<bool?>("ShowILComments") ?? this.ShowILComments;
this.ShowXmlDocumentation = sect.Attribute<bool?>("ShowXmlDocumentation") ?? this.ShowXmlDocumentation;
this.ShowTokenAndRvaComments = sect.Attribute<bool?>("ShowTokenAndRvaComments") ?? this.ShowTokenAndRvaComments;
this.ShowILBytes = sect.Attribute<bool?>("ShowILBytes") ?? this.ShowILBytes;
this.SortMembers = sect.Attribute<bool?>("SortMembers") ?? this.SortMembers;
this.disableSave = false;
}
readonly bool disableSave;
protected override void OnModified() {
if (disableSave)
return;
var sect = settingsManager.RecreateSection(SETTINGS_GUID);
sect.Attribute("ShowILComments", ShowILComments);
sect.Attribute("ShowXmlDocumentation", ShowXmlDocumentation);
sect.Attribute("ShowTokenAndRvaComments", ShowTokenAndRvaComments);
sect.Attribute("ShowILBytes", ShowILBytes);
sect.Attribute("SortMembers", SortMembers);
}
}
}

Просмотреть файл

@ -0,0 +1,239 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using dnSpy.Contracts.Languages;
using dnSpy.Languages.ILSpy.Properties;
using dnSpy.Languages.Settings;
using ICSharpCode.Decompiler;
namespace dnSpy.Languages.ILSpy.Settings {
sealed class LanguageDecompilerSettings : IDecompilerSettings {
public DecompilerSettings Settings {
get { return decompilerSettings; }
}
readonly DecompilerSettings decompilerSettings;
public LanguageDecompilerSettings(DecompilerSettings decompilerSettings = null) {
this.decompilerSettings = decompilerSettings ?? new DecompilerSettings();
this.options = CreateOptions().ToArray();
}
public IDecompilerSettings Clone() {
return new LanguageDecompilerSettings(this.decompilerSettings.Clone());
}
public IEnumerable<IDecompilerOption> Options {
get { return options.AsEnumerable(); }
}
readonly IDecompilerOption[] options;
IEnumerable<IDecompilerOption> CreateOptions() {
yield return new DecompilerOption<string>(DecompilerOptionConstants.MemberOrder_GUID,
() => GetMemberOrder(), a => SetMemberOrder(a)) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompilationOrder,
Name = DecompilerOptionConstants.MemberOrder_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.AnonymousMethods_GUID,
() => decompilerSettings.AnonymousMethods, a => decompilerSettings.AnonymousMethods = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileAnonMethods,
Name = DecompilerOptionConstants.AnonymousMethods_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.ExpressionTrees_GUID,
() => decompilerSettings.ExpressionTrees, a => decompilerSettings.ExpressionTrees = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileExprTrees,
Name = DecompilerOptionConstants.ExpressionTrees_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.YieldReturn_GUID,
() => decompilerSettings.YieldReturn, a => decompilerSettings.YieldReturn = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileEnumerators,
Name = DecompilerOptionConstants.YieldReturn_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.AsyncAwait_GUID,
() => decompilerSettings.AsyncAwait, a => decompilerSettings.AsyncAwait = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileAsyncMethods,
Name = DecompilerOptionConstants.AsyncAwait_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.AutomaticProperties_GUID,
() => decompilerSettings.AutomaticProperties, a => decompilerSettings.AutomaticProperties = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileAutoProps,
Name = DecompilerOptionConstants.AutomaticProperties_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.AutomaticEvents_GUID,
() => decompilerSettings.AutomaticEvents, a => decompilerSettings.AutomaticEvents = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileAutoEvents,
Name = DecompilerOptionConstants.AutomaticEvents_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.UsingStatement_GUID,
() => decompilerSettings.UsingStatement, a => decompilerSettings.UsingStatement = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileUsingStatements,
Name = DecompilerOptionConstants.UsingStatement_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.ForEachStatement_GUID,
() => decompilerSettings.ForEachStatement, a => decompilerSettings.ForEachStatement = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileForeachStatements,
Name = DecompilerOptionConstants.ForEachStatement_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.LockStatement_GUID,
() => decompilerSettings.LockStatement, a => decompilerSettings.LockStatement = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileLockStatements,
Name = DecompilerOptionConstants.LockStatement_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.SwitchStatementOnString_GUID,
() => decompilerSettings.SwitchStatementOnString, a => decompilerSettings.SwitchStatementOnString = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileSwitchOnString,
Name = DecompilerOptionConstants.SwitchStatementOnString_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.UsingDeclarations_GUID,
() => decompilerSettings.UsingDeclarations, a => decompilerSettings.UsingDeclarations = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_AddUsingDeclarations,
Name = DecompilerOptionConstants.UsingDeclarations_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.QueryExpressions_GUID,
() => decompilerSettings.QueryExpressions, a => decompilerSettings.QueryExpressions = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileQueryExpr,
Name = DecompilerOptionConstants.QueryExpressions_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.FullyQualifyAmbiguousTypeNames_GUID,
() => decompilerSettings.FullyQualifyAmbiguousTypeNames, a => decompilerSettings.FullyQualifyAmbiguousTypeNames = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_FullyQualifyAmbiguousTypeNames,
Name = DecompilerOptionConstants.FullyQualifyAmbiguousTypeNames_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.FullyQualifyAllTypes_GUID,
() => decompilerSettings.FullyQualifyAllTypes, a => decompilerSettings.FullyQualifyAllTypes = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_FullyQualifyAllTypes,
Name = DecompilerOptionConstants.FullyQualifyAllTypes_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.UseDebugSymbols_GUID,
() => decompilerSettings.UseDebugSymbols, a => decompilerSettings.UseDebugSymbols = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_UseLocalNameFromSyms,
Name = DecompilerOptionConstants.UseDebugSymbols_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.ObjectOrCollectionInitializers_GUID,
() => decompilerSettings.ObjectOrCollectionInitializers, a => decompilerSettings.ObjectOrCollectionInitializers = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ObjectOrCollectionInitializers,
Name = DecompilerOptionConstants.ObjectOrCollectionInitializers_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.ShowXmlDocumentation_GUID,
() => decompilerSettings.ShowXmlDocumentation, a => decompilerSettings.ShowXmlDocumentation = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowXMLDocComments,
Name = DecompilerOptionConstants.ShowXmlDocumentation_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.RemoveEmptyDefaultConstructors_GUID,
() => decompilerSettings.RemoveEmptyDefaultConstructors, a => decompilerSettings.RemoveEmptyDefaultConstructors = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_RemoveEmptyDefaultCtors,
Name = DecompilerOptionConstants.RemoveEmptyDefaultConstructors_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.IntroduceIncrementAndDecrement_GUID,
() => decompilerSettings.IntroduceIncrementAndDecrement, a => decompilerSettings.IntroduceIncrementAndDecrement = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_IntroduceIncrementAndDecrement,
Name = DecompilerOptionConstants.IntroduceIncrementAndDecrement_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.MakeAssignmentExpressions_GUID,
() => decompilerSettings.MakeAssignmentExpressions, a => decompilerSettings.MakeAssignmentExpressions = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_MakeAssignmentExpressions,
Name = DecompilerOptionConstants.MakeAssignmentExpressions_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.AlwaysGenerateExceptionVariableForCatchBlocks_GUID,
() => decompilerSettings.AlwaysGenerateExceptionVariableForCatchBlocks, a => decompilerSettings.AlwaysGenerateExceptionVariableForCatchBlocks = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_AlwaysGenerateExceptionVariableForCatchBlocks,
Name = DecompilerOptionConstants.AlwaysGenerateExceptionVariableForCatchBlocks_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.ShowTokenAndRvaComments_GUID,
() => decompilerSettings.ShowTokenAndRvaComments, a => decompilerSettings.ShowTokenAndRvaComments = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowTokensRvasOffsets,
Name = DecompilerOptionConstants.ShowTokenAndRvaComments_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.SortMembers_GUID,
() => decompilerSettings.SortMembers, a => decompilerSettings.SortMembers = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_SortMethods,
Name = DecompilerOptionConstants.SortMembers_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.ForceShowAllMembers_GUID,
() => decompilerSettings.ForceShowAllMembers, a => decompilerSettings.ForceShowAllMembers = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowCompilerGeneratedTypes,
Name = DecompilerOptionConstants.ForceShowAllMembers_NAME,
};
yield return new DecompilerOption<bool>(DecompilerOptionConstants.SortSystemUsingStatementsFirst_GUID,
() => decompilerSettings.SortSystemUsingStatementsFirst, a => decompilerSettings.SortSystemUsingStatementsFirst = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_SortSystemFirst,
Name = DecompilerOptionConstants.SortSystemUsingStatementsFirst_NAME,
};
yield return new DecompilerOption<int>(DecompilerOptionConstants.MaxArrayElements_GUID,
() => decompilerSettings.MaxArrayElements, a => decompilerSettings.MaxArrayElements = a) {
Description = dnSpy_Languages_ILSpy_Resources.DecompilerSettings_MaxArrayElements,
Name = DecompilerOptionConstants.MaxArrayElements_NAME,
};
}
string GetMemberOrder() {
return GetMemberOrderString(decompilerSettings.DecompilationObject0) +
GetMemberOrderString(decompilerSettings.DecompilationObject1) +
GetMemberOrderString(decompilerSettings.DecompilationObject2) +
GetMemberOrderString(decompilerSettings.DecompilationObject3) +
GetMemberOrderString(decompilerSettings.DecompilationObject4);
}
static string GetMemberOrderString(DecompilationObject d) {
switch (d) {
case DecompilationObject.NestedTypes: return "t";
case DecompilationObject.Fields: return "f";
case DecompilationObject.Events: return "e";
case DecompilationObject.Properties: return "p";
case DecompilationObject.Methods: return "m";
default:
Debug.Fail("Shouldn't be here");
return "?";
}
}
void SetMemberOrder(string s) {
if (s == null || s.Length != 5)
return;
decompilerSettings.DecompilationObject0 = GetDecompilationObject(s[0]) ?? decompilerSettings.DecompilationObject0;
decompilerSettings.DecompilationObject1 = GetDecompilationObject(s[1]) ?? decompilerSettings.DecompilationObject1;
decompilerSettings.DecompilationObject2 = GetDecompilationObject(s[2]) ?? decompilerSettings.DecompilationObject2;
decompilerSettings.DecompilationObject3 = GetDecompilationObject(s[3]) ?? decompilerSettings.DecompilationObject3;
decompilerSettings.DecompilationObject4 = GetDecompilationObject(s[4]) ?? decompilerSettings.DecompilationObject4;
}
static DecompilationObject? GetDecompilationObject(char c) {
switch (c) {
case 't': return DecompilationObject.NestedTypes;
case 'f': return DecompilationObject.Fields;
case 'e': return DecompilationObject.Events;
case 'p': return DecompilationObject.Properties;
case 'm': return DecompilationObject.Methods;
}
return null;
}
public override bool Equals(object obj) {
var other = obj as LanguageDecompilerSettings;
return other != null &&
decompilerSettings.Equals(other.decompilerSettings);
}
public override int GetHashCode() {
return decompilerSettings.GetHashCode();
}
}
}

Просмотреть файл

@ -0,0 +1,66 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System.ComponentModel.Composition;
using System.Threading;
namespace dnSpy.Languages.ILSpy.Settings {
[Export, PartCreationPolicy(CreationPolicy.Shared)]
sealed class LanguageSettingsManager {
/// <summary>
/// Should only be used indirectly by dnSpy.Console.exe
/// </summary>
public static LanguageSettingsManager __Instance_DONT_USE {
get {
if (__instance_DONT_USE == null)
Interlocked.CompareExchange(ref __instance_DONT_USE, new LanguageSettingsManager(), null);
return __instance_DONT_USE;
}
}
static LanguageSettingsManager __instance_DONT_USE;
LanguageSettingsManager() {
this.languageDecompilerSettings = new LanguageDecompilerSettings();
this.ilLanguageDecompilerSettings = new ILLanguageDecompilerSettings();
}
[ImportingConstructor]
LanguageSettingsManager(DecompilerSettingsImpl decompilerSettings, ILSettingsImpl ilSettings) {
this.languageDecompilerSettings = new LanguageDecompilerSettings(decompilerSettings);
this.ilLanguageDecompilerSettings = new ILLanguageDecompilerSettings(ilSettings);
}
public LanguageDecompilerSettings LanguageDecompilerSettings {
get { return languageDecompilerSettings; }
}
readonly LanguageDecompilerSettings languageDecompilerSettings;
public ILLanguageDecompilerSettings ILLanguageDecompilerSettings {
get { return ilLanguageDecompilerSettings; }
}
readonly ILLanguageDecompilerSettings ilLanguageDecompilerSettings;
#if DEBUG
public ILAstLanguageDecompilerSettings ILAstLanguageDecompilerSettings {
get { return ilAstLanguageDecompilerSettings; }
}
readonly ILAstLanguageDecompilerSettings ilAstLanguageDecompilerSettings = new ILAstLanguageDecompilerSettings();
#endif
}
}

Просмотреть файл

@ -0,0 +1,44 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
namespace dnSpy.Languages.ILSpy.Settings {
static class SettingsConstants {
/// <summary>
/// Redisassemble IL (ILSpy) code
/// </summary>
public static readonly Guid REDISASSEMBLE_IL_ILSPY_CODE = new Guid("9F975119-FB7A-461D-BA17-09B82C7AE258");
/// <summary>
/// Redecompile ILAst (ILSpy) code
/// </summary>
public static readonly Guid REDECOMPILE_ILAST_ILSPY_CODE = new Guid("20D97DB7-EA2D-489D-820F-DCDCE3AB01D3");
/// <summary>
/// Redecompile C# (ILSpy) code
/// </summary>
public static readonly Guid REDECOMPILE_CSHARP_ILSPY_CODE = new Guid("00C8E462-E6E7-4D1F-8CE0-3385B34EA1FB");
/// <summary>
/// Redecompile VB (ILSpy) code
/// </summary>
public static readonly Guid REDECOMPILE_VB_ILSPY_CODE = new Guid("818B8011-851F-4868-9674-3AC3A7B0AEC6");
}
}

Просмотреть файл

@ -0,0 +1,49 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:settings="clr-namespace:dnSpy.Languages.ILSpy.Settings"
xmlns:p="clr-namespace:dnSpy.Languages.ILSpy.Properties"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DataTemplate DataType="{x:Type settings:CSharpDecompilerSettingsTab}">
<StackPanel>
<CheckBox Margin="0 0 0 0" IsChecked="{Binding Settings.AnonymousMethods}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileAnonMethods}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.YieldReturn}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileEnumerators}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.AsyncAwait}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileAsyncMethods}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.QueryExpressions}" IsEnabled="{Binding Settings.AnonymousMethods}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileQueryExpr}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.ExpressionTrees}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompileExprTrees}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.UseDebugSymbols}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_UseLocalNameFromSyms}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.ShowXmlDocumentation}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowXMLDocComments}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.RemoveEmptyDefaultConstructors}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_RemoveEmptyDefaultCtors}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.ShowTokenAndRvaComments}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowTokensRvasOffsets}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.SortMembers}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_SortMethods}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.ForceShowAllMembers}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowCompilerGeneratedTypes}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.SortSystemUsingStatementsFirst}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_SortSystemFirst}"/>
<GroupBox Margin="0 5 0 0" Header="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_DecompilationOrder}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0" HorizontalAlignment="Stretch" ItemsSource="{Binding DecompilationObjectsArray}" SelectedItem="{Binding DecompilationObject0}" DisplayMemberPath="Text" />
<ComboBox Grid.Column="1" HorizontalAlignment="Stretch" ItemsSource="{Binding DecompilationObjectsArray}" SelectedItem="{Binding DecompilationObject1}" DisplayMemberPath="Text" />
<ComboBox Grid.Column="2" HorizontalAlignment="Stretch" ItemsSource="{Binding DecompilationObjectsArray}" SelectedItem="{Binding DecompilationObject2}" DisplayMemberPath="Text" />
<ComboBox Grid.Column="3" HorizontalAlignment="Stretch" ItemsSource="{Binding DecompilationObjectsArray}" SelectedItem="{Binding DecompilationObject3}" DisplayMemberPath="Text" />
<ComboBox Grid.Column="4" HorizontalAlignment="Stretch" ItemsSource="{Binding DecompilationObjectsArray}" SelectedItem="{Binding DecompilationObject4}" DisplayMemberPath="Text" />
</Grid>
</GroupBox>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type settings:ILDecompilerSettingsTab}">
<StackPanel>
<CheckBox Margin="0 0 0 0" IsChecked="{Binding Settings.ShowXmlDocumentation}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowXMLDocComments}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.ShowTokenAndRvaComments}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowTokensRvasOffsets}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.ShowILBytes}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowILInstrBytes}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.ShowILComments}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_ShowILComments}"/>
<CheckBox Margin="0 5 0 0" IsChecked="{Binding Settings.SortMembers}" Content="{x:Static p:dnSpy_Languages_ILSpy_Resources.DecompilerSettings_SortMethods}"/>
</StackPanel>
</DataTemplate>
</ResourceDictionary>

Просмотреть файл

@ -0,0 +1,145 @@
// Copyright (c) 2011 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 dnlib.DotNet;
using dnSpy.Decompiler.Shared;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.VB.Visitors;
namespace dnSpy.Languages.ILSpy.VB {
sealed class ILSpyEnvironmentProvider : IEnvironmentProvider {
public string RootNamespace {
get {
return "";
}
}
public string GetTypeNameForAttribute(ICSharpCode.NRefactory.CSharp.Attribute attribute) {
var mr = attribute.Type.Annotations
.OfType<IMemberRef>()
.FirstOrDefault();
return mr == null ? string.Empty : mr.FullName;
}
public ICSharpCode.NRefactory.TypeSystem.IType ResolveType(ICSharpCode.NRefactory.VB.Ast.AstType type, ICSharpCode.NRefactory.VB.Ast.TypeDeclaration entity = null) {
/*
var annotation = type.Annotation<TypeReference>();
if (annotation == null )
return null;
IEntity current = null;
if (entity != null) {
var typeInfo = entity.Annotation<TypeReference>();
current = loader.ReadTypeReference(typeInfo).Resolve(context).GetDefinition();
}
return loader.ReadTypeReference(annotation, entity: current).Resolve(context);*/
return SpecialType.UnknownType;
}
public TypeKind GetTypeKindForAstType(ICSharpCode.NRefactory.CSharp.AstType type) {
var annotation = type.Annotation<ITypeDefOrRef>();
if (annotation == null)
return TypeKind.Unknown;
var definition = annotation.ResolveTypeDef();
if (definition == null)
return TypeKind.Unknown;
if (definition.IsClass)
return TypeKind.Class;
if (definition.IsInterface)
return TypeKind.Interface;
if (definition.IsEnum)
return TypeKind.Enum;
if (definition.IsValueType)
return TypeKind.Struct;
return TypeKind.Unknown;
}
public TypeCode ResolveExpression(ICSharpCode.NRefactory.CSharp.Expression expression) {
var annotation = expression.Annotations.OfType<TypeInformation>().FirstOrDefault();
if (annotation == null || annotation.InferredType == null)
return TypeCode.Object;
var definition = annotation.InferredType.ScopeType.ResolveTypeDef();
if (definition == null)
return TypeCode.Object;
switch (definition.FullName) {
case "System.String":
return TypeCode.String;
default:
break;
}
return TypeCode.Object;
}
public Nullable<bool> IsReferenceType(ICSharpCode.NRefactory.CSharp.Expression expression) {
if (expression is ICSharpCode.NRefactory.CSharp.NullReferenceExpression)
return true;
var annotation = expression.Annotations.OfType<TypeInformation>().FirstOrDefault();
if (annotation == null || annotation.InferredType == null)
return null;
var definition = annotation.InferredType.ScopeType.ResolveTypeDef();
if (definition == null)
return null;
return !definition.IsValueType;
}
public IEnumerable<ICSharpCode.NRefactory.VB.Ast.InterfaceMemberSpecifier> CreateMemberSpecifiersForInterfaces(IEnumerable<ICSharpCode.NRefactory.VB.Ast.AstType> interfaces) {
foreach (var type in interfaces) {
var def = type.Annotation<ITypeDefOrRef>().ResolveTypeDef();
if (def == null)
continue;
foreach (var method in def.Methods.Where(m => !m.Name.StartsWith("get_") && !m.Name.StartsWith("set_"))) {
yield return new ICSharpCode.NRefactory.VB.Ast.InterfaceMemberSpecifier((ICSharpCode.NRefactory.VB.Ast.AstType)type.Clone(), method.Name, TextTokenKindUtils.GetTextTokenKind(method));
}
foreach (var property in def.Properties) {
yield return new ICSharpCode.NRefactory.VB.Ast.InterfaceMemberSpecifier((ICSharpCode.NRefactory.VB.Ast.AstType)type.Clone(), property.Name, TextTokenKindUtils.GetTextTokenKind(property));
}
}
}
public bool HasEvent(ICSharpCode.NRefactory.VB.Ast.Expression expression) {
return expression.Annotation<EventDef>() != null;
}
public bool IsMethodGroup(ICSharpCode.NRefactory.CSharp.Expression expression) {
var annotation = expression.Annotation<MethodDef>();
if (annotation != null) {
return true;
}
return false;
}
}
}

Просмотреть файл

@ -0,0 +1,327 @@
// Copyright (c) 2011 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.ComponentModel.Composition;
using dnlib.DotNet;
using dnSpy.Contracts.Languages;
using dnSpy.Languages.ILSpy.CSharp;
using dnSpy.Shared.Highlighting;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Ast.Transforms;
using ICSharpCode.NRefactory.VB;
using ICSharpCode.NRefactory.VB.Visitors;
using dnSpy.Decompiler.Shared;
using dnSpy.Languages.ILSpy.Settings;
using System.Diagnostics;
using System.Text;
namespace dnSpy.Languages.ILSpy.VB {
sealed class LanguageProvider : ILanguageProvider {
readonly LanguageSettingsManager languageSettingsManager;
// Keep the default ctor. It's used by dnSpy.Console.exe
public LanguageProvider()
: this(LanguageSettingsManager.__Instance_DONT_USE) {
}
public LanguageProvider(LanguageSettingsManager languageSettingsManager) {
Debug.Assert(languageSettingsManager != null);
if (languageSettingsManager == null)
throw new ArgumentNullException();
this.languageSettingsManager = languageSettingsManager;
}
public IEnumerable<ILanguage> Languages {
get { yield return new VBLanguage(languageSettingsManager.LanguageDecompilerSettings); }
}
}
[Export(typeof(ILanguageCreator))]
sealed class MyLanguageCreator : ILanguageCreator {
readonly LanguageSettingsManager languageSettingsManager;
[ImportingConstructor]
MyLanguageCreator(LanguageSettingsManager languageSettingsManager) {
this.languageSettingsManager = languageSettingsManager;
}
public IEnumerable<ILanguage> Create() {
return new LanguageProvider(languageSettingsManager).Languages;
}
}
/// <summary>
/// Decompiler logic for VB.
/// </summary>
sealed class VBLanguage : Language {
readonly Predicate<IAstTransform> transformAbortCondition = null;
readonly bool showAllMembers = false;
public override IDecompilerSettings Settings {
get { return langSettings; }
}
readonly LanguageDecompilerSettings langSettings;
public override double OrderUI {
get { return LanguageConstants.VB_ILSPY_ORDERUI; }
}
public VBLanguage(LanguageDecompilerSettings langSettings) {
this.langSettings = langSettings;
}
public override string GenericNameUI {
get { return LanguageConstants.GENERIC_NAMEUI_VB; }
}
public override string UniqueNameUI {
get { return "VB"; }
}
public override Guid GenericGuid {
get { return LanguageConstants.LANGUAGE_VB; }
}
public override Guid UniqueGuid {
get { return LanguageConstants.LANGUAGE_VB_ILSPY; }
}
public override string FileExtension {
get { return ".vb"; }
}
public override string ProjectFileExtension {
get { return ".vbproj"; }
}
public override void WriteCommentBegin(ITextOutput output, bool addSpace) {
if (addSpace)
output.Write("' ", TextTokenKind.Comment);
else
output.Write("'", TextTokenKind.Comment);
}
public override void WriteCommentEnd(ITextOutput output, bool addSpace) {
}
public override void Decompile(AssemblyDef asm, ITextOutput output, DecompilationContext ctx) {
WriteAssembly(asm, output, ctx);
using (ctx.DisableAssemblyLoad()) {
var state = CreateAstBuilder(ctx, langSettings.Settings, currentModule: asm.ManifestModule);
try {
state.AstBuilder.AddAssembly(asm.ManifestModule, true, true, false);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
}
public override void Decompile(ModuleDef mod, ITextOutput output, DecompilationContext ctx) {
WriteModule(mod, output, ctx);
using (ctx.DisableAssemblyLoad()) {
var state = CreateAstBuilder(ctx, langSettings.Settings, currentModule: mod);
try {
state.AstBuilder.AddAssembly(mod, true, false, true);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
}
public override void Decompile(MethodDef method, ITextOutput output, DecompilationContext ctx) {
WriteCommentLineDeclaringType(output, method);
var state = CreateAstBuilder(ctx, langSettings.Settings, currentType: method.DeclaringType, isSingleMember: true);
try {
state.AstBuilder.AddMethod(method);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
public override void Decompile(PropertyDef property, ITextOutput output, DecompilationContext ctx) {
WriteCommentLineDeclaringType(output, property);
var state = CreateAstBuilder(ctx, langSettings.Settings, currentType: property.DeclaringType, isSingleMember: true);
try {
state.AstBuilder.AddProperty(property);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
public override void Decompile(FieldDef field, ITextOutput output, DecompilationContext ctx) {
WriteCommentLineDeclaringType(output, field);
var state = CreateAstBuilder(ctx, langSettings.Settings, currentType: field.DeclaringType, isSingleMember: true);
try {
state.AstBuilder.AddField(field);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
public override void Decompile(EventDef ev, ITextOutput output, DecompilationContext ctx) {
WriteCommentLineDeclaringType(output, ev);
var state = CreateAstBuilder(ctx, langSettings.Settings, currentType: ev.DeclaringType, isSingleMember: true);
try {
state.AstBuilder.AddEvent(ev);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
public override void Decompile(TypeDef type, ITextOutput output, DecompilationContext ctx) {
var state = CreateAstBuilder(ctx, langSettings.Settings, currentType: type);
try {
state.AstBuilder.AddType(type);
RunTransformsAndGenerateCode(ref state, output, ctx);
}
finally {
state.Dispose();
}
}
public override bool ShowMember(IMemberRef member) {
return showAllMembers || !AstBuilder.MemberIsHidden(member, langSettings.Settings);
}
void RunTransformsAndGenerateCode(ref BuilderState state, ITextOutput output, DecompilationContext ctx, IAstTransform additionalTransform = null) {
var astBuilder = state.AstBuilder;
astBuilder.RunTransformations(transformAbortCondition);
if (additionalTransform != null) {
additionalTransform.Run(astBuilder.SyntaxTree);
}
CSharpLanguage.AddXmlDocumentation(ref state, langSettings.Settings, astBuilder);
var csharpUnit = astBuilder.SyntaxTree;
csharpUnit.AcceptVisitor(new ICSharpCode.NRefactory.CSharp.InsertParenthesesVisitor() { InsertParenthesesForReadability = true });
var unit = csharpUnit.AcceptVisitor(new CSharpToVBConverterVisitor(new ILSpyEnvironmentProvider()), null);
var outputFormatter = new VBTextOutputFormatter(output);
var formattingPolicy = new VBFormattingOptions();
unit.AcceptVisitor(new OutputVisitor(outputFormatter, formattingPolicy), null);
}
BuilderState CreateAstBuilder(DecompilationContext ctx, DecompilerSettings settings, ModuleDef currentModule = null, TypeDef currentType = null, bool isSingleMember = false) {
if (currentModule == null)
currentModule = currentType.Module;
settings = settings.Clone();
if (isSingleMember)
settings.UsingDeclarations = false;
settings.IntroduceIncrementAndDecrement = false;
settings.MakeAssignmentExpressions = false;
settings.QueryExpressions = false;
settings.AlwaysGenerateExceptionVariableForCatchBlocks = true;
var cache = ctx.GetOrCreate<BuilderCache>();
var state = new BuilderState(ctx, cache);
state.AstBuilder.Context.CurrentModule = currentModule;
state.AstBuilder.Context.CancellationToken = ctx.CancellationToken;
state.AstBuilder.Context.CurrentType = currentType;
state.AstBuilder.Context.Settings = settings;
return state;
}
protected override void FormatTypeName(ITextOutput output, TypeDef type) {
if (type == null)
throw new ArgumentNullException("type");
TypeToString(output, ConvertTypeOptions.DoNotUsePrimitiveTypeNames | ConvertTypeOptions.IncludeTypeParameterDefinitions, type);
}
protected override void TypeToString(ITextOutput output, ITypeDefOrRef type, bool includeNamespace, IHasCustomAttribute typeAttributes = null) {
ConvertTypeOptions options = ConvertTypeOptions.IncludeTypeParameterDefinitions;
if (includeNamespace)
options |= ConvertTypeOptions.IncludeNamespace;
TypeToString(output, options, type, typeAttributes);
}
void TypeToString(ITextOutput output, ConvertTypeOptions options, ITypeDefOrRef type, IHasCustomAttribute typeAttributes = null) {
var envProvider = new ILSpyEnvironmentProvider();
var converter = new CSharpToVBConverterVisitor(envProvider);
var astType = AstBuilder.ConvertType(type, new StringBuilder(), typeAttributes, options);
if (type.TryGetByRefSig() != null) {
output.Write("ByRef", TextTokenKind.Keyword);
output.WriteSpace();
if (astType is ICSharpCode.NRefactory.CSharp.ComposedType && ((ICSharpCode.NRefactory.CSharp.ComposedType)astType).PointerRank > 0)
((ICSharpCode.NRefactory.CSharp.ComposedType)astType).PointerRank--;
}
var vbAstType = astType.AcceptVisitor(converter, null);
vbAstType.AcceptVisitor(new OutputVisitor(new VBTextOutputFormatter(output), new VBFormattingOptions()), null);
}
public override bool CanDecompile(DecompilationType decompilationType) {
switch (decompilationType) {
case DecompilationType.PartialType:
case DecompilationType.AssemblyInfo:
return true;
}
return base.CanDecompile(decompilationType);
}
public override void Decompile(DecompilationType decompilationType, object data) {
switch (decompilationType) {
case DecompilationType.PartialType:
DecompilePartial((DecompilePartialType)data);
return;
case DecompilationType.AssemblyInfo:
DecompileAssemblyInfo((DecompileAssemblyInfo)data);
return;
}
base.Decompile(decompilationType, data);
}
void DecompilePartial(DecompilePartialType info) {
var state = CreateAstBuilder(info.Context, CSharpLanguage.CreateDecompilerSettings(langSettings.Settings, info.UseUsingDeclarations), currentType: info.Type);
try {
state.AstBuilder.AddType(info.Type);
RunTransformsAndGenerateCode(ref state, info.Output, info.Context, new DecompilePartialTransform(info.Type, info.Definitions, info.ShowDefinitions, info.AddPartialKeyword, info.InterfacesToRemove));
}
finally {
state.Dispose();
}
}
void DecompileAssemblyInfo(DecompileAssemblyInfo info) {
var state = CreateAstBuilder(info.Context, langSettings.Settings, currentModule: info.Module);
try {
state.AstBuilder.AddAssembly(info.Module, true, info.Module.IsManifestModule, true);
RunTransformsAndGenerateCode(ref state, info.Output, info.Context, new AssemblyInfoTransform());
}
finally {
state.Dispose();
}
}
}
}

Просмотреть файл

@ -0,0 +1,295 @@
// Copyright (c) 2011 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.Diagnostics;
using dnlib.DotNet;
using dnSpy.Decompiler.Shared;
using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.NRefactory.VB;
using ICSharpCode.NRefactory.VB.Ast;
namespace dnSpy.Languages.ILSpy.VB {
sealed class VBTextOutputFormatter : IOutputFormatter {
readonly ITextOutput output;
readonly Stack<AstNode> nodeStack = new Stack<AstNode>();
public VBTextOutputFormatter(ITextOutput output) {
if (output == null)
throw new ArgumentNullException("output");
this.output = output;
}
MemberMapping currentMemberMapping;
Stack<MemberMapping> parentMemberMappings = new Stack<MemberMapping>();
List<Tuple<MemberMapping, List<ILRange>>> multiMappings;
public void StartNode(AstNode node) {
// var ranges = node.Annotation<List<ILRange>>();
// if (ranges != null && ranges.Count > 0)
// {
// // find the ancestor that has method mapping as annotation
// if (node.Ancestors != null && node.Ancestors.Count() > 0)
// {
// var n = node.Ancestors.FirstOrDefault(a => a.Annotation<MemberMapping>() != null);
// if (n != null) {
// MemberMapping mapping = n.Annotation<MemberMapping>();
//
// // add all ranges
// foreach (var range in ranges) {
// mapping.MemberCodeMappings.Add(new SourceCodeMapping {
// ILInstructionOffset = range,
// SourceCodeLine = output.CurrentLine,
// MemberMapping = mapping
// });
// }
// }
// }
// }
nodeStack.Push(node);
MemberMapping mapping = node.Annotation<MemberMapping>();
if (mapping != null) {
parentMemberMappings.Push(currentMemberMapping);
currentMemberMapping = mapping;
}
// For ctor/cctor field initializers
var mms = node.Annotation<List<Tuple<MemberMapping, List<ILRange>>>>();
if (mms != null) {
Debug.Assert(multiMappings == null);
multiMappings = mms;
}
}
public void EndNode(AstNode node) {
if (nodeStack.Pop() != node)
throw new InvalidOperationException();
if (node.Annotation<MemberMapping>() != null) {
output.AddDebugSymbols(currentMemberMapping);
currentMemberMapping = parentMemberMappings.Pop();
}
var mms = node.Annotation<List<Tuple<MemberMapping, List<ILRange>>>>();
if (mms != null) {
Debug.Assert(mms == multiMappings);
if (mms == multiMappings) {
foreach (var mm in mms)
output.AddDebugSymbols(mm.Item1);
multiMappings = null;
}
}
}
public void WriteIdentifier(string identifier, TextTokenKind tokenKind) {
var definition = GetCurrentDefinition();
if (definition != null) {
output.WriteDefinition(IdentifierEscaper.Escape(identifier), definition, tokenKind);
return;
}
object memberRef = GetCurrentMemberReference();
if (memberRef != null) {
output.WriteReference(IdentifierEscaper.Escape(identifier), memberRef, tokenKind);
return;
}
definition = GetCurrentLocalDefinition();
if (definition != null) {
output.WriteDefinition(IdentifierEscaper.Escape(identifier), definition, tokenKind);
return;
}
memberRef = GetCurrentLocalReference();
if (memberRef != null) {
output.WriteReference(IdentifierEscaper.Escape(identifier), memberRef, tokenKind, true);
return;
}
output.Write(IdentifierEscaper.Escape(identifier), tokenKind);
}
IMemberRef GetCurrentMemberReference() {
AstNode node = nodeStack.Peek();
IMemberRef memberRef = node.Annotation<IMemberRef>();
if (memberRef == null && node.Role == AstNode.Roles.TargetExpression && (node.Parent is InvocationExpression || node.Parent is ObjectCreationExpression)) {
memberRef = node.Parent.Annotation<IMemberRef>();
}
return memberRef;
}
object GetCurrentLocalReference() {
AstNode node = nodeStack.Peek();
ILVariable variable = node.Annotation<ILVariable>();
if (variable != null) {
if (variable.OriginalParameter != null)
return variable.OriginalParameter;
//if (variable.OriginalVariable != null)
// return variable.OriginalVariable;
return variable;
}
return null;
}
object GetCurrentLocalDefinition() {
AstNode node = nodeStack.Peek();
var parameterDef = node.Annotation<Parameter>();
if (parameterDef != null)
return parameterDef;
if (node is VariableInitializer || node is CatchBlock || node is ForEachStatement) {
var variable = node.Annotation<ILVariable>();
if (variable != null) {
if (variable.OriginalParameter != null)
return variable.OriginalParameter;
//if (variable.OriginalVariable != null)
// return variable.OriginalVariable;
return variable;
}
else {
}
}
return null;
}
object GetCurrentDefinition() {
if (nodeStack == null || nodeStack.Count == 0)
return null;
var node = nodeStack.Peek();
if (IsDefinition(node))
return node.Annotation<IMemberRef>();
node = node.Parent;
if (IsDefinition(node))
return node.Annotation<IMemberRef>();
return null;
}
public void WriteKeyword(string keyword) {
IMemberRef memberRef = GetCurrentMemberReference();
var node = nodeStack.Peek();
if (memberRef != null && node is PrimitiveType)
output.WriteReference(keyword, memberRef, TextTokenKind.Keyword);
else
output.Write(keyword, TextTokenKind.Keyword);
}
public void WriteToken(string token, TextTokenKind tokenKind) {
// Attach member reference to token only if there's no identifier in the current node.
IMemberRef memberRef = GetCurrentMemberReference();
if (memberRef != null && nodeStack.Peek().GetChildByRole(AstNode.Roles.Identifier).IsNull)
output.WriteReference(token, memberRef, tokenKind);
else
output.Write(token, tokenKind);
}
public void Space() {
output.WriteSpace();
}
public void Indent() {
output.Indent();
}
public void Unindent() {
output.Unindent();
}
public void NewLine() {
output.WriteLine();
}
public void WriteComment(bool isDocumentation, string content) {
if (isDocumentation) {
output.Write("'''", TextTokenKind.XmlDocTag);
output.WriteXmlDoc(content);
output.WriteLine();
}
else
output.WriteLine("'" + content, TextTokenKind.Comment);
}
static bool IsDefinition(AstNode node) {
return
node is FieldDeclaration ||
node is ConstructorDeclaration ||
node is EventDeclaration ||
node is DelegateDeclaration ||
node is OperatorDeclaration ||
node is MemberDeclaration ||
node is TypeDeclaration;
}
class DebugState {
public List<AstNode> Nodes = new List<AstNode>();
public List<ILRange> ExtraILRanges = new List<ILRange>();
public TextPosition StartLocation;
}
readonly Stack<DebugState> debugStack = new Stack<DebugState>();
public void DebugStart(AstNode node) {
debugStack.Push(new DebugState { StartLocation = output.Location });
}
public void DebugHidden(object hiddenILRanges) {
var list = hiddenILRanges as IList<ILRange>;
if (list != null) {
if (debugStack.Count > 0)
debugStack.Peek().ExtraILRanges.AddRange(list);
}
}
public void DebugExpression(AstNode node) {
if (debugStack.Count > 0)
debugStack.Peek().Nodes.Add(node);
}
static readonly IEnumerable<ILRange> emptyILRange = new ILRange[0];
public void DebugEnd(AstNode node) {
var state = debugStack.Pop();
if (currentMemberMapping != null) {
foreach (var range in ILRange.OrderAndJoin(GetILRanges(state)))
currentMemberMapping.MemberCodeMappings.Add(new SourceCodeMapping(range, state.StartLocation, output.Location, currentMemberMapping));
}
else if (multiMappings != null) {
foreach (var mm in multiMappings) {
foreach (var range in ILRange.OrderAndJoin(mm.Item2))
mm.Item1.MemberCodeMappings.Add(new SourceCodeMapping(range, state.StartLocation, output.Location, mm.Item1));
}
}
}
static IEnumerable<ILRange> GetILRanges(DebugState state) {
foreach (var node in state.Nodes) {
foreach (var ann in node.Annotations) {
var list = ann as IList<ILRange>;
if (list == null)
continue;
foreach (var range in list)
yield return range;
}
}
foreach (var range in state.ExtraILRanges)
yield return range;
}
}
}

Просмотреть файл

@ -0,0 +1,65 @@
// Copyright (c) 2011 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 ICSharpCode.NRefactory.CSharp;
using dnlib.DotNet;
using dnSpy.Shared.Languages.XmlDoc;
using System.Text;
namespace dnSpy.Languages.ILSpy.XmlDoc {
/// <summary>
/// Adds XML documentation for member definitions.
/// </summary>
struct AddXmlDocTransform {
readonly StringBuilder stringBuilder;
public AddXmlDocTransform(StringBuilder sb) {
this.stringBuilder = sb;
}
public void Run(AstNode node) {
if (node is EntityDeclaration) {
IMemberRef mr = node.Annotation<IMemberRef>();
if (mr != null && mr.Module != null) {
var xmldoc = XmlDocLoader.LoadDocumentation(mr.Module);
if (xmldoc != null) {
string doc = xmldoc.GetDocumentation(XmlDocKeyProvider.GetKey(mr, stringBuilder));
if (!string.IsNullOrEmpty(doc)) {
InsertXmlDocumentation(node, doc);
}
}
}
if (!(node is TypeDeclaration))
return; // don't recurse into attributed nodes, except for type definitions
}
foreach (AstNode child in node.Children)
Run(child);
}
void InsertXmlDocumentation(AstNode node, string doc) {
foreach (var info in new XmlDocLine(doc)) {
stringBuilder.Clear();
if (info != null) {
stringBuilder.Append(' ');
info.Value.WriteTo(stringBuilder);
}
node.Parent.InsertChildBefore(node, new Comment(stringBuilder.ToString(), CommentType.Documentation), Roles.Comment);
}
}
}
}

Просмотреть файл

@ -0,0 +1,98 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace dnSpy.Languages.ILSpy.XmlDoc {
struct SubStringInfo {
public readonly int Index;
public readonly int Length;
public SubStringInfo(int index, int length) {
this.Index = index;
this.Length = length;
}
}
struct StringLineIterator : IEnumerable<SubStringInfo>, IEnumerator<SubStringInfo> {
readonly string s;
int index;
readonly int end;
SubStringInfo info;
bool finished;
public StringLineIterator(string s, int index, int length) {
this.s = s;
this.index = index;
this.end = index + length;
this.info = default(SubStringInfo);
this.finished = false;
}
public StringLineIterator GetEnumerator() {
return this;
}
IEnumerator<SubStringInfo> IEnumerable<SubStringInfo>.GetEnumerator() {
Debug.Fail("'this' was boxed");
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
Debug.Fail("'this' was boxed");
return GetEnumerator();
}
public SubStringInfo Current {
get { return info; }
}
object IEnumerator.Current {
get { Debug.Fail("'this' was boxed"); return info; }
}
public void Dispose() {
}
public bool MoveNext() {
int newLineIndex = this.s.IndexOfAny(newLineChars, this.index, end - this.index);
if (newLineIndex < 0) {
if (this.finished)
return false;
this.info = new SubStringInfo(this.index, end - this.index);
this.finished = true;
return true;
}
int len = newLineIndex - this.index;
this.info = new SubStringInfo(this.index, len);
if (s[newLineIndex] == '\r' && newLineIndex + 1 < s.Length && s[newLineIndex + 1] == '\n')
newLineIndex++;
this.index = newLineIndex + 1;
return true;
}
static readonly char[] newLineChars = new char[] { '\r', '\n' };
public void Reset() {
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -0,0 +1,42 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Text;
namespace dnSpy.Languages.ILSpy.XmlDoc {
struct SubString {
public readonly string String;
public readonly int Index;
public readonly int Length;
public SubString(string s, int index, int length) {
this.String = s;
this.Index = index;
this.Length = length;
}
public override string ToString() {
return this.String.Substring(this.Index, this.Length);
}
public void WriteTo(StringBuilder sb) {
sb.Append(this.String, this.Index, this.Length);
}
}
}

Просмотреть файл

@ -0,0 +1,163 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace dnSpy.Languages.ILSpy.XmlDoc {
struct XmlDocLine : IEnumerable<SubString?>, IEnumerator<SubString?> {
readonly string s;
readonly int start;
readonly int end;
SubString? current;
SubStringInfo? indent;
StringLineIterator iter;
int emptyLines;
public XmlDocLine(string s)
: this(s, 0, s.Length) {
}
public XmlDocLine(string s, int start, int length) {
this.s = s;
this.start = start;
this.end = start + length;
this.current = null;
this.indent = null;
this.iter = new StringLineIterator(s, start, end - start);
this.emptyLines = 0;
}
public XmlDocLine GetEnumerator() {
return this;
}
IEnumerator<SubString?> IEnumerable<SubString?>.GetEnumerator() {
Debug.Fail("'this' was boxed");
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
Debug.Fail("'this' was boxed");
return GetEnumerator();
}
public SubString? Current {
get { return current; }
}
object IEnumerator.Current {
get { Debug.Fail("'this' was boxed"); return current; }
}
public void Dispose() {
}
public bool MoveNext() {
if (this.indent == null) {
for (;;) {
if (!iter.MoveNext())
return false;
if (!IsWhiteSpace(s, iter.Current))
break;
}
indent = GetIndentation(s, iter.Current);
goto start2;
}
if (emptyLines != 0)
goto start2;
start:
if (!iter.MoveNext())
return false;
start2:
if (IsWhiteSpace(s, iter.Current)) {
emptyLines++;
goto start;
}
if (emptyLines != 0) {
if (emptyLines != -1) {
emptyLines--;
if (emptyLines == 0)
emptyLines = -1;
current = null;
return true;
}
emptyLines = 0;
}
int index, end;
Trim(out index, out end);
current = new SubString(s, index, end - index);
return true;
}
void Trim(out int trimmedIndex, out int trimmedEnd) {
Debug.Assert(indent != null);
int index = iter.Current.Index;
int end = index + iter.Current.Length;
if (indent.Value.Length > iter.Current.Length) {
trimmedIndex = index;
trimmedEnd = end;
return;
}
int end2 = index + indent.Value.Length;
for (int i = index, j = indent.Value.Index; i < end2; i++, j++) {
if (s[i] != s[j]) {
trimmedIndex = index;
trimmedEnd = end;
return;
}
}
trimmedIndex = index + indent.Value.Length;
trimmedEnd = end;
Debug.Assert(trimmedIndex <= trimmedEnd);
}
SubStringInfo GetIndentation(string doc, SubStringInfo info) {
int end = info.Index + info.Length;
int i = info.Index;
for (; i < end; i++) {
if (!char.IsWhiteSpace(doc[i]))
break;
}
return new SubStringInfo(info.Index, i - info.Index);
}
bool IsWhiteSpace(string doc, SubStringInfo info) {
int end = info.Index + info.Length;
for (int i = info.Index; i < end; i++) {
if (!char.IsWhiteSpace(doc[i]))
return false;
}
return true;
}
public void Reset() {
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D7FE873E-DF22-4F54-AEFA-BCF33AFD7E05}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>dnSpy.Languages.ILSpy</RootNamespace>
<AssemblyName>Languages.ILSpy.Plugin</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\..\dnSpy.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\dnSpy\dnSpy\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>1685</NoWarn>
<DocumentationFile>..\..\..\dnSpy\dnSpy\bin\Debug\Languages.ILSpy.Plugin.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\..\dnSpy\dnSpy\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>1685</NoWarn>
<DocumentationFile>..\..\..\dnSpy\dnSpy\bin\Release\Languages.ILSpy.Plugin.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.XML" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="CSharp\AssemblyInfoTransform.cs" />
<Compile Include="CSharp\BuilderCache.cs" />
<Compile Include="CSharp\BuilderState.cs" />
<Compile Include="CSharp\CSharpLanguage.cs" />
<Compile Include="CSharp\DecompilePartialTransform.cs" />
<Compile Include="CSharp\ThreadSafeObjectPool.cs" />
<Compile Include="Properties\dnSpy.Languages.ILSpy.Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>dnSpy.Languages.ILSpy.Resources.resx</DependentUpon>
</Compile>
<Compile Include="ILAst\ILAstLanguage.cs" />
<Compile Include="IL\ILLanguage.cs" />
<Compile Include="Plugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Settings\CSharpDecompilerSettingsTab.cs" />
<Compile Include="Settings\DecompilerAppSettingsModifiedListener.cs" />
<Compile Include="Settings\DecompilerSettingsImpl.cs" />
<Compile Include="Settings\DecompilerSettingsTabCreator.cs" />
<Compile Include="Settings\ILAstLanguageDecompilerSettings.cs" />
<Compile Include="Settings\ILDecompilerSettingsTab.cs" />
<Compile Include="Settings\ILLanguageDecompilerSettings.cs" />
<Compile Include="Settings\ILSettings.cs" />
<Compile Include="Settings\LanguageDecompilerSettings.cs" />
<Compile Include="Settings\LanguageSettingsManager.cs" />
<Compile Include="Settings\SettingsConstants.cs" />
<Compile Include="VB\ILSpyEnvironmentProvider.cs" />
<Compile Include="VB\VBLanguage.cs" />
<Compile Include="VB\VBTextOutputFormatter.cs" />
<Compile Include="XmlDoc\AddXmlDocTransform.cs" />
<Compile Include="XmlDoc\StringLineIterator.cs" />
<Compile Include="XmlDoc\SubString.cs" />
<Compile Include="XmlDoc\XmlDocLine.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Libraries\dnlib\src\dnlib.csproj">
<Project>{fdfc1237-143f-4919-8318-4926901f4639}</Project>
<Name>dnlib</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\dnSpy\dnSpy.Contracts\dnSpy.Contracts.csproj">
<Project>{9b234472-0e22-428c-9345-c8d9ee5e06af}</Project>
<Name>dnSpy.Contracts</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\dnSpy\dnSpy.Decompiler.Shared\dnSpy.Decompiler.Shared.csproj">
<Project>{a027546a-cf4b-47f9-bc53-ee1ad424ee41}</Project>
<Name>dnSpy.Decompiler.Shared</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\dnSpy\dnSpy.Shared\dnSpy.Shared.csproj">
<Project>{7e7c2cf8-2057-4eaa-9dad-ab3022cf4037}</Project>
<Name>dnSpy.Shared</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj">
<Project>{984cc812-9470-4a13-aff9-cc44068d666c}</Project>
<Name>ICSharpCode.Decompiler</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\dnSpy\dnSpy.Languages\dnSpy.Languages.csproj">
<Project>{9265e4ea-eb00-4cb6-8a9a-608871e24fd0}</Project>
<Name>dnSpy.Languages</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53dca265-3c3c-42f9-b647-f72ba678122b}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.Decompiler\NRefactory.VB\ICSharpCode.NRefactory.VB\ICSharpCode.NRefactory.VB.csproj">
<Project>{7b82b671-419f-45f4-b778-d9286f996efa}</Project>
<Name>ICSharpCode.NRefactory.VB</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\dnSpy.Languages.ILSpy.Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>dnSpy.Languages.ILSpy.Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Properties\dnSpy.Languages.ILSpy.Resources.ru.resx" />
<EmbeddedResource Include="Properties\dnSpy.Languages.ILSpy.Resources.zh-CN.resx" />
</ItemGroup>
<ItemGroup>
<Page Include="Themes\wpf.styles.templates.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\dnSpy\dnSpy\Properties\AssemblyInfo.Shared.cs">
<Link>Properties\AssemblyInfo.Shared.cs</Link>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,391 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using dnlib.DotNet;
using dnSpy.Analyzer.TreeNodes;
using dnSpy.Contracts.Controls;
using dnSpy.Contracts.Decompiler;
using dnSpy.Contracts.Files;
using dnSpy.Contracts.Files.Tabs;
using dnSpy.Contracts.Files.Tabs.TextEditor;
using dnSpy.Contracts.Images;
using dnSpy.Contracts.Languages;
using dnSpy.Contracts.Menus;
using dnSpy.Contracts.TextEditor;
using dnSpy.Contracts.Themes;
using dnSpy.Contracts.TreeView;
using dnSpy.Decompiler.Shared;
using dnSpy.Shared.MVVM;
namespace dnSpy.Analyzer {
interface IAnalyzerManager {
/// <summary>
/// Gets the <see cref="ITreeView"/> instance
/// </summary>
ITreeView TreeView { get; }
/// <summary>
/// Called when it's been closed
/// </summary>
void OnClose();
/// <summary>
/// Adds <paramref name="node"/> if it hasn't been added and gives it focus.
/// </summary>
/// <param name="node">Node</param>
void Add(IAnalyzerTreeNodeData node);
/// <summary>
/// Called by <paramref name="node"/> when its <see cref="ITreeNodeData.Activate()"/> method
/// has been called.
/// </summary>
/// <param name="node">Activated node (it's the caller)</param>
void OnActivated(IAnalyzerTreeNodeData node);
/// <summary>
/// Follows the reference
/// </summary>
/// <param name="node">Node</param>
/// <param name="newTab">true to show it in a new tab</param>
/// <param name="useCodeRef">true to show the reference in a method body</param>
void FollowNode(ITreeNodeData node, bool newTab, bool? useCodeRef);
/// <summary>
/// Returns true if <see cref="FollowNode(ITreeNodeData, bool, bool?)"/> can execute
/// </summary>
/// <param name="node">Node</param>
/// <param name="useCodeRef">true to show the reference in a method body</param>
/// <returns></returns>
bool CanFollowNode(ITreeNodeData node, bool useCodeRef);
}
[Export, Export(typeof(IAnalyzerManager)), PartCreationPolicy(CreationPolicy.Shared)]
sealed class AnalyzerManager : IAnalyzerManager, ITreeViewListener {
static readonly Guid ANALYZER_TREEVIEW_GUID = new Guid("8981898A-1384-4B67-9577-3CB096195146");
public ITreeView TreeView {
get { return treeView; }
}
readonly ITreeView treeView;
sealed class GuidObjectsCreator : IGuidObjectsCreator {
readonly ITreeView treeView;
public GuidObjectsCreator(ITreeView treeView) {
this.treeView = treeView;
}
public IEnumerable<GuidObject> GetGuidObjects(GuidObject creatorObject, bool openedFromKeyboard) {
yield return new GuidObject(MenuConstants.GUIDOBJ_TREEVIEW_NODES_ARRAY_GUID, treeView.TopLevelSelection);
}
}
readonly AnalyzerTreeNodeDataContext context;
readonly IFileTabManager fileTabManager;
[ImportingConstructor]
AnalyzerManager(IWpfCommandManager wpfCommandManager, IFileTabManager fileTabManager, ITreeViewManager treeViewManager, IMenuManager menuManager, IThemeManager themeManager, IAnalyzerSettings analyzerSettings, IDotNetImageManager dotNetImageManager, ILanguageManager languageManager) {
this.fileTabManager = fileTabManager;
this.context = new AnalyzerTreeNodeDataContext {
DotNetImageManager = dotNetImageManager,
Language = languageManager.Language,
FileManager = fileTabManager.FileTreeView.FileManager,
ShowToken = analyzerSettings.ShowToken,
SingleClickExpandsChildren = analyzerSettings.SingleClickExpandsChildren,
SyntaxHighlight = analyzerSettings.SyntaxHighlight,
UseNewRenderer = analyzerSettings.UseNewRenderer,
AnalyzerManager = this,
};
var options = new TreeViewOptions {
CanDragAndDrop = false,
TreeViewListener = this,
};
this.treeView = treeViewManager.Create(ANALYZER_TREEVIEW_GUID, options);
fileTabManager.FileTreeView.FileManager.CollectionChanged += FileManager_CollectionChanged;
fileTabManager.FileModified += FileTabManager_FileModified;
languageManager.LanguageChanged += LanguageManager_LanguageChanged;
themeManager.ThemeChanged += ThemeManager_ThemeChanged;
analyzerSettings.PropertyChanged += AnalyzerSettings_PropertyChanged;
menuManager.InitializeContextMenu((FrameworkElement)this.treeView.UIObject, new Guid(MenuConstants.GUIDOBJ_ANALYZER_TREEVIEW_GUID), new GuidObjectsCreator(this.treeView));
wpfCommandManager.Add(CommandConstants.GUID_ANALYZER_TREEVIEW, (UIElement)this.treeView.UIObject);
var cmds = wpfCommandManager.GetCommands(CommandConstants.GUID_ANALYZER_TREEVIEW);
var command = new RelayCommand(a => ActivateNode());
cmds.Add(command, ModifierKeys.Control, Key.Enter);
cmds.Add(command, ModifierKeys.Shift, Key.Enter);
}
void FileTabManager_FileModified(object sender, FileModifiedEventArgs e) {
AnalyzerTreeNodeData.HandleModelUpdated(treeView.Root, e.Files);
RefreshNodes();
}
void ActivateNode() {
var nodes = treeView.TopLevelSelection;
var node = nodes.Length == 0 ? null : nodes[0] as ITreeNodeData;
if (node != null)
node.Activate();
}
void FileManager_CollectionChanged(object sender, NotifyFileCollectionChangedEventArgs e) {
switch (e.Type) {
case NotifyFileCollectionType.Clear:
ClearAll();
break;
case NotifyFileCollectionType.Add:
AnalyzerTreeNodeData.HandleAssemblyListChanged(treeView.Root, new IDnSpyFile[0], e.Files);
break;
case NotifyFileCollectionType.Remove:
AnalyzerTreeNodeData.HandleAssemblyListChanged(treeView.Root, e.Files, new IDnSpyFile[0]);
break;
default:
break;
}
}
void LanguageManager_LanguageChanged(object sender, EventArgs e) {
this.context.Language = ((ILanguageManager)sender).Language;
RefreshNodes();
}
void AnalyzerSettings_PropertyChanged(object sender, PropertyChangedEventArgs e) {
var analyzerSettings = (IAnalyzerSettings)sender;
switch (e.PropertyName) {
case "ShowToken":
context.ShowToken = analyzerSettings.ShowToken;
RefreshNodes();
break;
case "SyntaxHighlight":
context.SyntaxHighlight = analyzerSettings.SyntaxHighlight;
RefreshNodes();
break;
case "UseNewRenderer":
context.UseNewRenderer = analyzerSettings.UseNewRenderer;
RefreshNodes();
break;
}
}
void ThemeManager_ThemeChanged(object sender, ThemeChangedEventArgs e) {
RefreshNodes();
}
void RefreshNodes() {
this.treeView.RefreshAllNodes();
}
void ITreeViewListener.OnEvent(ITreeView treeView, TreeViewListenerEventArgs e) {
if (e.Event == TreeViewListenerEvent.NodeCreated) {
Debug.Assert(context != null);
var node = (ITreeNode)e.Argument;
var d = node.Data as IAnalyzerTreeNodeData;
if (d != null)
d.Context = context;
return;
}
}
void Cancel() {
AnalyzerTreeNodeData.CancelSelfAndChildren(treeView.Root.Data);
}
public void OnClose() {
ClearAll();
}
void ClearAll() {
Cancel();
this.treeView.Root.Children.Clear();
}
public void Add(IAnalyzerTreeNodeData node) {
if (node is EntityNode) {
var an = node as EntityNode;
var found = this.treeView.Root.DataChildren.OfType<EntityNode>().FirstOrDefault(n => n.Member == an.Member);
if (found != null) {
found.TreeNode.IsExpanded = true;
this.treeView.SelectItems(new ITreeNodeData[] { found });
this.treeView.Focus();
return;
}
}
this.treeView.Root.Children.Add(this.treeView.Create(node));
node.TreeNode.IsExpanded = true;
this.treeView.SelectItems(new ITreeNodeData[] { node });
this.treeView.Focus();
}
public void OnActivated(IAnalyzerTreeNodeData node) {
if (node == null)
throw new ArgumentNullException();
bool newTab = Keyboard.Modifiers == ModifierKeys.Control || Keyboard.Modifiers == ModifierKeys.Shift;
FollowNode(node, newTab, null);
}
public void FollowNode(ITreeNodeData node, bool newTab, bool? useCodeRef) {
var tokNode = node as IMDTokenNode;
var @ref = tokNode == null ? null : tokNode.Reference;
var entityNode = node as EntityNode;
var srcRef = entityNode == null ? null : entityNode.SourceRef;
bool code = useCodeRef ?? srcRef != null;
if (code) {
if (srcRef == null)
return;
fileTabManager.FollowReference(srcRef.Value.Method, newTab, true, a => {
if (!a.HasMovedCaret && a.Success && srcRef != null)
a.HasMovedCaret = GoTo(a.Tab, srcRef.Value.Method, srcRef.Value.ILOffset, srcRef.Value.Reference);
});
}
else {
if (@ref == null)
return;
fileTabManager.FollowReference(@ref, newTab);
}
}
public bool CanFollowNode(ITreeNodeData node, bool useCodeRef) {
var tokNode = node as IMDTokenNode;
var @ref = tokNode == null ? null : tokNode.Reference;
var entityNode = node as EntityNode;
var srcRef = entityNode == null ? null : entityNode.SourceRef;
if (useCodeRef)
return srcRef != null;
return @ref != null;
}
bool GoTo(IFileTab tab, MethodDef method, uint? ilOffset, object @ref) {
if (method == null || ilOffset == null)
return false;
var uiContext = tab.TryGetTextEditorUIContext();
if (uiContext == null)
return false;
var cm = uiContext.GetCodeMappings();
var mapping = cm.Find(method, ilOffset.Value);
if (mapping == null)
return false;
var location = mapping.StartPosition;
var loc = FindLocation(uiContext.GetCodeReferences(location.Line, location.Column), mapping.EndPosition, @ref);
if (loc == null)
loc = new TextEditorLocation(location.Line, location.Column);
uiContext.ScrollAndMoveCaretTo(loc.Value.Line, loc.Value.Column);
return true;
}
TextEditorLocation? FindLocation(IEnumerable<Tuple<CodeReference, TextEditorLocation>> infos, TextPosition endLoc, object @ref) {
foreach (var info in infos) {
int c = Compare(info.Item2, endLoc);
if (c > 0)
break;
if (RefEquals(@ref, info.Item1.Reference))
return info.Item2;
}
return null;
}
static int Compare(TextEditorLocation a, TextPosition b) {
if (a.Line > b.Line)
return 1;
if (a.Line == b.Line)
return a.Column.CompareTo(b.Column);
return -1;
}
static bool RefEquals(object a, object b) {
if (Equals(a, b))
return true;
if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
return false;
{
var pb = b as PropertyDef;
if (pb != null) {
var tmp = a;
a = b;
b = tmp;
}
var eb = b as EventDef;
if (eb != null) {
var tmp = a;
a = b;
b = tmp;
}
}
const SigComparerOptions flags = SigComparerOptions.CompareDeclaringTypes | SigComparerOptions.PrivateScopeIsComparable;
var type = a as IType;
if (type != null)
return new SigComparer().Equals(type, b as IType);
var method = a as IMethod;
if (method != null && method.IsMethod)
return new SigComparer(flags).Equals(method, b as IMethod);
var field = a as IField;
if (field != null && field.IsField)
return new SigComparer(flags).Equals(field, b as IField);
var prop = a as PropertyDef;
if (prop != null) {
if (new SigComparer(flags).Equals(prop, b as PropertyDef))
return true;
var bm = b as IMethod;
return bm != null &&
(new SigComparer(flags).Equals(prop.GetMethod, bm) ||
new SigComparer(flags).Equals(prop.SetMethod, bm));
}
var evt = a as EventDef;
if (evt != null) {
if (new SigComparer(flags).Equals(evt, b as EventDef))
return true;
var bm = b as IMethod;
return bm != null &&
(new SigComparer(flags).Equals(evt.AddMethod, bm) ||
new SigComparer(flags).Equals(evt.InvokeMethod, bm) ||
new SigComparer(flags).Equals(evt.RemoveMethod, bm));
}
Debug.Fail("Shouldn't be here");
return false;
}
}
}

Просмотреть файл

@ -0,0 +1,129 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.ComponentModel;
using System.ComponentModel.Composition;
using dnSpy.Contracts.Settings;
using dnSpy.Shared.MVVM;
namespace dnSpy.Analyzer {
interface IAnalyzerSettings : INotifyPropertyChanged {
bool SyntaxHighlight { get; }
bool ShowToken { get; }
bool SingleClickExpandsChildren { get; }
bool UseNewRenderer { get; }
}
class AnalyzerSettings : ViewModelBase, IAnalyzerSettings {
protected virtual void OnModified() {
}
public bool SyntaxHighlight {
get { return syntaxHighlight; }
set {
if (syntaxHighlight != value) {
syntaxHighlight = value;
OnPropertyChanged("SyntaxHighlight");
OnModified();
}
}
}
bool syntaxHighlight = true;
public bool ShowToken {
get { return showToken; }
set {
if (showToken != value) {
showToken = value;
OnPropertyChanged("ShowToken");
OnModified();
}
}
}
bool showToken = true;
public bool SingleClickExpandsChildren {
get { return singleClickExpandsChildren; }
set {
if (singleClickExpandsChildren != value) {
singleClickExpandsChildren = value;
OnPropertyChanged("SingleClickExpandsChildren");
OnModified();
}
}
}
bool singleClickExpandsChildren = true;
public bool UseNewRenderer {
get { return useNewRenderer; }
set {
if (useNewRenderer != value) {
useNewRenderer = value;
OnPropertyChanged("UseNewRenderer");
OnModified();
}
}
}
bool useNewRenderer = false;
public AnalyzerSettings Clone() {
return CopyTo(new AnalyzerSettings());
}
public AnalyzerSettings CopyTo(AnalyzerSettings other) {
other.SyntaxHighlight = this.SyntaxHighlight;
other.ShowToken = this.ShowToken;
other.SingleClickExpandsChildren = this.SingleClickExpandsChildren;
other.UseNewRenderer = this.UseNewRenderer;
return other;
}
}
[Export, Export(typeof(IAnalyzerSettings)), PartCreationPolicy(CreationPolicy.Shared)]
sealed class AnalyzerSettingsImpl : AnalyzerSettings {
static readonly Guid SETTINGS_GUID = new Guid("0A9208EC-CFAB-41C2-82C6-FCDA44A8E684");
readonly ISettingsManager settingsManager;
[ImportingConstructor]
AnalyzerSettingsImpl(ISettingsManager settingsManager) {
this.settingsManager = settingsManager;
this.disableSave = true;
var sect = settingsManager.GetOrCreateSection(SETTINGS_GUID);
this.SyntaxHighlight = sect.Attribute<bool?>("SyntaxHighlight") ?? this.SyntaxHighlight;
this.ShowToken = sect.Attribute<bool?>("ShowToken") ?? this.ShowToken;
this.SingleClickExpandsChildren = sect.Attribute<bool?>("SingleClickExpandsChildren") ?? this.SingleClickExpandsChildren;
this.UseNewRenderer = sect.Attribute<bool?>("UseNewRenderer") ?? this.UseNewRenderer;
this.disableSave = false;
}
readonly bool disableSave;
protected override void OnModified() {
if (disableSave)
return;
var sect = settingsManager.RecreateSection(SETTINGS_GUID);
sect.Attribute("SyntaxHighlight", SyntaxHighlight);
sect.Attribute("ShowToken", ShowToken);
sect.Attribute("SingleClickExpandsChildren", SingleClickExpandsChildren);
sect.Attribute("UseNewRenderer", UseNewRenderer);
}
}
}

Просмотреть файл

@ -0,0 +1,102 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Windows;
using dnSpy.Analyzer.Properties;
using dnSpy.Contracts.Controls;
using dnSpy.Contracts.ToolWindows;
using dnSpy.Contracts.ToolWindows.App;
namespace dnSpy.Analyzer {
[Export(typeof(IMainToolWindowContentCreator))]
sealed class AnalyzerToolWindowContentCreator : IMainToolWindowContentCreator {
readonly Lazy<IAnalyzerManager> analyzerManager;
public AnalyzerToolWindowContent FileTreeViewWindowContent {
get { return analyzerToolWindowContent ?? (analyzerToolWindowContent = new AnalyzerToolWindowContent(analyzerManager)); }
}
AnalyzerToolWindowContent analyzerToolWindowContent;
[ImportingConstructor]
AnalyzerToolWindowContentCreator(Lazy<IAnalyzerManager> analyzerManager) {
this.analyzerManager = analyzerManager;
}
public IEnumerable<ToolWindowContentInfo> ContentInfos {
get { yield return new ToolWindowContentInfo(AnalyzerToolWindowContent.THE_GUID, AnalyzerToolWindowContent.DEFAULT_LOCATION, AppToolWindowConstants.DEFAULT_CONTENT_ORDER_BOTTOM_ANALYZER, false); }
}
public IToolWindowContent GetOrCreate(Guid guid) {
if (guid == AnalyzerToolWindowContent.THE_GUID)
return FileTreeViewWindowContent;
return null;
}
}
sealed class AnalyzerToolWindowContent : IToolWindowContent, IFocusable {
public static readonly Guid THE_GUID = new Guid("5827D693-A5DF-4D65-B1F8-ACF249508A96");
public const AppToolWindowLocation DEFAULT_LOCATION = AppToolWindowLocation.DefaultHorizontal;
public IInputElement FocusedElement {
get { return null; }
}
public FrameworkElement ScaleElement {
get { return analyzerManager.Value.TreeView.UIObject as FrameworkElement; }
}
public Guid Guid {
get { return THE_GUID; }
}
public string Title {
get { return dnSpy_Analyzer_Resources.AnalyzerWindowTitle; }
}
public object ToolTip {
get { return null; }
}
public object UIObject {
get { return analyzerManager.Value.TreeView.UIObject; }
}
public bool CanFocus {
get { return true; }
}
readonly Lazy<IAnalyzerManager> analyzerManager;
public AnalyzerToolWindowContent(Lazy<IAnalyzerManager> analyzerManager) {
this.analyzerManager = analyzerManager;
}
public void OnVisibilityChanged(ToolWindowContentVisibilityEvent visEvent) {
if (visEvent == ToolWindowContentVisibilityEvent.Removed)
analyzerManager.Value.OnClose();
}
public void Focus() {
analyzerManager.Value.TreeView.Focus();
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using dnSpy.Analyzer.TreeNodes;
using dnSpy.Contracts.Files;
using dnSpy.Contracts.Images;
using dnSpy.Contracts.Languages;
namespace dnSpy.Analyzer {
sealed class AnalyzerTreeNodeDataContext : IAnalyzerTreeNodeDataContext {
public IDotNetImageManager DotNetImageManager { get; set; }
public ILanguage Language { get; set; }
public IFileManager FileManager { get; set; }
public IAnalyzerManager AnalyzerManager { get; set; }
public bool ShowToken { get; set; }
public bool SingleClickExpandsChildren { get; set; }
public bool SyntaxHighlight { get; set; }
public bool UseNewRenderer { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,234 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Input;
using dnSpy.Contracts.Controls;
using dnSpy.Contracts.Menus;
using dnSpy.Contracts.Plugin;
using dnSpy.Contracts.TreeView;
using dnSpy.Shared.Menus;
namespace dnSpy.Analyzer {
abstract class OpenReferenceCtxMenuCommandBase : MenuItemBase {
readonly Lazy<IAnalyzerManager> analyzerManager;
readonly bool newTab;
readonly bool useCodeRef;
protected OpenReferenceCtxMenuCommandBase(Lazy<IAnalyzerManager> analyzerManager, bool newTab, bool useCodeRef) {
this.analyzerManager = analyzerManager;
this.newTab = newTab;
this.useCodeRef = useCodeRef;
}
public override void Execute(IMenuItemContext context) {
var @ref = GetReference(context);
if (@ref == null)
return;
analyzerManager.Value.FollowNode(@ref, newTab, useCodeRef);
}
public override bool IsVisible(IMenuItemContext context) {
return GetReference(context) != null;
}
ITreeNodeData GetReference(IMenuItemContext context) {
if (context.CreatorObject.Guid != new Guid(MenuConstants.GUIDOBJ_ANALYZER_TREEVIEW_GUID))
return null;
var nodes = context.Find<ITreeNodeData[]>();
if (nodes == null || nodes.Length != 1)
return null;
var tokenNode = nodes[0] as IMDTokenNode;
if (tokenNode != null && tokenNode.Reference != null) {
if (!analyzerManager.Value.CanFollowNode(nodes[0], useCodeRef))
return null;
return nodes[0];
}
return null;
}
}
[ExportMenuItem(Header = "res:GoToReferenceInCodeCommand", InputGestureText = "res:DoubleClick", Group = MenuConstants.GROUP_CTX_ANALYZER_TABS, Order = 0)]
sealed class OpenReferenceInCodeCtxMenuCommand : OpenReferenceCtxMenuCommandBase {
[ImportingConstructor]
OpenReferenceInCodeCtxMenuCommand(Lazy<IAnalyzerManager> analyzerManager)
: base(analyzerManager, false, true) {
}
}
[ExportMenuItem(Header = "res:GoToReferenceInCodeNewTabCommand", InputGestureText = "res:ShiftDoubleClick", Group = MenuConstants.GROUP_CTX_ANALYZER_TABS, Order = 10)]
sealed class OpenReferenceInCodeNewTabCtxMenuCommand : OpenReferenceCtxMenuCommandBase {
[ImportingConstructor]
OpenReferenceInCodeNewTabCtxMenuCommand(Lazy<IAnalyzerManager> analyzerManager)
: base(analyzerManager, true, true) {
}
}
[ExportMenuItem(Header = "res:GoToReferenceCommand", Group = MenuConstants.GROUP_CTX_ANALYZER_TABS, Order = 20)]
sealed class OpenReferenceCtxMenuCommand : OpenReferenceCtxMenuCommandBase {
[ImportingConstructor]
OpenReferenceCtxMenuCommand(Lazy<IAnalyzerManager> analyzerManager)
: base(analyzerManager, false, false) {
}
}
[ExportMenuItem(Header = "res:GoToReferenceNewTabCommand", Group = MenuConstants.GROUP_CTX_ANALYZER_TABS, Order = 30)]
sealed class OpenReferenceNewTabCtxMenuCommand : OpenReferenceCtxMenuCommandBase {
[ImportingConstructor]
OpenReferenceNewTabCtxMenuCommand(Lazy<IAnalyzerManager> analyzerManager)
: base(analyzerManager, true, false) {
}
}
[ExportAutoLoaded]
sealed class BreakpointsContentCommandLoader : IAutoLoaded {
[ImportingConstructor]
BreakpointsContentCommandLoader(IWpfCommandManager wpfCommandManager, Lazy<IAnalyzerManager> analyzerManager) {
var cmds = wpfCommandManager.GetCommands(CommandConstants.GUID_ANALYZER_TREEVIEW);
cmds.Add(ApplicationCommands.Copy,
(s, e) => CopyCtxMenuCommand.ExecuteInternal(analyzerManager),
(s, e) => e.CanExecute = CopyCtxMenuCommand.CanExecuteInternal(analyzerManager));
}
}
[ExportMenuItem(Header = "res:CopyCommand", InputGestureText = "res:ShortCutKeyCtrlC", Icon = "Copy", Group = MenuConstants.GROUP_CTX_ANALYZER_TOKENS, Order = -1)]
sealed class CopyCtxMenuCommand : MenuItemBase {
readonly Lazy<IAnalyzerManager> analyzerManager;
[ImportingConstructor]
CopyCtxMenuCommand(Lazy<IAnalyzerManager> analyzerManager) {
this.analyzerManager = analyzerManager;
}
public override bool IsVisible(IMenuItemContext context) {
return context.CreatorObject.Guid == new Guid(MenuConstants.GUIDOBJ_ANALYZER_TREEVIEW_GUID);
}
public override bool IsEnabled(IMenuItemContext context) {
return CanExecuteInternal(analyzerManager);
}
public override void Execute(IMenuItemContext context) {
ExecuteInternal(analyzerManager);
}
public static bool CanExecuteInternal(Lazy<IAnalyzerManager> analyzerManager) {
return analyzerManager.Value.TreeView.SelectedItems.Length > 0;
}
public static void ExecuteInternal(Lazy<IAnalyzerManager> analyzerManager) {
var items = analyzerManager.Value.TreeView.SelectedItems;
var sb = new StringBuilder();
int count = 0;
foreach (var t in GetNodes(analyzerManager.Value.TreeView, items)) {
if (count > 0)
sb.Append(Environment.NewLine);
sb.Append(new string('\t', t.Item1));
sb.Append(t.Item2.ToString());
count++;
}
if (count > 1)
sb.Append(Environment.NewLine);
if (sb.Length > 0) {
try {
Clipboard.SetText(sb.ToString());
}
catch (ExternalException) { }
}
}
sealed class State {
public readonly int Level;
public int Index;
public readonly IList<ITreeNode> Nodes;
public State(ITreeNode node, int level) {
this.Level = level;
this.Nodes = node.Children;
}
}
static IEnumerable<Tuple<int, ITreeNodeData>> GetNodes(ITreeView treeView, IEnumerable<ITreeNodeData> nodes) {
var hash = new HashSet<ITreeNodeData>(nodes);
var stack = new Stack<State>();
stack.Push(new State(treeView.Root, 0));
while (stack.Count > 0) {
var state = stack.Pop();
if (state.Index >= state.Nodes.Count)
continue;
var child = state.Nodes[state.Index++];
if (hash.Contains(child.Data))
yield return Tuple.Create(state.Level, child.Data);
stack.Push(state);
stack.Push(new State(child, state.Level + 1));
}
}
}
[ExportMenuItem(Header = "res:ShowMetadataTokensCommand", Group = MenuConstants.GROUP_CTX_ANALYZER_OPTIONS, Order = 0)]
sealed class ShowTokensCtxMenuCommand : MenuItemBase {
readonly AnalyzerSettingsImpl analyzerSettings;
[ImportingConstructor]
ShowTokensCtxMenuCommand(AnalyzerSettingsImpl analyzerSettings) {
this.analyzerSettings = analyzerSettings;
}
public override bool IsVisible(IMenuItemContext context) {
return context.CreatorObject.Guid == new Guid(MenuConstants.GUIDOBJ_ANALYZER_TREEVIEW_GUID);
}
public override bool IsChecked(IMenuItemContext context) {
return analyzerSettings.ShowToken;
}
public override void Execute(IMenuItemContext context) {
analyzerSettings.ShowToken = !analyzerSettings.ShowToken;
}
}
[ExportMenuItem(Header = "res:SyntaxHighlightCommand", Group = MenuConstants.GROUP_CTX_ANALYZER_OPTIONS, Order = 10)]
sealed class SyntaxHighlightCtxMenuCommand : MenuItemBase {
readonly AnalyzerSettingsImpl analyzerSettings;
[ImportingConstructor]
SyntaxHighlightCtxMenuCommand(AnalyzerSettingsImpl analyzerSettings) {
this.analyzerSettings = analyzerSettings;
}
public override bool IsVisible(IMenuItemContext context) {
return context.CreatorObject.Guid == new Guid(MenuConstants.GUIDOBJ_ANALYZER_TREEVIEW_GUID);
}
public override bool IsChecked(IMenuItemContext context) {
return analyzerSettings.SyntaxHighlight;
}
public override void Execute(IMenuItemContext context) {
analyzerSettings.SyntaxHighlight = !analyzerSettings.SyntaxHighlight;
}
}
}

Двоичные данные
Plugins/dnSpy.Analyzer/Images/Copy.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 194 B

Двоичные данные
Plugins/dnSpy.Analyzer/Images/Delete.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 523 B

Двоичные данные
Plugins/dnSpy.Analyzer/Images/Search.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 522 B

Просмотреть файл

@ -0,0 +1,47 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
using System.ComponentModel.Composition;
using dnSpy.Analyzer.Properties;
using dnSpy.Contracts.Plugin;
namespace dnSpy.Analyzer {
[ExportPlugin]
sealed class Plugin : IPlugin {
[ImportingConstructor]
Plugin() {
}
public IEnumerable<string> MergedResourceDictionaries {
get { yield break; }
}
public PluginInfo PluginInfo {
get {
return new PluginInfo {
ShortDescription = dnSpy_Analyzer_Resources.Plugin_ShortDescription,
};
}
}
public void OnEvent(PluginEvent @event, object obj) {
}
}
}

Просмотреть файл

@ -0,0 +1,14 @@
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Analyzer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Analyzer")]
[assembly: AssemblyCopyright("Copyright 2011-2014 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: NeutralResourcesLanguage("en")]

360
Plugins/dnSpy.Analyzer/Properties/dnSpy.Analyzer.Resources.Designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,360 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace dnSpy.Analyzer.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class dnSpy_Analyzer_Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal dnSpy_Analyzer_Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("dnSpy.Analyzer.Properties.dnSpy.Analyzer.Resources", typeof(dnSpy_Analyzer_Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Analy_ze.
/// </summary>
public static string AnalyzeCommand {
get {
return ResourceManager.GetString("AnalyzeCommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Analyzer.
/// </summary>
public static string AnalyzerWindowTitle {
get {
return ResourceManager.GetString("AnalyzerWindowTitle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Applied To.
/// </summary>
public static string AppliedToTreeNode {
get {
return ResourceManager.GetString("AppliedToTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Assigned By.
/// </summary>
public static string AssignedByTreeNode {
get {
return ResourceManager.GetString("AssignedByTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cop_y.
/// </summary>
public static string CopyCommand {
get {
return ResourceManager.GetString("CopyCommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dbl Click.
/// </summary>
public static string DoubleClick {
get {
return ResourceManager.GetString("DoubleClick", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to add.
/// </summary>
public static string EventAdderTreeNodeName {
get {
return ResourceManager.GetString("EventAdderTreeNodeName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to remove.
/// </summary>
public static string EventRemoverTreeNodeName {
get {
return ResourceManager.GetString("EventRemoverTreeNodeName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Exposed By.
/// </summary>
public static string ExposedByTreeNode {
get {
return ResourceManager.GetString("ExposedByTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Extension Methods.
/// </summary>
public static string ExtensionMethodsTreeNode {
get {
return ResourceManager.GetString("ExtensionMethodsTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Go to Reference.
/// </summary>
public static string GoToReferenceCommand {
get {
return ResourceManager.GetString("GoToReferenceCommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show Reference in Method.
/// </summary>
public static string GoToReferenceInCodeCommand {
get {
return ResourceManager.GetString("GoToReferenceInCodeCommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show Reference in Method (New _Tab).
/// </summary>
public static string GoToReferenceInCodeNewTabCommand {
get {
return ResourceManager.GetString("GoToReferenceInCodeNewTabCommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Go to Reference (New Ta_b).
/// </summary>
public static string GoToReferenceNewTabCommand {
get {
return ResourceManager.GetString("GoToReferenceNewTabCommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to hides.
/// </summary>
public static string HidesParent {
get {
return ResourceManager.GetString("HidesParent", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Implemented By.
/// </summary>
public static string ImplementedByTreeNode {
get {
return ResourceManager.GetString("ImplementedByTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Instantiated By.
/// </summary>
public static string InstantiatedByTreeNode {
get {
return ResourceManager.GetString("InstantiatedByTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Overridden By.
/// </summary>
public static string OverriddenByTreeNode {
get {
return ResourceManager.GetString("OverriddenByTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Analyzes assemblies.
/// </summary>
public static string Plugin_ShortDescription {
get {
return ResourceManager.GetString("Plugin_ShortDescription", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to get.
/// </summary>
public static string PropertyGetterTreeNode {
get {
return ResourceManager.GetString("PropertyGetterTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to set.
/// </summary>
public static string PropertySetterTreeNode {
get {
return ResourceManager.GetString("PropertySetterTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Raised By.
/// </summary>
public static string RaisedByTreeNode {
get {
return ResourceManager.GetString("RaisedByTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Read By.
/// </summary>
public static string ReadByTreeNode {
get {
return ResourceManager.GetString("ReadByTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Remove.
/// </summary>
public static string RemoveCommand {
get {
return ResourceManager.GetString("RemoveCommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Searching....
/// </summary>
public static string Searching {
get {
return ResourceManager.GetString("Searching", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shift+Dbl Click.
/// </summary>
public static string ShiftDoubleClick {
get {
return ResourceManager.GetString("ShiftDoubleClick", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ctrl+C.
/// </summary>
public static string ShortCutKeyCtrlC {
get {
return ResourceManager.GetString("ShortCutKeyCtrlC", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ctrl+R.
/// </summary>
public static string ShortCutKeyCtrlR {
get {
return ResourceManager.GetString("ShortCutKeyCtrlR", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Del.
/// </summary>
public static string ShortCutKeyDelete {
get {
return ResourceManager.GetString("ShortCutKeyDelete", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show Tokens.
/// </summary>
public static string ShowMetadataTokensCommand {
get {
return ResourceManager.GetString("ShowMetadataTokensCommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Syntax Highlight.
/// </summary>
public static string SyntaxHighlightCommand {
get {
return ResourceManager.GetString("SyntaxHighlightCommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Used By.
/// </summary>
public static string UsedByTreeNode {
get {
return ResourceManager.GetString("UsedByTreeNode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Uses.
/// </summary>
public static string UsesTreeNode {
get {
return ResourceManager.GetString("UsesTreeNode", resourceCulture);
}
}
}
}

Просмотреть файл

@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AnalyzeCommand" xml:space="preserve">
<value>Analy_ze</value>
</data>
<data name="AnalyzerWindowTitle" xml:space="preserve">
<value>Analyzer</value>
</data>
<data name="AppliedToTreeNode" xml:space="preserve">
<value>Applied To</value>
</data>
<data name="AssignedByTreeNode" xml:space="preserve">
<value>Assigned By</value>
</data>
<data name="CopyCommand" xml:space="preserve">
<value>Cop_y</value>
</data>
<data name="DoubleClick" xml:space="preserve">
<value>Dbl Click</value>
</data>
<data name="EventAdderTreeNodeName" xml:space="preserve">
<value>add</value>
</data>
<data name="EventRemoverTreeNodeName" xml:space="preserve">
<value>remove</value>
</data>
<data name="ExposedByTreeNode" xml:space="preserve">
<value>Exposed By</value>
</data>
<data name="ExtensionMethodsTreeNode" xml:space="preserve">
<value>Extension Methods</value>
</data>
<data name="GoToReferenceCommand" xml:space="preserve">
<value>Go to Reference</value>
</data>
<data name="GoToReferenceInCodeCommand" xml:space="preserve">
<value>Show Reference in Method</value>
</data>
<data name="GoToReferenceInCodeNewTabCommand" xml:space="preserve">
<value>Show Reference in Method (New _Tab)</value>
</data>
<data name="GoToReferenceNewTabCommand" xml:space="preserve">
<value>Go to Reference (New Ta_b)</value>
</data>
<data name="HidesParent" xml:space="preserve">
<value>hides</value>
</data>
<data name="ImplementedByTreeNode" xml:space="preserve">
<value>Implemented By</value>
</data>
<data name="InstantiatedByTreeNode" xml:space="preserve">
<value>Instantiated By</value>
</data>
<data name="OverriddenByTreeNode" xml:space="preserve">
<value>Overridden By</value>
</data>
<data name="Plugin_ShortDescription" xml:space="preserve">
<value>Analyzes assemblies</value>
</data>
<data name="PropertyGetterTreeNode" xml:space="preserve">
<value>get</value>
</data>
<data name="PropertySetterTreeNode" xml:space="preserve">
<value>set</value>
</data>
<data name="RaisedByTreeNode" xml:space="preserve">
<value>Raised By</value>
</data>
<data name="ReadByTreeNode" xml:space="preserve">
<value>Read By</value>
</data>
<data name="RemoveCommand" xml:space="preserve">
<value>_Remove</value>
</data>
<data name="Searching" xml:space="preserve">
<value>Searching...</value>
</data>
<data name="ShiftDoubleClick" xml:space="preserve">
<value>Shift+Dbl Click</value>
</data>
<data name="ShortCutKeyCtrlC" xml:space="preserve">
<value>Ctrl+C</value>
</data>
<data name="ShortCutKeyCtrlR" xml:space="preserve">
<value>Ctrl+R</value>
</data>
<data name="ShortCutKeyDelete" xml:space="preserve">
<value>Del</value>
</data>
<data name="ShowMetadataTokensCommand" xml:space="preserve">
<value>Show Tokens</value>
</data>
<data name="SyntaxHighlightCommand" xml:space="preserve">
<value>Syntax Highlight</value>
</data>
<data name="UsedByTreeNode" xml:space="preserve">
<value>Used By</value>
</data>
<data name="UsesTreeNode" xml:space="preserve">
<value>Uses</value>
</data>
</root>

Просмотреть файл

@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AnalyzeCommand" xml:space="preserve">
<value>Анали_зировать</value>
</data>
<data name="AnalyzerWindowTitle" xml:space="preserve">
<value>Анализатор</value>
</data>
<data name="AppliedToTreeNode" xml:space="preserve">
<value>Применяется к</value>
</data>
<data name="AssignedByTreeNode" xml:space="preserve">
<value>Кем назначено</value>
</data>
<data name="CopyCommand" xml:space="preserve">
<value>Коп_ировать</value>
</data>
<data name="DoubleClick" xml:space="preserve">
<value>Dbl Click</value>
</data>
<data name="EventAdderTreeNodeName" xml:space="preserve">
<value>add</value>
</data>
<data name="EventRemoverTreeNodeName" xml:space="preserve">
<value>remove</value>
</data>
<data name="ExposedByTreeNode" xml:space="preserve">
<value>Кем представлено</value>
</data>
<data name="ExtensionMethodsTreeNode" xml:space="preserve">
<value>Методы расширения</value>
</data>
<data name="GoToReferenceCommand" xml:space="preserve">
<value>Перейти по ссылке</value>
</data>
<data name="GoToReferenceInCodeCommand" xml:space="preserve">
<value>Показать ссылку на метод</value>
</data>
<data name="GoToReferenceInCodeNewTabCommand" xml:space="preserve">
<value>Показать ссылку в методе (новая _вкладка)</value>
</data>
<data name="GoToReferenceNewTabCommand" xml:space="preserve">
<value>Перейти к ссылке (New Ta_b)</value>
</data>
<data name="HidesParent" xml:space="preserve">
<value>hides</value>
</data>
<data name="ImplementedByTreeNode" xml:space="preserve">
<value>Реализовано в</value>
</data>
<data name="InstantiatedByTreeNode" xml:space="preserve">
<value>Вызвано в</value>
</data>
<data name="OverriddenByTreeNode" xml:space="preserve">
<value>Перегружен в</value>
</data>
<data name="Plugin_ShortDescription" xml:space="preserve">
<value>Анализирует сборки</value>
</data>
<data name="PropertyGetterTreeNode" xml:space="preserve">
<value>get</value>
</data>
<data name="PropertySetterTreeNode" xml:space="preserve">
<value>set</value>
</data>
<data name="RaisedByTreeNode" xml:space="preserve">
<value>Кем вызвано</value>
</data>
<data name="ReadByTreeNode" xml:space="preserve">
<value>Кем читается</value>
</data>
<data name="RemoveCommand" xml:space="preserve">
<value>_Убрать</value>
</data>
<data name="Searching" xml:space="preserve">
<value>Поиск...</value>
</data>
<data name="ShiftDoubleClick" xml:space="preserve">
<value>Shift+Dbl Click</value>
</data>
<data name="ShortCutKeyCtrlC" xml:space="preserve">
<value>Ctrl+C</value>
</data>
<data name="ShortCutKeyCtrlR" xml:space="preserve">
<value>Ctrl+R</value>
</data>
<data name="ShortCutKeyDelete" xml:space="preserve">
<value>Del</value>
</data>
<data name="ShowMetadataTokensCommand" xml:space="preserve">
<value>Показать токены</value>
</data>
<data name="SyntaxHighlightCommand" xml:space="preserve">
<value>Подсветка синтаксиса</value>
</data>
<data name="UsedByTreeNode" xml:space="preserve">
<value>Используется</value>
</data>
<data name="UsesTreeNode" xml:space="preserve">
<value>Использует</value>
</data>
</root>

Просмотреть файл

@ -0,0 +1,219 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AnalyzeCommand" xml:space="preserve">
<value>分析(_Z)</value>
</data>
<data name="AnalyzerWindowTitle" xml:space="preserve">
<value>分析器</value>
</data>
<data name="AppliedToTreeNode" xml:space="preserve">
<value>已应用到</value>
</data>
<data name="AssignedByTreeNode" xml:space="preserve">
<value>被赋值</value>
</data>
<data name="CopyCommand" xml:space="preserve">
<value>复制(_Y)</value>
</data>
<data name="DoubleClick" xml:space="preserve">
<value>双击</value>
</data>
<data name="EventAdderTreeNodeName" xml:space="preserve">
<value>添加</value>
</data>
<data name="EventRemoverTreeNodeName" xml:space="preserve">
<value>移除</value>
</data>
<data name="ExposedByTreeNode" xml:space="preserve">
<value>被公开</value>
</data>
<data name="ExtensionMethodsTreeNode" xml:space="preserve">
<value>扩展方法</value>
</data>
<data name="GoToReferenceCommand" xml:space="preserve">
<value>转到引用</value>
</data>
<data name="GoToReferenceInCodeCommand" xml:space="preserve">
<value>显示方法内的引用</value>
</data>
<data name="GoToReferenceInCodeNewTabCommand" xml:space="preserve">
<value>显示方法内引用(新标签)</value>
</data>
<data name="GoToReferenceNewTabCommand" xml:space="preserve">
<value>转到引用(新标签)(_B)</value>
</data>
<data name="HidesParent" xml:space="preserve">
<value>隐藏</value>
</data>
<data name="ImplementedByTreeNode" xml:space="preserve">
<value>被实现</value>
</data>
<data name="InstantiatedByTreeNode" xml:space="preserve">
<value>被实例化</value>
</data>
<data name="OverriddenByTreeNode" xml:space="preserve">
<value>被重写</value>
</data>
<data name="Plugin_ShortDescription" xml:space="preserve">
<value>分析程序集</value>
</data>
<data name="PropertyGetterTreeNode" xml:space="preserve">
<value>get</value>
</data>
<data name="PropertySetterTreeNode" xml:space="preserve">
<value>set</value>
</data>
<data name="RaisedByTreeNode" xml:space="preserve">
<value>被触发</value>
</data>
<data name="ReadByTreeNode" xml:space="preserve">
<value>被读取</value>
</data>
<data name="RemoveCommand" xml:space="preserve">
<value>移除(_R)</value>
</data>
<data name="Searching" xml:space="preserve">
<value>搜索中…</value>
</data>
<data name="ShiftDoubleClick" xml:space="preserve">
<value>Shift+双击</value>
</data>
<data name="ShortCutKeyCtrlC" xml:space="preserve">
<value>Ctrl+C</value>
</data>
<data name="ShortCutKeyCtrlR" xml:space="preserve">
<value>Ctrl+R</value>
</data>
<data name="ShortCutKeyDelete" xml:space="preserve">
<value>Del</value>
</data>
<data name="ShowMetadataTokensCommand" xml:space="preserve">
<value>显示Tokens</value>
</data>
<data name="SyntaxHighlightCommand" xml:space="preserve">
<value>语法高亮</value>
</data>
<data name="UsedByTreeNode" xml:space="preserve">
<value>被使用</value>
</data>
<data name="UsesTreeNode" xml:space="preserve">
<value>使用</value>
</data>
</root>

Просмотреть файл

@ -0,0 +1,162 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Linq;
using dnlib.DotNet;
using dnSpy.Contracts.Files;
using dnSpy.Contracts.Highlighting;
using dnSpy.Contracts.Images;
using dnSpy.Contracts.Languages;
using dnSpy.Contracts.TreeView;
using dnSpy.Shared.Highlighting;
using dnSpy.Shared.TreeView;
namespace dnSpy.Analyzer.TreeNodes {
abstract class AnalyzerTreeNodeData : TreeNodeData, IAnalyzerTreeNodeData {
public override Guid Guid {
get { return Guid.Empty; }
}
public sealed override bool SingleClickExpandsChildren {
get { return Context.SingleClickExpandsChildren; }
}
public IAnalyzerTreeNodeDataContext Context { get; set; }
protected abstract ImageReference GetIcon(IDotNetImageManager dnImgMgr);
protected virtual ImageReference? GetExpandedIcon(IDotNetImageManager dnImgMgr) {
return null;
}
public sealed override ImageReference Icon {
get { return GetIcon(this.Context.DotNetImageManager); }
}
public sealed override ImageReference? ExpandedIcon {
get { return GetExpandedIcon(this.Context.DotNetImageManager); }
}
public sealed override object Text {
get {
var gen = UISyntaxHighlighter.Create(Context.SyntaxHighlight);
var cached = cachedText != null ? cachedText.Target : null;
if (cached != null)
return cached;
Write(gen.Output, Context.Language);
var text = gen.CreateResultNewFormatter(Context.UseNewRenderer, filterOutNewLines: true);
cachedText = new WeakReference(text);
return text;
}
}
WeakReference cachedText;
protected abstract void Write(ISyntaxHighlightOutput output, ILanguage language);
public sealed override object ToolTip {
get { return null; }
}
public sealed override string ToString() {
return ToString(Context.Language);
}
public string ToString(ILanguage language) {
var output = new NoSyntaxHighlightOutput();
Write(output, language);
return output.ToString();
}
public sealed override void OnRefreshUI() {
cachedText = null;
}
public abstract bool HandleAssemblyListChanged(IDnSpyFile[] removedAssemblies, IDnSpyFile[] addedAssemblies);
public abstract bool HandleModelUpdated(IDnSpyFile[] files);
public static void CancelSelfAndChildren(ITreeNodeData node) {
foreach (var c in node.DescendantsAndSelf()) {
var id = c as IAsyncCancellable;
if (id != null)
id.Cancel();
}
}
public static void HandleAssemblyListChanged(ITreeNode node, IDnSpyFile[] removedAssemblies, IDnSpyFile[] addedAssemblies) {
var children = node.DataChildren.ToArray();
for (int i = children.Length - 1; i >= 0; i--) {
var c = children[i];
var n = c as IAnalyzerTreeNodeData;
if (n == null || !n.HandleAssemblyListChanged(removedAssemblies, addedAssemblies)) {
AnalyzerTreeNodeData.CancelSelfAndChildren(c);
node.Children.RemoveAt(i);
}
}
}
public static void HandleModelUpdated(ITreeNode node, IDnSpyFile[] files) {
var children = node.DataChildren.ToArray();
for (int i = children.Length - 1; i >= 0; i--) {
var c = children[i];
var n = c as IAnalyzerTreeNodeData;
if (n == null || !n.HandleModelUpdated(files)) {
AnalyzerTreeNodeData.CancelSelfAndChildren(c);
node.Children.RemoveAt(i);
}
}
}
protected IMemberRef GetOriginalCodeLocation(IMemberRef member) {
// Emulate the original code. Only the C# override returned something other than the input
if (Context.Language.UniqueGuid != LanguageConstants.LANGUAGE_CSHARP_ILSPY)
return member;
if (!Context.Language.Settings.GetBoolean(DecompilerOptionConstants.AnonymousMethods_GUID))
return member;
return Helpers.GetOriginalCodeLocation(member);
}
sealed class TheTreeNodeGroup : ITreeNodeGroup {
public static ITreeNodeGroup Instance = new TheTreeNodeGroup();
TheTreeNodeGroup() {
}
public double Order {
get { return 100; }
}
public int Compare(ITreeNodeData x, ITreeNodeData y) {
if (x == y)
return 0;
var a = x as IAnalyzerTreeNodeData;
var b = y as IAnalyzerTreeNodeData;
if (a == null) return -1;
if (b == null) return 1;
return StringComparer.OrdinalIgnoreCase.Compare(a.ToString(), b.ToString());
}
}
public override ITreeNodeGroup TreeNodeGroup {
get { return TheTreeNodeGroup.Instance; }
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
// Copyright (c) 2011 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 dnlib.DotNet;
using dnSpy.Contracts.Highlighting;
using dnSpy.Contracts.Images;
using dnSpy.Contracts.Languages;
using dnSpy.Shared.Highlighting;
namespace dnSpy.Analyzer.TreeNodes {
sealed class AssemblyNode : EntityNode {
readonly AssemblyDef analyzedAssembly;
public AssemblyNode(AssemblyDef analyzedAssembly) {
this.analyzedAssembly = analyzedAssembly;
}
protected override ImageReference GetIcon(IDotNetImageManager dnImgMgr) {
return dnImgMgr.GetImageReference(analyzedAssembly);
}
protected override void Write(ISyntaxHighlightOutput output, ILanguage language) {
output.Write(analyzedAssembly);
}
public override IMemberRef Member {
get { return null; }
}
public override IMDTokenProvider Reference {
get { return analyzedAssembly; }
}
}
}

Просмотреть файл

@ -0,0 +1,93 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using dnSpy.Analyzer.Properties;
using dnSpy.Contracts.Files.TreeView;
using dnSpy.Contracts.Images;
using dnSpy.Contracts.TreeView;
using dnSpy.Shared.TreeView;
namespace dnSpy.Analyzer.TreeNodes {
sealed class AsyncFetchChildrenHelper : AsyncNodeCreator {
readonly SearchNode node;
readonly Action completed;
public AsyncFetchChildrenHelper(SearchNode node, Action completed)
: base(node) {
this.node = node;
this.completed = completed;
Start();
}
sealed class MessageNodeTreeNodeGroup : ITreeNodeGroup {
public double Order {
get { return order; }
set { order = value; }
}
double order;
public int Compare(ITreeNodeData x, ITreeNodeData y) {
if (x == y)
return 0;
var a = x as IMessageNode;
var b = y as IMessageNode;
if (a == null) return -1;
if (b == null) return 1;
return 0;
}
}
sealed class MessageNode : TreeNodeData {
public override Guid Guid {
get { return Guid.Empty; }
}
public override ImageReference Icon {
get { return new ImageReference(GetType().Assembly, "Search"); }
}
public override object Text {
get { return dnSpy_Analyzer_Resources.Searching; }
}
public override object ToolTip {
get { return null; }
}
public override void OnRefreshUI() {
}
public override ITreeNodeGroup TreeNodeGroup {
get { return treeNodeGroup; }
}
readonly ITreeNodeGroup treeNodeGroup = new MessageNodeTreeNodeGroup();
}
protected override void ThreadMethod() {
AddMessageNode(() => new MessageNode());
foreach (var child in node.FetchChildrenInternal(cancellationToken))
AddNode(child);
}
protected override void OnCompleted() {
completed();
}
}
}

Просмотреть файл

@ -0,0 +1,366 @@
// Copyright (c) 2011 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.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using dnlib.DotNet;
using dnlib.Threading;
using dnSpy.Analyzer.Properties;
using dnSpy.Contracts.Highlighting;
using dnSpy.Contracts.Languages;
using dnSpy.Decompiler.Shared;
namespace dnSpy.Analyzer.TreeNodes {
sealed class AttributeAppliedToNode : SearchNode {
readonly TypeDef analyzedType;
readonly string attributeName;
AttributeTargets usage = AttributeTargets.All;
bool allowMutiple;
bool inherited = true;
ConcurrentDictionary<MethodDef, int> foundMethods;
public static bool CanShow(TypeDef type) {
return type.IsClass && IsCustomAttribute(type);
}
static bool IsCustomAttribute(TypeDef type) {
while (type != null) {
var bt = type.BaseType.ResolveTypeDef();
if (bt == null)
return false;
if (bt.FullName == "System.Attribute")
return true;
type = bt;
}
return false;
}
public AttributeAppliedToNode(TypeDef analyzedType) {
if (analyzedType == null)
throw new ArgumentNullException("analyzedType");
this.analyzedType = analyzedType;
attributeName = this.analyzedType.FullName;
GetAttributeUsage();
}
void GetAttributeUsage() {
if (analyzedType.HasCustomAttributes) {
foreach (CustomAttribute ca in analyzedType.CustomAttributes) {
ITypeDefOrRef t = ca.AttributeType;
if (t != null && t.Name == "AttributeUsageAttribute" && t.Namespace == "System" &&
ca.ConstructorArguments.Count > 0 &&
ca.ConstructorArguments[0].Value is int) {
this.usage = (AttributeTargets)ca.ConstructorArguments[0].Value;
if (ca.ConstructorArguments.Count > 2) {
if (ca.ConstructorArguments[1].Value is bool)
this.allowMutiple = (bool)ca.ConstructorArguments[1].Value;
if (ca.ConstructorArguments[2].Value is bool)
this.inherited = (bool)ca.ConstructorArguments[2].Value;
}
foreach (var namedArgument in ca.Properties) {
switch (namedArgument.Name) {
case "AllowMultiple":
if (namedArgument.Argument.Value is bool)
this.allowMutiple = (bool)namedArgument.Argument.Value;
break;
case "Inherited":
if (namedArgument.Argument.Value is bool)
this.inherited = (bool)namedArgument.Argument.Value;
break;
}
}
}
}
}
}
protected override void Write(ISyntaxHighlightOutput output, ILanguage language) {
output.Write(dnSpy_Analyzer_Resources.AppliedToTreeNode, TextTokenKind.Text);
}
protected override IEnumerable<IAnalyzerTreeNodeData> FetchChildren(CancellationToken ct) {
foundMethods = new ConcurrentDictionary<MethodDef, int>();
//get the assemblies to search
var currentAssembly = analyzedType.Module.Assembly;
var modules = analyzedType.IsPublic ? GetReferencingModules(analyzedType.Module, ct) : GetModuleAndAnyFriends(analyzedType.Module, ct);
var results = modules.AsParallel().WithCancellation(ct).SelectMany(a => FindReferencesInModule(new[] { a.Item1 }, a.Item2, ct));
foreach (var result in results)
yield return result;
foundMethods = null;
}
IEnumerable<IAnalyzerTreeNodeData> FindReferencesInModule(IEnumerable<ModuleDef> modules, ITypeDefOrRef tr, CancellationToken ct) {
var checkedAsms = new HashSet<AssemblyDef>();
foreach (var module in modules) {
if ((usage & AttributeTargets.Assembly) != 0) {
AssemblyDef asm = module.Assembly;
if (asm != null && !checkedAsms.Contains(asm) && asm.HasCustomAttributes) {
checkedAsms.Add(asm);
foreach (var attribute in asm.CustomAttributes) {
if (new SigComparer().Equals(attribute.AttributeType, tr)) {
yield return new AssemblyNode(asm) { Context = Context };
break;
}
}
}
}
ct.ThrowIfCancellationRequested();
if ((usage & AttributeTargets.Module) != 0) {
if (module.HasCustomAttributes) {
foreach (var attribute in module.CustomAttributes) {
if (new SigComparer().Equals(attribute.AttributeType, tr)) {
yield return new ModuleNode(module) { Context = Context };
break;
}
}
}
}
ct.ThrowIfCancellationRequested();
foreach (TypeDef type in TreeTraversal.PreOrder(module.Types, t => t.NestedTypes)) {
ct.ThrowIfCancellationRequested();
foreach (var result in FindReferencesWithinInType(type, tr)) {
ct.ThrowIfCancellationRequested();
yield return result;
}
}
}
}
IEnumerable<IAnalyzerTreeNodeData> FindReferencesWithinInType(TypeDef type, ITypeDefOrRef attrTypeRef) {
bool searchRequired = (type.IsClass && usage.HasFlag(AttributeTargets.Class))
|| (type.IsEnum && usage.HasFlag(AttributeTargets.Enum))
|| (type.IsInterface && usage.HasFlag(AttributeTargets.Interface))
|| (type.IsValueType && usage.HasFlag(AttributeTargets.Struct));
if (searchRequired) {
if (type.HasCustomAttributes) {
foreach (var attribute in type.CustomAttributes) {
if (new SigComparer().Equals(attribute.AttributeType, attrTypeRef)) {
yield return new TypeNode(type) { Context = Context };
break;
}
}
}
}
if ((this.usage & AttributeTargets.GenericParameter) != 0 && type.HasGenericParameters) {
foreach (var parameter in type.GenericParameters) {
if (parameter.HasCustomAttributes) {
foreach (var attribute in parameter.CustomAttributes) {
if (new SigComparer().Equals(attribute.AttributeType, attrTypeRef)) {
yield return new TypeNode(type) { Context = Context };
break;
}
}
}
}
}
if ((this.usage & AttributeTargets.Field) != 0 && type.HasFields) {
foreach (var field in type.Fields) {
if (field.HasCustomAttributes) {
foreach (var attribute in field.CustomAttributes) {
if (new SigComparer().Equals(attribute.AttributeType, attrTypeRef)) {
yield return new FieldNode(field) { Context = Context };
break;
}
}
}
}
}
if (((usage & AttributeTargets.Property) != 0) && type.HasProperties) {
foreach (var property in type.Properties) {
if (property.HasCustomAttributes) {
foreach (var attribute in property.CustomAttributes) {
if (new SigComparer().Equals(attribute.AttributeType, attrTypeRef)) {
yield return new PropertyNode(property) { Context = Context };
break;
}
}
}
}
}
if (((usage & AttributeTargets.Event) != 0) && type.HasEvents) {
foreach (var _event in type.Events) {
if (_event.HasCustomAttributes) {
foreach (var attribute in _event.CustomAttributes) {
if (new SigComparer().Equals(attribute.AttributeType, attrTypeRef)) {
yield return new EventNode(_event) { Context = Context };
break;
}
}
}
}
}
if (type.HasMethods) {
foreach (var method in type.Methods) {
bool found = false;
if ((usage & (AttributeTargets.Method | AttributeTargets.Constructor)) != 0) {
if (method.HasCustomAttributes) {
foreach (var attribute in method.CustomAttributes) {
if (new SigComparer().Equals(attribute.AttributeType, attrTypeRef)) {
found = true;
break;
}
}
}
}
if (!found &&
((usage & AttributeTargets.ReturnValue) != 0) &&
method.Parameters.ReturnParameter.HasParamDef &&
method.Parameters.ReturnParameter.ParamDef.HasCustomAttributes) {
foreach (var attribute in method.Parameters.ReturnParameter.ParamDef.CustomAttributes) {
if (new SigComparer().Equals(attribute.AttributeType, attrTypeRef)) {
found = true;
break;
}
}
}
if (!found &&
((usage & AttributeTargets.Parameter) != 0) &&
method.Parameters.Count > 0) {
foreach (var parameter in method.Parameters.Where(param => param.HasParamDef)) {
if (parameter.IsHiddenThisParameter)
continue;
foreach (var attribute in parameter.ParamDef.CustomAttributes) {
if (new SigComparer().Equals(attribute.AttributeType, attrTypeRef)) {
found = true;
break;
}
}
}
}
if (found) {
MethodDef codeLocation = GetOriginalCodeLocation(method) as MethodDef;
if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) {
yield return new MethodNode(codeLocation) { Context = Context };
}
}
}
}
}
bool HasAlreadyBeenFound(MethodDef method) {
return !foundMethods.TryAdd(method, 0);
}
IEnumerable<Tuple<ModuleDef, ITypeDefOrRef>> GetReferencingModules(ModuleDef mod, CancellationToken ct) {
var asm = mod.Assembly;
if (asm == null) {
yield return new Tuple<ModuleDef, ITypeDefOrRef>(mod, this.analyzedType);
yield break;
}
foreach (var m in asm.Modules.GetSafeEnumerable())
yield return new Tuple<ModuleDef, ITypeDefOrRef>(m, this.analyzedType);
var assemblies = Context.FileManager.GetFiles().Where(a => a.AssemblyDef != null);
foreach (var assembly in assemblies) {
ct.ThrowIfCancellationRequested();
bool found = false;
foreach (var reference in assembly.AssemblyDef.Modules.GetSafeEnumerable().SelectMany(module => module.GetAssemblyRefs())) {
if (AssemblyNameComparer.CompareAll.CompareTo(asm, reference) == 0) {
found = true;
break;
}
}
if (found) {
var typeref = GetScopeTypeRefInAssembly(assembly.AssemblyDef);
if (typeref != null) {
foreach (var m in assembly.AssemblyDef.Modules.GetSafeEnumerable())
yield return new Tuple<ModuleDef, ITypeDefOrRef>(m, typeref);
}
}
}
}
IEnumerable<Tuple<ModuleDef, ITypeDefOrRef>> GetModuleAndAnyFriends(ModuleDef mod, CancellationToken ct) {
var asm = mod.Assembly;
if (asm == null) {
yield return new Tuple<ModuleDef, ITypeDefOrRef>(mod, this.analyzedType);
yield break;
}
foreach (var m in asm.Modules.GetSafeEnumerable())
yield return new Tuple<ModuleDef, ITypeDefOrRef>(m, this.analyzedType);
if (asm.HasCustomAttributes) {
var attributes = asm.CustomAttributes
.Where(attr => attr.TypeFullName == "System.Runtime.CompilerServices.InternalsVisibleToAttribute");
var friendAssemblies = new HashSet<string>();
foreach (var attribute in attributes) {
if (attribute.ConstructorArguments.Count == 0)
continue;
string assemblyName = attribute.ConstructorArguments[0].Value as UTF8String;
if (assemblyName == null)
continue;
assemblyName = assemblyName.Split(',')[0]; // strip off any public key info
friendAssemblies.Add(assemblyName);
}
if (friendAssemblies.Count > 0) {
var assemblies = Context.FileManager.GetFiles().Where(a => a.AssemblyDef != null);
foreach (var assembly in assemblies) {
ct.ThrowIfCancellationRequested();
if (friendAssemblies.Contains(assembly.AssemblyDef.Name)) {
var typeref = GetScopeTypeRefInAssembly(assembly.AssemblyDef);
if (typeref != null) {
foreach (var m in assembly.AssemblyDef.Modules.GetSafeEnumerable())
yield return new Tuple<ModuleDef, ITypeDefOrRef>(m, typeref);
}
}
}
}
}
}
ITypeDefOrRef GetScopeTypeRefInAssembly(AssemblyDef asm) {
foreach (var mod in asm.Modules.GetSafeEnumerable()) {
foreach (var typeref in mod.GetTypeRefs()) {
if (new SigComparer().Equals(analyzedType, typeref))
return typeref;
}
}
return null;
}
}
static class ExtensionMethods {
public static bool HasCustomAttribute(this IMemberRef member, string attributeTypeName) {
return false;
}
}
}

Просмотреть файл

@ -0,0 +1,391 @@
/*
Copyright (C) 2014-2016 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Input;
using dnlib.DotNet;
using dnSpy.Contracts.Controls;
using dnSpy.Contracts.Files.Tabs;
using dnSpy.Contracts.Files.Tabs.TextEditor;
using dnSpy.Contracts.Languages;
using dnSpy.Contracts.Menus;
using dnSpy.Contracts.Plugin;
using dnSpy.Contracts.Search;
using dnSpy.Contracts.ToolWindows.App;
using dnSpy.Contracts.TreeView;
using dnSpy.Shared.Menus;
namespace dnSpy.Analyzer.TreeNodes {
[ExportAutoLoaded]
sealed class AnalyzeCommandLoader : IAutoLoaded {
public static readonly RoutedCommand AnalyzeRoutedCommand = new RoutedCommand("AnalyzeRoutedCommand", typeof(AnalyzeCommandLoader));
readonly IMainToolWindowManager mainToolWindowManager;
readonly IFileTabManager fileTabManager;
readonly Lazy<IAnalyzerManager> analyzerManager;
readonly ILanguageManager languageManager;
[ImportingConstructor]
AnalyzeCommandLoader(IMainToolWindowManager mainToolWindowManager, IWpfCommandManager wpfCommandManager, IFileTabManager fileTabManager, Lazy<IAnalyzerManager> analyzerManager, ILanguageManager languageManager) {
this.mainToolWindowManager = mainToolWindowManager;
this.fileTabManager = fileTabManager;
this.analyzerManager = analyzerManager;
this.languageManager = languageManager;
var cmds = wpfCommandManager.GetCommands(CommandConstants.GUID_TEXTEDITOR_UICONTEXT);
cmds.Add(AnalyzeRoutedCommand, TextEditor_Executed, TextEditor_CanExecute, ModifierKeys.Control, Key.R);
cmds.Add(AnalyzeRoutedCommand, ShowAnalyzerExecuted, ShowAnalyzerCanExecute, ModifierKeys.Control, Key.R);
cmds = wpfCommandManager.GetCommands(CommandConstants.GUID_FILE_TREEVIEW);
cmds.Add(AnalyzeRoutedCommand, FileTreeView_Executed, FileTreeView_CanExecute, ModifierKeys.Control, Key.R);
cmds.Add(AnalyzeRoutedCommand, ShowAnalyzerExecuted, ShowAnalyzerCanExecute, ModifierKeys.Control, Key.R);
cmds = wpfCommandManager.GetCommands(CommandConstants.GUID_ANALYZER_TREEVIEW);
cmds.Add(AnalyzeRoutedCommand, AnalyzerTreeView_Executed, AnalyzerTreeView_CanExecute, ModifierKeys.Control, Key.R);
cmds.Add(AnalyzeRoutedCommand, ShowAnalyzerExecuted, ShowAnalyzerCanExecute, ModifierKeys.Control, Key.R);
cmds = wpfCommandManager.GetCommands(CommandConstants.GUID_SEARCH_LISTBOX);
cmds.Add(AnalyzeRoutedCommand, SearchListBox_Executed, SearchListBox_CanExecute, ModifierKeys.Control, Key.R);
cmds.Add(AnalyzeRoutedCommand, ShowAnalyzerExecuted, ShowAnalyzerCanExecute, ModifierKeys.Control, Key.R);
}
void ShowAnalyzerCanExecute(object sender, CanExecuteRoutedEventArgs e) {
e.CanExecute = mainToolWindowManager.IsShown(AnalyzerToolWindowContent.THE_GUID);
}
void ShowAnalyzerExecuted(object sender, ExecutedRoutedEventArgs e) {
mainToolWindowManager.Show(AnalyzerToolWindowContent.THE_GUID);
}
void TextEditor_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
e.CanExecute = AnalyzeCommand.CanAnalyze(TextEditor_GetMemberRef(), languageManager.Language);
}
void TextEditor_Executed(object sender, ExecutedRoutedEventArgs e) {
AnalyzeCommand.Analyze(mainToolWindowManager, analyzerManager, languageManager.Language, TextEditor_GetMemberRef());
}
IMemberRef TextEditor_GetMemberRef() {
var tab = fileTabManager.ActiveTab;
var uiContext = tab == null ? null : tab.UIContext as ITextEditorUIContext;
if (uiContext == null)
return null;
return uiContext.SelectedReference as IMemberRef;
}
void FileTreeView_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
e.CanExecute = AnalyzeCommand.CanAnalyze(FileTreeView_GetMemberRef(), languageManager.Language);
}
void FileTreeView_Executed(object sender, ExecutedRoutedEventArgs e) {
AnalyzeCommand.Analyze(mainToolWindowManager, analyzerManager, languageManager.Language, FileTreeView_GetMemberRef());
}
IMemberRef FileTreeView_GetMemberRef() {
var nodes = fileTabManager.FileTreeView.TreeView.TopLevelSelection;
var node = nodes.Length == 0 ? null : nodes[0] as IMDTokenNode;
return node == null ? null : node.Reference as IMemberRef;
}
void AnalyzerTreeView_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
e.CanExecute = AnalyzeCommand.CanAnalyze(AnalyzerTreeView_GetMemberRef(), languageManager.Language);
}
void AnalyzerTreeView_Executed(object sender, ExecutedRoutedEventArgs e) {
AnalyzeCommand.Analyze(mainToolWindowManager, analyzerManager, languageManager.Language, AnalyzerTreeView_GetMemberRef());
}
IMemberRef AnalyzerTreeView_GetMemberRef() {
var nodes = analyzerManager.Value.TreeView.TopLevelSelection;
var node = nodes.Length == 0 ? null : nodes[0] as IMDTokenNode;
return node == null ? null : node.Reference as IMemberRef;
}
void SearchListBox_CanExecute(object sender, CanExecuteRoutedEventArgs e) {
e.CanExecute = AnalyzeCommand.CanAnalyze(SearchListBox_GetMemberRef(e.Source as ListBox), languageManager.Language);
}
void SearchListBox_Executed(object sender, ExecutedRoutedEventArgs e) {
AnalyzeCommand.Analyze(mainToolWindowManager, analyzerManager, languageManager.Language, SearchListBox_GetMemberRef(e.Source as ListBox));
}
IMemberRef SearchListBox_GetMemberRef(ListBox listBox) {
var sr = listBox == null ? null : listBox.SelectedItem as ISearchResult;
return sr == null ? null : sr.Reference as IMemberRef;
}
}
static class AnalyzeCommand {
[ExportMenuItem(Header = "res:AnalyzeCommand", Icon = "Search", InputGestureText = "res:ShortCutKeyCtrlR", Group = MenuConstants.GROUP_CTX_FILES_OTHER, Order = 0)]
sealed class FilesCommand : MenuItemBase {
readonly IMainToolWindowManager mainToolWindowManager;
readonly ILanguageManager languageManager;
readonly Lazy<IAnalyzerManager> analyzerManager;
[ImportingConstructor]
FilesCommand(IMainToolWindowManager mainToolWindowManager, ILanguageManager languageManager, Lazy<IAnalyzerManager> analyzerManager) {
this.mainToolWindowManager = mainToolWindowManager;
this.languageManager = languageManager;
this.analyzerManager = analyzerManager;
}
public override bool IsVisible(IMenuItemContext context) {
return GetMemberRefs(context).Any();
}
IEnumerable<IMemberRef> GetMemberRefs(IMenuItemContext context) {
return GetMemberRefs(context, MenuConstants.GUIDOBJ_FILES_TREEVIEW_GUID, false, languageManager);
}
internal static IEnumerable<IMemberRef> GetMemberRefs(IMenuItemContext context, string guid, bool checkRoot, ILanguageManager languageManager) {
if (context.CreatorObject.Guid != new Guid(guid))
yield break;
var nodes = context.Find<ITreeNodeData[]>();
if (nodes == null)
yield break;
if (checkRoot && nodes.All(a => a.TreeNode.Parent != null && a.TreeNode.Parent.Parent == null))
yield break;
foreach (var node in nodes) {
var mr = node as IMDTokenNode;
if (mr != null && CanAnalyze(mr.Reference as IMemberRef, languageManager.Language))
yield return mr.Reference as IMemberRef;
}
}
public override void Execute(IMenuItemContext context) {
Analyze(mainToolWindowManager, analyzerManager, languageManager.Language, GetMemberRefs(context));
}
}
[ExportMenuItem(Header = "res:AnalyzeCommand", Icon = "Search", InputGestureText = "res:ShortCutKeyCtrlR", Group = MenuConstants.GROUP_CTX_ANALYZER_OTHER, Order = 0)]
sealed class AnalyzerCommand : MenuItemBase {
readonly IMainToolWindowManager mainToolWindowManager;
readonly ILanguageManager languageManager;
readonly Lazy<IAnalyzerManager> analyzerManager;
[ImportingConstructor]
AnalyzerCommand(IMainToolWindowManager mainToolWindowManager, ILanguageManager languageManager, Lazy<IAnalyzerManager> analyzerManager) {
this.mainToolWindowManager = mainToolWindowManager;
this.languageManager = languageManager;
this.analyzerManager = analyzerManager;
}
public override bool IsVisible(IMenuItemContext context) {
return GetMemberRefs(context).Any();
}
IEnumerable<IMemberRef> GetMemberRefs(IMenuItemContext context) {
return FilesCommand.GetMemberRefs(context, MenuConstants.GUIDOBJ_ANALYZER_TREEVIEW_GUID, true, languageManager);
}
public override void Execute(IMenuItemContext context) {
Analyze(mainToolWindowManager, analyzerManager, languageManager.Language, GetMemberRefs(context));
}
}
[ExportMenuItem(Header = "res:AnalyzeCommand", Icon = "Search", InputGestureText = "res:ShortCutKeyCtrlR", Group = MenuConstants.GROUP_CTX_CODE_OTHER, Order = 0)]
sealed class CodeCommand : MenuItemBase {
readonly IMainToolWindowManager mainToolWindowManager;
readonly ILanguageManager languageManager;
readonly Lazy<IAnalyzerManager> analyzerManager;
[ImportingConstructor]
CodeCommand(IMainToolWindowManager mainToolWindowManager, ILanguageManager languageManager, Lazy<IAnalyzerManager> analyzerManager) {
this.mainToolWindowManager = mainToolWindowManager;
this.languageManager = languageManager;
this.analyzerManager = analyzerManager;
}
public override bool IsVisible(IMenuItemContext context) {
return GetMemberRefs(context).Any();
}
static IEnumerable<IMemberRef> GetMemberRefs(IMenuItemContext context) {
return GetMemberRefs(context, MenuConstants.GUIDOBJ_TEXTEDITORCONTROL_GUID);
}
internal static IEnumerable<IMemberRef> GetMemberRefs(IMenuItemContext context, string guid) {
if (context.CreatorObject.Guid != new Guid(guid))
yield break;
var @ref = context.Find<CodeReference>();
if (@ref != null) {
var mr = @ref.Reference as IMemberRef;
if (mr != null)
yield return mr;
}
}
public override void Execute(IMenuItemContext context) {
Analyze(mainToolWindowManager, analyzerManager, languageManager.Language, GetMemberRefs(context));
}
}
[ExportMenuItem(Header = "res:AnalyzeCommand", Icon = "Search", InputGestureText = "res:ShortCutKeyCtrlR", Group = MenuConstants.GROUP_CTX_SEARCH_OTHER, Order = 0)]
sealed class SearchCommand : MenuItemBase {
readonly IMainToolWindowManager mainToolWindowManager;
readonly ILanguageManager languageManager;
readonly Lazy<IAnalyzerManager> analyzerManager;
[ImportingConstructor]
SearchCommand(IMainToolWindowManager mainToolWindowManager, ILanguageManager languageManager, Lazy<IAnalyzerManager> analyzerManager) {
this.mainToolWindowManager = mainToolWindowManager;
this.languageManager = languageManager;
this.analyzerManager = analyzerManager;
}
static IEnumerable<IMemberRef> GetMemberRefs(IMenuItemContext context) {
return CodeCommand.GetMemberRefs(context, MenuConstants.GUIDOBJ_SEARCH_GUID);
}
public override bool IsVisible(IMenuItemContext context) {
return GetMemberRefs(context).Any();
}
public override void Execute(IMenuItemContext context) {
Analyze(mainToolWindowManager, analyzerManager, languageManager.Language, GetMemberRefs(context));
}
}
public static bool CanAnalyze(IMemberRef member, ILanguage language) {
member = ResolveReference(member);
return member is TypeDef ||
member is FieldDef ||
member is MethodDef ||
PropertyNode.CanShow(member, language) ||
EventNode.CanShow(member, language);
}
static void Analyze(IMainToolWindowManager mainToolWindowManager, Lazy<IAnalyzerManager> analyzerManager, ILanguage language, IEnumerable<IMemberRef> mrs) {
foreach (var mr in mrs)
Analyze(mainToolWindowManager, analyzerManager, language, mr);
}
public static void Analyze(IMainToolWindowManager mainToolWindowManager, Lazy<IAnalyzerManager> analyzerManager, ILanguage language, IMemberRef member) {
var memberDef = ResolveReference(member);
var type = memberDef as TypeDef;
if (type != null) {
mainToolWindowManager.Show(AnalyzerToolWindowContent.THE_GUID);
analyzerManager.Value.Add(new TypeNode(type));
}
var field = memberDef as FieldDef;
if (field != null) {
mainToolWindowManager.Show(AnalyzerToolWindowContent.THE_GUID);
analyzerManager.Value.Add(new FieldNode(field));
}
var method = memberDef as MethodDef;
if (method != null) {
mainToolWindowManager.Show(AnalyzerToolWindowContent.THE_GUID);
analyzerManager.Value.Add(new MethodNode(method));
}
var propertyAnalyzer = PropertyNode.TryCreateAnalyzer(member, language);
if (propertyAnalyzer != null) {
mainToolWindowManager.Show(AnalyzerToolWindowContent.THE_GUID);
analyzerManager.Value.Add(propertyAnalyzer);
}
var eventAnalyzer = EventNode.TryCreateAnalyzer(member, language);
if (eventAnalyzer != null) {
mainToolWindowManager.Show(AnalyzerToolWindowContent.THE_GUID);
analyzerManager.Value.Add(eventAnalyzer);
}
}
static IMemberDef ResolveReference(object reference) {
if (reference is ITypeDefOrRef)
return ((ITypeDefOrRef)reference).ResolveTypeDef();
else if (reference is IMethod && ((IMethod)reference).MethodSig != null)
return ((IMethod)reference).ResolveMethodDef();
else if (reference is IField)
return ((IField)reference).ResolveFieldDef();
else if (reference is PropertyDef)
return (PropertyDef)reference;
else if (reference is EventDef)
return (EventDef)reference;
return null;
}
}
[ExportAutoLoaded]
sealed class RemoveAnalyzeCommand : IAutoLoaded {
readonly Lazy<IAnalyzerManager> analyzerManager;
[ImportingConstructor]
RemoveAnalyzeCommand(IWpfCommandManager wpfCommandManager, Lazy<IAnalyzerManager> analyzerManager) {
this.analyzerManager = analyzerManager;
var cmds = wpfCommandManager.GetCommands(CommandConstants.GUID_ANALYZER_TREEVIEW);
cmds.Add(ApplicationCommands.Delete, (s, e) => DeleteNodes(), (s, e) => e.CanExecute = CanDeleteNodes, ModifierKeys.None, Key.Delete);
}
bool CanDeleteNodes {
get { return GetNodes() != null; }
}
void DeleteNodes() {
DeleteNodes(GetNodes());
}
ITreeNodeData[] GetNodes() {
return GetNodes(analyzerManager.Value.TreeView.TopLevelSelection);
}
internal static ITreeNodeData[] GetNodes(ITreeNodeData[] nodes) {
if (nodes == null)
return null;
if (nodes.Length == 0 || !nodes.All(a => a.TreeNode.Parent != null && a.TreeNode.Parent.Parent == null))
return null;
return nodes;
}
internal static void DeleteNodes(ITreeNodeData[] nodes) {
if (nodes != null) {
foreach (var node in nodes) {
AnalyzerTreeNodeData.CancelSelfAndChildren(node);
node.TreeNode.Parent.Children.Remove(node.TreeNode);
}
}
}
}
[ExportMenuItem(Header = "res:RemoveCommand", Icon = "Delete", InputGestureText = "res:ShortCutKeyDelete", Group = MenuConstants.GROUP_CTX_ANALYZER_OTHER, Order = 10)]
sealed class RemoveAnalyzeCtxMenuCommand : MenuItemBase {
public override bool IsVisible(IMenuItemContext context) {
return GetNodes(context) != null;
}
static ITreeNodeData[] GetNodes(IMenuItemContext context) {
if (context.CreatorObject.Guid != new Guid(MenuConstants.GUIDOBJ_ANALYZER_TREEVIEW_GUID))
return null;
return RemoveAnalyzeCommand.GetNodes(context.Find<ITreeNodeData[]>());
}
public override void Execute(IMenuItemContext context) {
RemoveAnalyzeCommand.DeleteNodes(GetNodes(context));
}
}
}

Просмотреть файл

@ -0,0 +1,53 @@
// Copyright (c) 2011 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 dnlib.DotNet;
using dnSpy.Contracts.Files;
using dnSpy.Contracts.TreeView;
namespace dnSpy.Analyzer.TreeNodes {
abstract class EntityNode : AnalyzerTreeNodeData, IMDTokenNode {
public abstract IMemberRef Member { get; }
public abstract IMDTokenProvider Reference { get; }
public SourceRef? SourceRef { get; set; }
public override bool Activate() {
Context.AnalyzerManager.OnActivated(this);
return true;
}
public override bool HandleAssemblyListChanged(IDnSpyFile[] removedAssemblies, IDnSpyFile[] addedAssemblies) {
foreach (IDnSpyFile asm in removedAssemblies) {
if (this.Member.Module == asm.ModuleDef)
return false; // remove this node
}
HandleAssemblyListChanged(this.TreeNode, removedAssemblies, addedAssemblies);
return true;
}
public override bool HandleModelUpdated(IDnSpyFile[] files) {
if (this.Member.Module == null)
return false; // remove this node
if ((this.Member is IField || this.Member is IMethod || this.Member is PropertyDef || this.Member is EventDef) &&
this.Member.DeclaringType == null)
return false;
HandleModelUpdated(this.TreeNode, files);
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,40 @@
// Copyright (c) 2011 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 dnlib.DotNet;
using dnSpy.Contracts.Highlighting;
using dnSpy.Contracts.Languages;
using dnSpy.Decompiler.Shared;
namespace dnSpy.Analyzer.TreeNodes {
sealed class EventAccessorNode : MethodNode {
readonly string name;
public EventAccessorNode(MethodDef analyzedMethod, string name)
: base(analyzedMethod) {
this.name = name;
}
protected override void Write(ISyntaxHighlightOutput output, ILanguage language) {
if (name != null)
output.Write(name, TextTokenKind.Keyword);
else
base.Write(output, language);
}
}
}

Просмотреть файл

@ -0,0 +1,130 @@
// Copyright (c) 2011 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.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using dnSpy.Analyzer.Properties;
using dnSpy.Contracts.Highlighting;
using dnSpy.Contracts.Languages;
using dnSpy.Decompiler.Shared;
namespace dnSpy.Analyzer.TreeNodes {
sealed class EventFiredByNode : SearchNode {
readonly EventDef analyzedEvent;
readonly FieldDef eventBackingField;
readonly MethodDef eventFiringMethod;
ConcurrentDictionary<MethodDef, int> foundMethods;
public EventFiredByNode(EventDef analyzedEvent) {
if (analyzedEvent == null)
throw new ArgumentNullException("analyzedEvent");
this.analyzedEvent = analyzedEvent;
this.eventBackingField = GetBackingField(analyzedEvent);
var eventType = analyzedEvent.EventType.ResolveTypeDef();
if (eventType != null)
this.eventFiringMethod = eventType.Methods.First(md => md.Name == "Invoke");
}
protected override void Write(ISyntaxHighlightOutput output, ILanguage language) {
output.Write(dnSpy_Analyzer_Resources.RaisedByTreeNode, TextTokenKind.Text);
}
protected override IEnumerable<IAnalyzerTreeNodeData> FetchChildren(CancellationToken ct) {
foundMethods = new ConcurrentDictionary<MethodDef, int>();
foreach (var child in FindReferencesInType(analyzedEvent.DeclaringType)) {
yield return child;
}
foundMethods = null;
}
IEnumerable<IAnalyzerTreeNodeData> FindReferencesInType(TypeDef type) {
// HACK: in lieu of proper flow analysis, I'm going to use a simple heuristic
// If the method accesses the event's backing field, and calls invoke on a delegate
// with the same signature, then it is (most likely) raise the given event.
foreach (MethodDef method in type.Methods) {
bool readBackingField = false;
if (!method.HasBody)
continue;
Instruction foundInstr = null;
foreach (Instruction instr in method.Body.Instructions) {
Code code = instr.OpCode.Code;
if (code == Code.Ldfld || code == Code.Ldflda) {
IField fr = instr.Operand as IField;
if (fr.ResolveFieldDef() == eventBackingField) {
readBackingField = true;
}
}
if (readBackingField && (code == Code.Callvirt || code == Code.Call)) {
IMethod mr = instr.Operand as IMethod;
if (mr != null && eventFiringMethod != null && mr.Name == eventFiringMethod.Name && mr.ResolveMethodDef() == eventFiringMethod) {
foundInstr = instr;
break;
}
}
}
if (foundInstr != null) {
MethodDef codeLocation = GetOriginalCodeLocation(method) as MethodDef;
if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) {
var node = new MethodNode(codeLocation) { Context = Context };
if (codeLocation == method)
node.SourceRef = new SourceRef(method, foundInstr.Offset, foundInstr.Operand as IMDTokenProvider);
yield return node;
}
}
}
}
bool HasAlreadyBeenFound(MethodDef method) {
return !foundMethods.TryAdd(method, 0);
}
// HACK: we should probably examine add/remove methods to determine this
static FieldDef GetBackingField(EventDef ev) {
var fieldName = ev.Name;
var vbStyleFieldName = fieldName + "Event";
var fieldType = ev.EventType;
if (fieldType == null)
return null;
foreach (var fd in ev.DeclaringType.Fields) {
if (fd.Name == fieldName || fd.Name == vbStyleFieldName)
if (new SigComparer().Equals(fd.FieldType, fieldType))
return fd;
}
return null;
}
public static bool CanShow(EventDef ev) {
return GetBackingField(ev) != null;
}
}
}

Просмотреть файл

@ -0,0 +1,107 @@
// Copyright (c) 2011 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 dnlib.DotNet;
using dnSpy.Analyzer.Properties;
using dnSpy.Contracts.Highlighting;
using dnSpy.Contracts.Images;
using dnSpy.Contracts.Languages;
using dnSpy.Contracts.TreeView;
using dnSpy.Decompiler.Shared;
using dnSpy.Shared.Files.TreeView;
using dnSpy.Shared.Highlighting;
namespace dnSpy.Analyzer.TreeNodes {
sealed class EventNode : EntityNode {
readonly EventDef analyzedEvent;
readonly bool hidesParent;
public EventNode(EventDef analyzedEvent, bool hidesParent = false) {
if (analyzedEvent == null)
throw new ArgumentNullException("analyzedEvent");
this.analyzedEvent = analyzedEvent;
this.hidesParent = hidesParent;
}
public override void Initialize() {
this.TreeNode.LazyLoading = true;
}
public override IMemberRef Member {
get { return analyzedEvent; }
}
public override IMDTokenProvider Reference {
get { return analyzedEvent; }
}
protected override ImageReference GetIcon(IDotNetImageManager dnImgMgr) {
return dnImgMgr.GetImageReference(analyzedEvent);
}
protected override void Write(ISyntaxHighlightOutput output, ILanguage language) {
if (hidesParent) {
output.Write("(", TextTokenKind.Operator);
output.Write(dnSpy_Analyzer_Resources.HidesParent, TextTokenKind.Text);
output.Write(")", TextTokenKind.Operator);
output.WriteSpace();
}
language.WriteType(output, analyzedEvent.DeclaringType, true);
output.Write(".", TextTokenKind.Operator);
new NodePrinter().Write(output, language, analyzedEvent, Context.ShowToken);
}
public override IEnumerable<ITreeNodeData> CreateChildren() {
if (analyzedEvent.AddMethod != null)
yield return new EventAccessorNode(analyzedEvent.AddMethod, dnSpy_Analyzer_Resources.EventAdderTreeNodeName);
if (analyzedEvent.RemoveMethod != null)
yield return new EventAccessorNode(analyzedEvent.RemoveMethod, dnSpy_Analyzer_Resources.EventRemoverTreeNodeName);
foreach (var accessor in analyzedEvent.OtherMethods)
yield return new EventAccessorNode(accessor, null);
if (EventFiredByNode.CanShow(analyzedEvent))
yield return new EventFiredByNode(analyzedEvent);
if (EventOverridesNode.CanShow(analyzedEvent))
yield return new EventOverridesNode(analyzedEvent);
if (InterfaceEventImplementedByNode.CanShow(analyzedEvent))
yield return new InterfaceEventImplementedByNode(analyzedEvent);
}
public static IAnalyzerTreeNodeData TryCreateAnalyzer(IMemberRef member, ILanguage language) {
if (CanShow(member, language))
return new EventNode(member as EventDef);
else
return null;
}
public static bool CanShow(IMemberRef member, ILanguage language) {
var eventDef = member as EventDef;
if (eventDef == null)
return false;
return !language.ShowMember(eventDef.AddMethod ?? eventDef.RemoveMethod)
|| EventOverridesNode.CanShow(eventDef);
}
}
}

Просмотреть файл

@ -0,0 +1,68 @@
// Copyright (c) 2011 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.Threading;
using dnlib.DotNet;
using dnSpy.Analyzer.Properties;
using dnSpy.Contracts.Highlighting;
using dnSpy.Contracts.Languages;
using dnSpy.Decompiler.Shared;
namespace dnSpy.Analyzer.TreeNodes {
sealed class EventOverridesNode : SearchNode {
readonly EventDef analyzedEvent;
public EventOverridesNode(EventDef analyzedEvent) {
if (analyzedEvent == null)
throw new ArgumentNullException("analyzedEvent");
this.analyzedEvent = analyzedEvent;
}
protected override void Write(ISyntaxHighlightOutput output, ILanguage language) {
output.Write(dnSpy_Analyzer_Resources.OverriddenByTreeNode, TextTokenKind.Text);
}
protected override IEnumerable<IAnalyzerTreeNodeData> FetchChildren(CancellationToken ct) {
var analyzer = new ScopedWhereUsedAnalyzer<IAnalyzerTreeNodeData>(Context.FileManager, analyzedEvent, FindReferencesInType);
return analyzer.PerformAnalysis(ct);
}
IEnumerable<IAnalyzerTreeNodeData> FindReferencesInType(TypeDef type) {
if (!TypesHierarchyHelpers.IsBaseType(analyzedEvent.DeclaringType, type, resolveTypeArguments: false))
yield break;
foreach (EventDef eventDef in type.Events) {
if (TypesHierarchyHelpers.IsBaseEvent(analyzedEvent, eventDef)) {
MethodDef anyAccessor = eventDef.AddMethod ?? eventDef.RemoveMethod;
if (anyAccessor == null)
continue;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;
yield return new EventNode(eventDef, hidesParent) { Context = Context };
}
}
}
public static bool CanShow(EventDef property) {
var accessor = property.AddMethod ?? property.RemoveMethod;
return accessor != null && accessor.IsVirtual && !accessor.IsFinal && !accessor.DeclaringType.IsInterface;
}
}
}

Просмотреть файл

@ -0,0 +1,118 @@
// Copyright (c) 2011 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;
using System.Collections.Generic;
using System.Threading;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using dnSpy.Analyzer.Properties;
using dnSpy.Contracts.Highlighting;
using dnSpy.Contracts.Languages;
using dnSpy.Decompiler.Shared;
namespace dnSpy.Analyzer.TreeNodes {
sealed class FieldAccessNode : SearchNode {
readonly bool showWrites; // true: show writes; false: show read access
readonly FieldDef analyzedField;
Lazy<Hashtable> foundMethods;
readonly object hashLock = new object();
public FieldAccessNode(FieldDef analyzedField, bool showWrites) {
if (analyzedField == null)
throw new ArgumentNullException("analyzedField");
this.analyzedField = analyzedField;
this.showWrites = showWrites;
}
protected override void Write(ISyntaxHighlightOutput output, ILanguage language) {
output.Write(showWrites ? dnSpy_Analyzer_Resources.AssignedByTreeNode : dnSpy_Analyzer_Resources.ReadByTreeNode, TextTokenKind.Text);
}
protected override IEnumerable<IAnalyzerTreeNodeData> FetchChildren(CancellationToken ct) {
foundMethods = new Lazy<Hashtable>(LazyThreadSafetyMode.ExecutionAndPublication);
var analyzer = new ScopedWhereUsedAnalyzer<IAnalyzerTreeNodeData>(Context.FileManager, analyzedField, FindReferencesInType);
foreach (var child in analyzer.PerformAnalysis(ct)) {
yield return child;
}
foundMethods = null;
}
IEnumerable<IAnalyzerTreeNodeData> FindReferencesInType(TypeDef type) {
foreach (MethodDef method in type.Methods) {
if (!method.HasBody)
continue;
Instruction foundInstr = null;
foreach (Instruction instr in method.Body.Instructions) {
if (CanBeReference(instr.OpCode.Code)) {
IField fr = instr.Operand as IField;
if (fr.ResolveFieldDef() == analyzedField &&
Helpers.IsReferencedBy(analyzedField.DeclaringType, fr.DeclaringType)) {
foundInstr = instr;
break;
}
}
}
if (foundInstr != null) {
MethodDef codeLocation = GetOriginalCodeLocation(method) as MethodDef;
if (codeLocation != null && !HasAlreadyBeenFound(codeLocation)) {
var node = new MethodNode(codeLocation) { Context = Context };
if (codeLocation == method)
node.SourceRef = new SourceRef(method, foundInstr.Offset, foundInstr.Operand as IMDTokenProvider);
yield return node;
}
}
}
}
bool CanBeReference(Code code) {
switch (code) {
case Code.Ldfld:
case Code.Ldsfld:
return !showWrites;
case Code.Stfld:
case Code.Stsfld:
return showWrites;
case Code.Ldflda:
case Code.Ldsflda:
case Code.Ldtoken:
return true; // always show address-loading
default:
return false;
}
}
bool HasAlreadyBeenFound(MethodDef method) {
Hashtable hashtable = foundMethods.Value;
lock (hashLock) {
if (hashtable.Contains(method)) {
return true;
}
else {
hashtable.Add(method, null);
return false;
}
}
}
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше