What's wrong
In Semantics.Paths/SemanticFilePath.cs:
FileExtension (around line 14) searches the entire path with LastIndexOf('.').
FullFileExtension (around line 53) does the same with IndexOf('.').
Neither limits the search to the file-name segment. When a directory component contains a dot, the substring handed to FileExtension.Create includes a directory separator. IsFileExtensionAttribute rejects that, so the property getter throws.
Failure scenarios (Linux, reproduced)
| Expression |
Result |
AbsoluteFilePath("/home/user/.config/settings.json").FullFileExtension |
ArgumentException: Cannot convert ".config/settings.json" to FileExtension |
RelativeFilePath("../data/archive.tar.gz").FullFileExtension |
throws for "../data/archive.tar.gz" |
FilePath("./notes.txt").FullFileExtension |
throws for "./notes.txt" |
AbsoluteFilePath("/opt/app.v2/README").FileExtension |
throws for ".v2/README"; it should return an empty extension |
Paths with ./, ../, dot-directories such as .config, .git and .vscode, or versioned folder names are everyday input. For all of them, a simple property read throws. The existing tests use bare file names only (for example "test.tar.gz"), so the bug goes unnoticed.
Suggested fix
Work on the file-name segment only. Slice after the last / or \ (or use Path.GetFileName) before searching for dots. For FullFileExtension, also skip a leading dot in the file name, so .bashrc is treated as a name with no extension rather than an extension.
Acceptance criteria
"./notes.txt" → FileExtension == ".txt" and FullFileExtension == ".txt".
"../data/archive.tar.gz" → FileExtension == ".gz" and FullFileExtension == ".tar.gz".
"/opt/app.v2/README" → both are empty.
"/home/user/.bashrc" → both are empty, per the chosen dotfile rule, which should be documented.
- The tests cover both the netstandard2.0 branch and the span branch.
What's wrong
In
Semantics.Paths/SemanticFilePath.cs:FileExtension(around line 14) searches the entire path withLastIndexOf('.').FullFileExtension(around line 53) does the same withIndexOf('.').Neither limits the search to the file-name segment. When a directory component contains a dot, the substring handed to
FileExtension.Createincludes a directory separator.IsFileExtensionAttributerejects that, so the property getter throws.Failure scenarios (Linux, reproduced)
AbsoluteFilePath("/home/user/.config/settings.json").FullFileExtensionArgumentException: Cannot convert ".config/settings.json" to FileExtensionRelativeFilePath("../data/archive.tar.gz").FullFileExtension"../data/archive.tar.gz"FilePath("./notes.txt").FullFileExtension"./notes.txt"AbsoluteFilePath("/opt/app.v2/README").FileExtension".v2/README"; it should return an empty extensionPaths with
./,../, dot-directories such as.config,.gitand.vscode, or versioned folder names are everyday input. For all of them, a simple property read throws. The existing tests use bare file names only (for example"test.tar.gz"), so the bug goes unnoticed.Suggested fix
Work on the file-name segment only. Slice after the last
/or\(or usePath.GetFileName) before searching for dots. ForFullFileExtension, also skip a leading dot in the file name, so.bashrcis treated as a name with no extension rather than an extension.Acceptance criteria
"./notes.txt"→FileExtension == ".txt"andFullFileExtension == ".txt"."../data/archive.tar.gz"→FileExtension == ".gz"andFullFileExtension == ".tar.gz"."/opt/app.v2/README"→ both are empty."/home/user/.bashrc"→ both are empty, per the chosen dotfile rule, which should be documented.