Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't trigger rename of code element if filename has not been changed. #920

Merged
merged 2 commits into from Jan 6, 2017

Conversation

jinujoseph
Copy link
Contributor

@jinujoseph jinujoseph commented Dec 12, 2016

fixes #363 , fixes #1063
@davkean @srivatsn @dotnet/project-system

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a test for this?

@@ -68,6 +68,11 @@ public Task HintingAsync(IProjectChangeHint hint)

private void ScheduleRename(string oldFilePath, string newFilePath)
{
if (Equals(Path.GetFileName(oldFilePath),Path.GetFileName(newFilePath)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatting nit: spacing between arguments.

@jinujoseph
Copy link
Contributor Author

will add tests

@jinujoseph jinujoseph force-pushed the RenameFix branch 2 times, most recently from 016845b to 2ff9551 Compare December 12, 2016 23:33
@@ -23,7 +23,7 @@ public override bool CanHandleRename(string oldFileName, string newFileName)
{
var oldNameBase = Path.GetFileNameWithoutExtension(oldFileName);
var newNameBase = Path.GetFileNameWithoutExtension(newFileName);
return SyntaxFacts.IsValidIdentifier(oldNameBase) && SyntaxFacts.IsValidIdentifier(newNameBase);
return SyntaxFacts.IsValidIdentifier(oldNameBase) && SyntaxFacts.IsValidIdentifier(newNameBase) && !Equals(Path.GetFileName(oldNameBase), Path.GetFileName(newNameBase));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is object.Equals, you should be using StringComparers.Path.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, it's by design that takes into account case? Unsure what I think about this - given most Windows file systems are case insensitive

Copy link
Member

@davkean davkean Dec 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this probably just represents the case of the <Compile Include="foo.cs" /> in the project file - and should this result in a rename for VB which is also case-insenstive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davkean , i am comparing the filename's not path . Have switched to using string.Compare.
I compared this with VS 14 and the rename is case sensitive. So rename is triggered if you change from Foo to foo. Let me know if you think otherwise

@davkean
Copy link
Member

davkean commented Dec 15, 2016

Spent some time about this, and I think this is what we should:

For C#, case should be factored in and we should rename program -> Program and vice versa.
For VB, however, I don't think case should be factored in.

This matches the legacy project system's behavior.

We should try and do above in a language-agnostic way - ie by asking some service from Roslyn based on the document and see if that can tell us whether it's case or a case-insensitive language to avoid hard-coding a language.

@davkean
Copy link
Member

davkean commented Dec 15, 2016

Okay, did some more research, basically, what you want to do is look at the doc and do something like:

this.Document.GetLanguageService<ISyntaxFactsService>().IsCaseSensitive;

@jinujoseph
Copy link
Contributor Author

@davkean thanks for taking a look, will add the conditional check

@davkean
Copy link
Member

davkean commented Jan 3, 2017

@jinujoseph Can you see if this resolves #1063? It looks like we're kicking off a bunch of rename sessions when dragging a bunch of files around.

@jinujoseph
Copy link
Contributor Author

jinujoseph commented Jan 3, 2017

@davkean: My understanding from @mavasani is that in order to use ISyntaxFactsService I need to have IVT access to Roslyn workspaces, so i will have to add IVT access, publish new nugetpackages for roslyn and add corresponding rolsyn dependencies to workspaces. Manish suggested i use compilation object instead [http://source.roslyn.io/#Microsoft.CodeAnalysis/Compilation/Compilation.cs,a12821839905319d,references ] , Let me know if you forsee any issue here.

I will validate 1063 on big project.

@mavasani
Copy link
Member

mavasani commented Jan 3, 2017

Note that Compilation.IsCaseSensitive will only work for projects supporting Compilation, i.e. VB and C# for now, which is probably fine until we support another language such as TypeScript which doesn't support compilation.

@davkean
Copy link
Member

davkean commented Jan 4, 2017

Sounds fine.

@jinujoseph
Copy link
Contributor Author

verified that this resolves #1063

{
var oldNameBase = Path.GetFileNameWithoutExtension(oldFileName);
var newNameBase = Path.GetFileNameWithoutExtension(newFileName);
return SyntaxFacts.IsValidIdentifier(oldNameBase) && SyntaxFacts.IsValidIdentifier(newNameBase);
return SyntaxFacts.IsValidIdentifier(oldNameBase) && SyntaxFacts.IsValidIdentifier(newNameBase) && (string.Compare(Path.GetFileName(oldNameBase), Path.GetFileName(newNameBase), IsCaseSensitive) !=0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jinujoseph Can you fix this to not call into C# specific SyntaxFacts? You should create a C# and VB specific rename strategy in corresponding layers and use language specific SyntaxFacts in those projects.

{
IRenameStrategy[] strategies = new IRenameStrategy[] {
new SimpleRenameStrategy(_threadingService, _userNotificationServices, _optionsSettings, _roslynServices)
};
return strategies.FirstOrDefault(s => s.CanHandleRename(_oldFilePath, _newFilePath));

var compilation = await project.GetCompilationAsync().ConfigureAwait(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compilation can be null for projects not supporting compilation, you should add a null check.

@@ -77,15 +77,17 @@ internal sealed class Renamer

public Task RenameAsync(Project project)
{
return GetStrategy()?.RenameAsync(project, _oldFilePath, _newFilePath) ?? Task.CompletedTask;
return GetStrategyAsync(project).Result?.RenameAsync(project, _oldFilePath, _newFilePath) ?? Task.CompletedTask;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use await, not .Result.

Additionally, you should do a null check as GetStrategyAsync can return null result.

@@ -19,11 +19,11 @@ public SimpleRenameStrategy(IProjectThreadingService threadingService, IUserNoti
}

// For the SimpleRename, it can attempt to handle any situtation
public override bool CanHandleRename(string oldFileName, string newFileName)
public override bool CanHandleRename(string oldFileName, string newFileName, bool IsCaseSensitive)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

param casing: isCaseSensitive

{
var oldNameBase = Path.GetFileNameWithoutExtension(oldFileName);
var newNameBase = Path.GetFileNameWithoutExtension(newFileName);
return SyntaxFacts.IsValidIdentifier(oldNameBase) && SyntaxFacts.IsValidIdentifier(newNameBase);
return SyntaxFacts.IsValidIdentifier(oldNameBase) && SyntaxFacts.IsValidIdentifier(newNameBase) && (string.Compare(Path.GetFileName(oldNameBase), Path.GetFileName(newNameBase), isCaseSensitive) !=0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does a cultural aware comparison, so "encyclopedia" == "encyclopædia" and will result in different results based on the user's current culture. You are dealing with paths here, so you want an ordinal comparison.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add tests cases for this? If I rename encyclopedia to encyclopædia it should still rename.

Copy link
Member

@davkean davkean left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above.

@jinujoseph
Copy link
Contributor Author

@srivatsn for approval

@jinujoseph jinujoseph merged commit 919ce33 into dotnet:master Jan 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants