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

Ensure generated trees have a full path #60095

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

chsienki
Copy link
Contributor

  • Use GeneratedFilesOutputDirectory as the base if provided
  • Fallback to OutputDirectory when not
  • Add tests and fix full PDB verification

Fixes #51998
Fixes #51773

- Use GeneratedFilesOutputDirectory as the base if provided
- Fallback to OutputDirectory when not
- Add tests and fix full PDB verification
@chsienki
Copy link
Contributor Author

@dotnet/roslyn-compiler for review please


Assert.Equal(expectedEmbeddedMap[docPath], sourceStr);
Assert.True(expectedEmbeddedMap.Remove(docPath));
}
}
catch
finally
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Turns out we were silently ignoring failures, but this function was not actually being used anyway :/

@@ -14324,6 +14325,123 @@ public void TestDuplicateAdditionalFiles(string additionalFilePath1, string addi
[InlineData("abc/a.txt", "./../ABC/a.txt", 2)]
public void TestDuplicateAdditionalFiles_Linux(string additionalFilePath1, string additionalFilePath2, int expectedCount) => TestDuplicateAdditionalFiles(additionalFilePath1, additionalFilePath2, expectedCount);


Copy link
Member

Choose a reason for hiding this comment

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

How does this behavior interact with [CallerFilePath] optional arguments? Now that the source file has a full path would expect some interaction with this feature.

driver = driver.RunGenerators(input);
var results = driver.GetRunResult();

var treeRoot = this.Arguments.GeneratedFilesOutputDirectory ?? Arguments.OutputDirectory;
Copy link
Member

Choose a reason for hiding this comment

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

This makes me nervous because toggling $(EmitCompilerGeneratedFiles) will end up impacting which directory we use here. That ends up impacting determinism because it's possible /pathmap accounts for these directories differently.

Not sure how do this better though. Only thought I had is should we only give them full paths if GeneratedFilesOutputDirectory is set? Basically if the user wants full paths they have to help us out here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, this is the crux of the issue really, but @tmat was fairly explicit that they should always have full paths as that's whats causing downstream tooling breaks.

We do have a test in this PR that validates /pathmap is working as expected for GeneratedFilesOutputDirectory, so we should be good on that front. If the user turns on $(EmitCompilerGeneratedFiles) then yes the user will have to also path map the directory we use there (which is user controllable too)

Copy link
Member

@tmat tmat Feb 6, 2023

Choose a reason for hiding this comment

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

Seems like a logical requirement for /pathmap that it needs to cover the directory specified in GeneratedFilesOutputDirectory. In practice, it will likely be some subdirectory of the project directory.

var results = driver.GetRunResult();

var treeRoot = this.Arguments.GeneratedFilesOutputDirectory ?? Arguments.OutputDirectory;
var compilationOut = input.AddSyntaxTrees(results.GeneratedTrees.Select(t => t.WithFilePath(Path.Combine(treeRoot, t.FilePath))));
Copy link
Member

@cston cston Mar 14, 2022

Choose a reason for hiding this comment

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

AddSyntaxTrees

Do we need to update PostInitTrees as well? #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if (Directory.Exists(Arguments.GeneratedFilesOutputDirectory))
{
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
Directory.CreateDirectory(Path.GetDirectoryName(tree.FilePath)!);
Copy link
Member

@cston cston Mar 14, 2022

Choose a reason for hiding this comment

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

tree.FilePath

Minor: Consider extracting a path local - in part, to minimize the changes here. #Closed

// validate that *no* sources were written
Assert.Empty(Directory.GetDirectories(generatedDir.Path));

// but we still have full paths (using output dir) in the PDBs
Copy link
Member

@cston cston Mar 14, 2022

Choose a reason for hiding this comment

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

Should we verify the files were written to the expected directory?

ValidateWrittenSources(new() { { generatedDir.Path, new() { { "generatedSource.cs", generatedSource } } } });
``` #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So we're not actually emitting any files here, which we check that on line 14384.

// validate that *no* sources were written
Assert.Empty(Directory.GetDirectories(generatedDir.Path));

// but we still have full paths (using output dir) in the PDBs
Copy link
Member

@cston cston Mar 14, 2022

Choose a reason for hiding this comment

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

Should we verify the files were written to the expected directory?

ValidateWrittenSources(new() { { Path.Combine(mappedPath, generatorPrefix), new() { { "generatedSource.cs", generatedSource } } } });
``` #Closed

@@ -2451,13 +2451,14 @@ private static void ValidateEmbeddedSources_Windows(Dictionary<string, string> e
continue;
}

var sourceStr = Encoding.UTF8.GetString(sourceBlob.Array, sourceBlob.Offset, sourceBlob.Count);
// offset by 3 to skip the BOM
Copy link
Member

Choose a reason for hiding this comment

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

Odd to do this unconditionally. What if there is no BOM?

@tmat
Copy link
Member

tmat commented Feb 6, 2023

Issue #51998 also mentions potential problem with #line directives using full paths in source-generated files. Seems like that still needs to be addressed, right?

@jaredpar
Copy link
Member

@chsienki this PR is essentially one year stale now. If we're not actively working on it can we move it to draft?

@chsienki chsienki marked this pull request as draft March 30, 2023 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants