When I right-click a symbol and run the Find Usages ReSharper command, ReSharper will often seem to spend most of its time searching resx files. The majority of the time during which the progress dialog is visible, the file names shown in that dialog are various .resx files in the solution.
Is ReSharper actually searching .resx files? Why would it do this, and why would it take so long? Can I alter this behavior?
Setup: ReSharper 8.2.0.2160 C# Edition. Visual Studio 2013 Premium.
What I've tried:
Adding resx as a mask to the Code Inspection Items To Skip R# preference, but that doesn't make a difference
Find Usages Advanced, uncheck the Textual Occurrences option. Doesn't make a difference
The answer to this is all due to ReSharper's underlying architecture. When processing files, ReSharper will build an abstract syntax tree, and each node in the tree can have one or more references to an element in the semantic model. In other words, the Foo in the expression new Foo(42) will have a reference to the semantic element describing the class called Foo. Each file will have lots of references, as any usage of an element (variable, parameter, method, property, CSS class, HTML colour, file system path, and more) has one or more references to the declaration of that element.
These references are very powerful. They enable Ctrl+Click navigation, by simply navigating to the target(s) of the reference. They can provide code completion by displaying the candidate targets that would satisfy a reference at the current location in code.
And of course, they also power Find Usages, by finding all references that target a particular element. But this requires working backwards, from the target to the reference. The brute force approach would require checking the target of every reference in every file, trying to find the target. This clearly wouldn't scale, and the data set is too big to cache.
To make Find Usages run in a sane timescale, ReSharper also maintains a word index, of all words used in all files (this also helps with normal Go To navigation). When you invoke Find Usages on a symbol (such as EnterDate in the screenshot in the question), ReSharper uses the word index to narrow down the files it needs to search - it would look up EnterDate, and only use those files that include the word. Once it has a reduced subset of files to search, it needs to find any references that target the original element. To do this, it walks the syntax tree of each file in the subset. Each node is checked for references that match the name of the symbol we're looking for, e.g. EnterDate. If it matches, the reference is resolved, and the target is checked to see if it matches the same element - the EnterDate class, or property or whatever it actually was. If it does point to the expected target, it is added to the collection of usages, and gets displayed to the user.
(Things are slightly more complex than this, in that a reference might have multiple names, e.g. if you try and find usages on [Pure], ReSharper needs to find any usages of both Pure or PureAttribute. Fortunately, these alternative names are also stored in the word index, and used to help reduce the files to be searched. When checking the references, all of the alternative names are checked)
So, if you have a .resx file that contains the text EnterDate, it will be searched for a reference to the EnterDate element you're looking for - ReSharper will walk the syntax tree of the .resx file, and check each reference to see if it matches EnterDate.
We check all files, even if it seems obvious to the user that the target element can't possibly be used in that file, because we allow references to be cross language. That is, a VB file can reference a C# element, or a HTML file can reference a CSS element, or an XAML file reference a C# method element, and so on. So there is no filtering on "sensible" usage. For example, if EnterDate is a class, you as a user can tell that it's not likely to be in a .resx file, but ReSharper has no way of knowing that. After all, it's perfectly fine to use a class name in the type attribute of a web.config file, or as a parameter to typeof in a VB file. Or a plugin could add a reference provider that allows for usages of typenames in .resx files. So, we keep things simple and search all candidate references, even though it might look odd in the progress dialog.
Related
In SublimeText3 binary_file_patterns excludes files from being found in Files or fuzzy search (Goto Anything) while index_exclude_patterns prevents files from being indexed.
Since we know that not indexed files cannot be found and assuming that untraceable files do not need to be indexed, what are the differences and implications by the usage of one over another?
Sublime maintains a catalog of all known files based on the folders that are currently open in the window/project, and that catalog of files is used to populate the Goto Anything file list and also the list of files that are searched when you do Find in Files.
You can control what appears in the catalog by using the file_exclude_patterns and folder_exclude_patterns settings to stop files from appearing in the sidebar (and thus in the catalog). As you mentioned you can also use binary_file_patterns to indicate that files should still appear in the side bar, but should not be offered in the Goto Anything panel or searched by Find in Files.
In addition to the above, as long as index_files is turned on, then in addition to the file catalog Sublime also runs an indexing process against the files in the side bar as well.
The indexer runs in the background using some number of threads (controlled by index_workers) and essentially loads every file in the side bar, applies the appropriate syntax definition, and then gathers the list of symbols that are marked as ones that should appear in the index (this is a per-syntax setting). The index_exclude_patterns setting specifies files which should not be indexed, even if they appear in the sidebar.
The index is used to power the Goto Definition/Goto Reference/Goto Symbol in Project functionality; it's literally just a list of all of the indexed symbols, what files they appear in, and where in that file that they appear.
Your assumption that files that are not indexed are ones that can't be found is not correct; files that are not indexed can still appear in the side bar and be found by Goto Anything, they just don't contribute symbols to the index, which means the above functionality will not show any content from those files, but you can still open and search them.
So overall, the implications of the two are:
If you want a file to appear in the side bar but you don't want to search inside it or have it eligible for opening with Goto Anything, add it to the binary_file_patterns.
If you want a file to appear in the side bar but not contribute symbols to the index, then add it to the index_exclude_patterns setting.
Files can appear in both settings, in which case you can see them in the side bar but Sublime pretends that they're not there for purposes of all of the above functionality.
Right now I do ⌘t then scroll through autocomplete, or start typing the name (but half the time it doesn't find it).
Sublime doesn't find a file in many cases. For example, I typically have all my files called index.<ext> nested inside some folder. So I might have:
my/long/directory/structure/index.js
my/long/directory/structure2/index.js
my/long/directory/structure3/index.js
my/long/directory/structure.../index.js
my/long/directory/structuren/index.js
my/long/directory/index.js
my/long/directory2/index.js
my/long/directory.../index.js
my/long/directoryn/index.js
my/long/index.js
my/index.js
...
But in sublime you have to search for an exact path. I can't search this:
my directory index
And get results for directory, directory2, directory..., directoryn, I just get empty results because there is not my/directory. I can't remember the full folder path most of the time, so it takes a lot of effort to do so and I end up just navigating in the sidebar to find the file which takes some time.
Wondering if there is a better/faster way of doing this. Basically searching for a file by snippets/keywords of the complete path. So m dir would return my/long/directory, etc.
The first thing to note is that you do not have to search for an exact path; anywhere that Sublime provides you a list of items to select from and a text entry, fuzzy matching is in play. In your example searching just for idx will narrow down the list to all items that have those characters in that order, even if they're not adjacent to each other.
The entries show you visually how they're matching up, and there's a fairly sophisticated system behind the scenes that decides which characters make the best matches (relative to some hidden scoring algorithm):
In addition to this you can use multiple space separated terms to filter down the list. Each term is applied to the list of items resulting from the prior term, so they don't need to be provided in the same order as they appear in the file names.
This helps with searches where you know generally the name of the file, and from there can further drill down on segments of the path or other terms that will help narrow things down:
Something to note here is that as seen in these images, the folder structure is my/long/directory/structure, but the names of the files as seen in the panel don't include the my/ at the start.
In cases where your project contains only one top level folder, that folder isn't presented in the names of the files. Presumably this is because it's common to every file and thus not going to be a useful filter. As such trying to use my in the search field will return no matches unless one of the files has an m and a y somewhere in their filenames.
This isn't the case if there are multiple top level folders; in that case Sublime will include the root folder in the names of the files presented because now it's required to be able to distinguish between files in the different folders:
In addition to this, note that for any given filter text you enter in a panel, Sublime remembers the full text of the item that you selected while that filter text was being used, and uses that in it's scoring to prioritize the matches the next time you search in the same panel. The next time you search with the same term, Sublime will automatically pre-select the item that you picked last time under the theory that you probably want it again.
The search terms and their matches are saved in the session file and in your project's sublime-workspace files, so as you move from window to window and project to project you're essentially training Sublime how to find the files that you want.
My advice would be to try and flip your thinking a little bit. In my opinion the power of the fuzzy matching algorithm works best when you try to find files in a more organic way than trying to replicate the path entirely.
Instead, I would throw a few characters from the name of the file that I'm trying to find first, and then add another term that filters on some part of the path that will disambiguate things more; a term of idx s1 in this example immediately finds the two index.js files that are contained in structure1 folders, for example.
In a more real world example the names of the folders might contain the names of the components that they're a part of or something else that is providing a logical structure to the code, so you might do idx con to pull the index.js from the controller folder or idx mod to find the one in the model folder, and so on.
Regarding a better/faster way to do this I don't think there is one, at least in the general case. Sublime inherently knows every file that's in your project as a part of indexing all of the files to power other features such as Goto Symbol and it uses file watchers to detect changes to the structure of the open folders.
Anything else, including a third party plugin or package, would need to first do a redundant file scan to accumulate the list of files and would also have to replicate the file watching that Sublime is already doing in order to know when things change.
Within my company we have an XML-based notation. Among other features, it is possible to define references from one XML document into another. I would like to enable autocompletion in Sublime so that whenever I am adding a reference, the possible files (i.e. XML files within the same project) and link points (i.e. symbols within that file) get offered as recommendations.
So far, I have found a lot of plugins that enable autocomplete for, say, HTML, PHP or LaTeX. However, I have the feeling the code base is too complex for a somewhat simple task. Is there, for instance, some vanilla function that generates completions based on an arbitrary array received as parameter? I would create the logic to determine what is a symbol and derive said array, but the whole process seems somewhat cumbersome to me.
(As a note: I can program in Python and have fiddled with other Sublime features, such as snippets, but these packages seem to be much more complex than it feels necessary.)
The base to create the completions entry is not to complicated. You now need to fill the array with the correct values (this could be done via a project setting or parsing other files).
import sublime
import sublime_plugin
# Your array, which contains the completions
arr = ["foo", "bar", "baz"]
class MyCompletionsListener(sublime_plugin.EventListener):
def on_query_completions(self, view, prefix, locations):
loc = locations[0]
# limit you completions scope
if not view.score_selector(loc, "text"):
return
completions = [(v + "\tYour Description", v) for v in arr]
return completions
OP's note: The answer works as advertised. However, the integration is so seamless that I thought for a while that something was missing. If the Python script above is on the right folder, all of the completions returned by the completions array will be suggested (depending on Sublime settings, it might be necessary to trigger the completions menu with Ctrl+Space). Also worth noting:
The completions may be None, in which case they just don't add any completion option, or an array of 2-tuples, where the first element is the description (which will be shown in the drop-down menu and trigger the completion) and the second is the value (i.e. the text that will be input if the completion is selected).
The score_selector method can be used to determine if the cursor position is within a given scope.
When I type alt-f7 against a class property in c# (in a web project), ReSharper scans through all files including javascript, html, and razor web views (.cshtml). Is it possible to tell ReSharper only to search against c# files?
This doesn't appear to be possible. If you use the advanced Find Usages tool, you will see that ReSharper's only available scoping options are solution, libraries, solution and libraries, current project and current file. It would be awesome if they included a file type (.cs, .cshtml, etc.), object type (class, struct, enum, etc.) or similar scoping options.
ReSharper looks in file types that might not be obviously linked because it supports references between arbitrary file types. For example, xml config files can contain a reference to a C# type defined in the project, cshtml files will refer to other C# code, CSS classes can be used in C#. Find usages needs to collect all of these.
However, ReSharper is still being smart about what it scans. When you do a find usages, ReSharper looks the identifier up in a word index to get the list of files where it's being used. It then only looks at these files, rather than scanning all files in the solution.
I'm trying to localize a large MFC project where all the strings are hard-coded into the source code. (It was the easiest thing to do at the time, back before we had any idea we'd expand into other markets.) I've looked at localization tools, and invariably they say to put all the strings into the .rc file first, or just assume it has been done. Of the ones I've checked, appTranslator is the only one that even hints it may be a problem, and provides a couple of convenience functions to cut down on the wordiness of the resulting source code.
Does anybody have a better idea than going through hundreds of files manually, and making the occasional mistake along the way?
Is there some sort of product out there to help?
Does anybody have experience with doing this?
It is a tedious process to be sure. I participated in an effort like this many years ago. We did it manually. You can probably write some common code that makes the loading, checking, etc all pretty clean with minimal bloat.
I don't know of any products that will do it for you.
CStrings might be your friend - using the LoadString() member.
I would either derive from CString or write some other code that encapsulates default values (their current hard-coded values probably) and other error conditions and then use that in place of the hard-coded strings.
If you prefer not to use CString, then deriving from std::string and using the global LoadString() works fine too.
as for tools:
not sure they will work for your case:
http://www.modelmakertools.com/articles/hard-coded-strings.html
apparently this tool can find all the strings in your exe files:
http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
Then you can search for them and replace.
I think writing a tool would be fairly straightforward - look for " character and then create an entry in an rc file that corresponds to the .cpp or .h file it came from. You will have a lot of culling to do, but it is a start. You can do a replace of the text, or insert comments, etc. You can use the line number and file name for the resource id/name in a #include.
I know it's too late but just for the search engine.
There is a feature of CString to initialize it from a resource ID.
CString((LPCTSTR)IDS_RESOURCE_ID)