Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

fix: use safe-decode-uri-component #450

Closed

Conversation

ramybenaroya
Copy link

This takes care of file names with '%' character. File names like
these can be automatically created by IDEs for backup.
Also, added a test for adding file with '%' character to InMemoryFileSystem.

Fixes #422

This takes care of file names with `'%'` character. File names like
these can be automatically created by IDEs for backup.
Also, added a test for adding file with `'%'` character to `InMemoryFileSystem`.

Fixes sourcegraph#422
@@ -9,6 +9,7 @@
"sourceMap": true,
"declaration": true,
"strictFunctionTypes": false,
"esModuleInterop": true,
Copy link
Author

Choose a reason for hiding this comment

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

Added this because safe-decode-uri-component is written in CommonJS. With this flag safe-decode-uri-component can be imported by:

import safeDecodeURIComponent from 'safe-decode-uri-component'

rather than

import * as safeDecodeURIComponent from 'safe-decode-uri-component'

@@ -18,6 +18,14 @@ describe('memfs.ts', () => {
sinon.assert.calledOnce(listener)
sinon.assert.calledWithExactly(listener, 'file:///foo/bar.txt', undefined)
})
it('should add a URI with `%` character and emit an event', () => {
Copy link
Author

Choose a reason for hiding this comment

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

This test would have been failed before this PR changes.
This is exactly the case #422 referres to.

Since esModuleInterop set to true, `rimraf` can be imported like a
regular module
@@ -2,7 +2,7 @@ import * as chai from 'chai'
import chaiAsPromised = require('chai-as-promised')
import * as fs from 'mz/fs'
import * as path from 'path'
import * as rimraf from 'rimraf'
import rimraf from 'rimraf'
Copy link
Author

Choose a reason for hiding this comment

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

@codecov
Copy link

codecov bot commented Apr 23, 2018

Codecov Report

Merging #450 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #450      +/-   ##
==========================================
+ Coverage   83.18%   83.19%   +<.01%     
==========================================
  Files          15       15              
  Lines        2040     2041       +1     
  Branches      415      415              
==========================================
+ Hits         1697     1698       +1     
  Misses        341      341              
  Partials        2        2
Impacted Files Coverage Δ
src/util.ts 89.88% <100%> (+0.11%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 312e432...bca9756. Read the comment docs.

@felixfbecker
Copy link
Contributor

Reading the code, it appears to me this only fixes the issue for file names with invalid escapes. If you modify your test to use a valid escape in the file name, would it still pass?

@ramybenaroya
Copy link
Author

Do you mean 'file:///foo/a%20bar.txt'?
If so, yes it would pass.

@felixfbecker
Copy link
Contributor

I meant a file that is literally called my%20file.txt

@ramybenaroya
Copy link
Author

oh, I see what you mean.
You are right, my PR's purpose is only for fixing invalid escaped.
Generally, on runtime, at this line, segment argument will already be my%2520file.txt since InMemoryFileSystem.add's input is a URI, meaning a valid escaped URL.

I made this PR to fix #422 (where for some reason paths are not escaped properly) in order to prevent a fatal exception.

@felixfbecker
Copy link
Contributor

felixfbecker commented May 1, 2018

Okay, in that case I believe the issue should be fixed properly.

@ramybenaroya
Copy link
Author

Do you want to close the PR?
I am ready to help with a proper fix if you can guide me a bit since this is my first contribution in this project.
What do you have in mind for a proper fix?

@autozimu
Copy link
Contributor

autozimu commented May 1, 2018

Sorry for bluntly chime in.

#422 is not caused by invalid encoding.

The file name is literally %test.js, which is used by vim as backup file by default (vaguely remember emacs does the same thing).

As I also commented under #422, language client didn't send this path. It is picked up by language server when trying to build index.

With that said, this should resolve #422, though it only fixes the consequeue but not the cause.

I'd love to see #422 got resolved, but a concern from this project's perspective is that how much compatibility this new safe-decode-uri-component can provide as a replacement of decodeURIComponent , when it comes to decoding valid uris.

@ramybenaroya
Copy link
Author

@autozimu Thanks for the explanation.
I am closing this for the following reasons:
1.safe-decode-uri-componentis probably not a good candidate for replacing native decodeURIComponent since it is not widely used and doesn't meet this project's standards.
2. A better solution will be to fix the index building process in order that %test.js will be encoded to %25test.js.
3. Fixing the consequence is never good enough.

@felixfbecker @autozimu Thanks for your input and attention.

@felixfbecker
Copy link
Contributor

For context, the reason why the code calls encodeURIComponent(decodeURIComponent(segment)) is so that files names have a canonical name and can be used as map keys. Otherwise you can end up with the client sending URIs for certain files with a different URI than what the language server came up with and you get duplicate entries in Maps. For example, a client might encode a space as +, but the language server used %20. Or the language server chose to escape some special character that the client didn't.

Now the bug here seems to be indeed that the URI for %test.js at that point in the code is not properly encoded to %25test.js. I would set a conditional breakpoint inside the function (or an if with console.trace()) and see where the value comes from.

@autozimu
Copy link
Contributor

autozimu commented May 1, 2018

The call comes from

subscriber.next(normalizeUri(base + file))

The result come from glob should already be valid paths.

For the concern that the path might have other aliases other than its canonical form. I believe it can be done by querying from filesystem, https://github.com/autozimu/LanguageClient-neovim/blob/84445be4a3bf7f67547abad205c6c46eb289844d/src/languageclient.rs#L1619 It won't cover all cases, but should be enough for general cases.

@felixfbecker
Copy link
Contributor

Oh, seems like all it needs it to encode file in that line! When constructing the URI from file paths, it needs to be encoded.

For the concern that the path might have other aliases other than its canonical form. I believe it can be done by querying from filesystem

That won't work because not all files the language server works with are available on the file system.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants