My source generator needs to write some files to disk in addition to generating code files for the compilation in progress. These disk writes are completely unnecessary when the generator is being run by the IDE for its IntelliSense (or equivalent) functionality and only makes sense when the project is being actually built (it even tends to cause some failures, the IDE loves to run multiple instances of the source generator simultaneously).
Additionally, I see no reason to generate actual internals of any of the types generated by the source generator. Intuitively, only generating the public surface for the generated types would be lead to a faster and more responsive editor experience.
What is the most robust way for the source generator to differentiate what purpose it is being run for?
We don't give you a way to ask "am I in the IDE?" since that isn't always the correct question. For example:
Additionally, I see no reason to generate actual internals of any of the types generated by the source generator. Intuitively, only generating the public surface for the generated types would be lead to a faster and more responsive editor experience.
That's correct, up until you are doing Hot Reload/Edit and Continue, and we need those full implementations in the IDE process as were updating the debugee process. Now, that might not be workable in your particular scenario, but you get the idea.
What we have been trying to do instead is give a better way to give hints of intent. An incremental generator can call RegisterImplementationSourceOutput which is our hint to only run that if we need implementations. At the moment of this writing and in VS 17.2 we are still running that in the IDE, but we'll hopefully fix that soon.
There's also still some work in the pipeline: https://github.com/dotnet/roslyn/issues/57589 is tracking adding an API to do the reverse, and https://github.com/dotnet/roslyn/issues/49935 for a way to write other files directly.