Skip to content

Support CodeClass2.Parts returning parts in source generated files #58241

Merged
jasonmalinowski merged 4 commits intodotnet:mainfrom
jasonmalinowski:give-some-support-for-generated-documents-in-codemodel
Dec 15, 2021
Merged

Support CodeClass2.Parts returning parts in source generated files #58241
jasonmalinowski merged 4 commits intodotnet:mainfrom
jasonmalinowski:give-some-support-for-generated-documents-in-codemodel

Conversation

@jasonmalinowski
Copy link
Copy Markdown
Member

@jasonmalinowski jasonmalinowski commented Dec 10, 2021

Some designers look through the other partial parts of a class to look for methods that match event handler signatures. Here I'm adding limited support so you can get a FileCodeModel and CodeElement for things residing in source generated files.

Unlike regular FileCodeModels that have certain lifetime guarantees and use our COM weak handle magic, this is keeping the implementation simple and just returning a new FileCodeModel any time we need one, under the hopes that the uses of this are rare. If that becomes a problem, we can refactor the CodeModel cache to deal with these, but there is some complexity around when we precisely know the document has gone away. Since CodeModel is very much a legacy API I don't want to spend time adding complexity until we know we need it.

This also doesn't implement any support for raising change events if a generator output changes. Again, if that is needed we can update the diffing code accordingly.

These can be used by things other than the project system tests.
@ghost ghost added the Area-IDE label Dec 10, 2021
@jasonmalinowski jasonmalinowski self-assigned this Dec 10, 2021
@jasonmalinowski jasonmalinowski force-pushed the give-some-support-for-generated-documents-in-codemodel branch 2 times, most recently from 1dee96e to fbabebf Compare December 14, 2021 02:42
@jasonmalinowski jasonmalinowski changed the title Give some support for generated documents in CodeModel Support CodeClass2.Parts returning parts in source generated files Dec 14, 2021
The unit tests were testing against a special mock of
VisualStudioWorkspace, which meant the "real" implementation of
GetFileCodeModel wasn't being used, but instead requests for code model
would just go through a lookup into a dictionary. This commit moves
the MockVisualStudioWorkspace to inherit from VisualStudioWorkspaceImpl
where the actual implementation lies, and then generally cleans up this
area to create things via MEF rather than via direct calls to
constructors of some MEF-produced types.
This returns a ProjectItem from the project system for a file, but in
the case of source generated files we won't be able to do that since
they're not represented by anything the project system knows about.

Coincidently, our unit tests always have been passing null the whole
time so this is something more or less we need to deal with regardless.
Some designers look through the other partial parts of a class to look
for methods that match event handler signatures. Here I'm adding limited
support so you can get a FileCodeModel and CodeElement for things
residing in source generated files.

Unlike regular FileCodeModels that have certain lifetime guarantees and
use our COM weak handle magic, this is keeping the implementation simple
and just returning a new FileCodeModel any time we need one, under the
hopes that the uses of this are rare. If that becomes a problem, we can
refactor the CodeModel cache to deal with these, but there is some
complexity around when we precisely know the document has gone away.
Since CodeModel is very much a legacy API I don't want to spend time
adding complexity until we know we need it.

This also doesn't implement any support for raising change events if
a generator output changes. Again, if that is needed we can update
the diffing code accordingly.
@jasonmalinowski jasonmalinowski force-pushed the give-some-support-for-generated-documents-in-codemodel branch from fee5781 to f89b4bf Compare December 14, 2021 22:57
return WorkspaceAndCodeModel.workspace;
}

private VisualStudioWorkspace GetExtraWorkspaceToDisposeButNotUse()
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The VisualStudioWorkspace instance is now created by the MEF container, which will dispose it when we dispose the container itself.

@jasonmalinowski jasonmalinowski marked this pull request as ready for review December 15, 2021 02:44
@jasonmalinowski jasonmalinowski requested a review from a team as a code owner December 15, 2021 02:44

var documentFilePath = GetFilePath(documentId);
if (documentFilePath == null)
var document = _threadingContext.JoinableTaskFactory.Run(() => CurrentSolution.GetDocumentAsync(documentId, includeSourceGenerated: true).AsTask());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

:(

is this on UI thread? does this mean we're now blocking hte UI thread on unbounded source-generator work?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That's not new, in essence: any CodeModel operation is going to be asking for semantics, which will block.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Chatting with @CyrusNajmabadi offline, we also realized that in many cases they only way you get here is already having ran generators. i.e. you won't have known there's a DocumentId for the source generated file in the first place without generators having ran.

else if (_isSourceGeneratedOutput)
{
document = State.ThreadingContext.JoinableTaskFactory.Run(
() => Workspace.CurrentSolution.GetSourceGeneratedDocumentAsync(GetDocumentId(), CancellationToken.None).AsTask());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

same concern here.

{
// Unlike for "regular" documents, we make no effort to cache these between callers or hold them for longer lifetimes with
// events.
return FileCodeModel.Create(GetCodeModelCache().State, parent: null, sourceGeneratedDocument.Id, isSourceGeneratorOutput: true, new TextManagerAdapter()).Handle;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

do you want to CWT this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I could, I didn't want to do any caching at all just to keep things simple.

@jasonmalinowski jasonmalinowski merged commit d6f231d into dotnet:main Dec 15, 2021
@jasonmalinowski jasonmalinowski deleted the give-some-support-for-generated-documents-in-codemodel branch December 15, 2021 20:12
@ghost ghost added this to the Next milestone Dec 15, 2021
@Cosifne Cosifne modified the milestones: Next, 17.1.P3 Jan 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants