I'm guessing/hoping that the completion service is doing a proper evaluation of the project by using the MSBuild SDK to load and evaluate the project. An example of not doing a proper project evaluation would be treating the project as an XML file and querying for Reference elements. The problem with doing this is that Properties (which you have referred to as variables) will not be evaluated.
Environment variables are mapped to Properties. You could, at your command prompt or in a shell script, define a RimWorldManagedDir environment variable and then start VSCode with code.
The RimWorldManagedDir property could have a default value. e.g.
<PropertyGroup>
<!-- assumes a RimWorld subdirectory of the project directory -->
<RimWorldManagedDir Condition="'$(RimWorldManagedDir)' == ''">RimWorld/RimWorldLinux_Data/Managed/</RimWorldManagedDir>
<!-- normalize the directory path to always end with a slash -->
<RimWorldManagedDir>$([MSBuild]::EnsureTrailingSlash('$(RimWorldManagedDir)'))</RimWorldManagedDir>
</PropertyGroup>
<Reference Include="Assembly-CSharp">
<HintPath>$(RimWorldManagedDir)Assembly-CSharp.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>$(RimWorldManagedDir)UnityEngine.CoreModule.dll</HintPath>
</Reference>
When there is a RimWorldManagedDir environment variable, the RimWorldManagedDir property will have a value and the Condition of '$(RimWorldManagedDir)' == '' will be false.
MSBuild supports textual includes via the Import element. An Import can have a Condition.
<Import Project="user.targets" Condition="Exists('user.targets')" />
<PropertyGroup>
<!-- assumes a RimWorld subdirectory of the project directory -->
<RimWorldManagedDir Condition="'$(RimWorldManagedDir)' == ''">RimWorld/RimWorldLinux_Data/Managed/</RimWorldManagedDir>
<!-- normalize the directory path to always end with a slash -->
<RimWorldManagedDir>$([MSBuild]::EnsureTrailingSlash('$(RimWorldManagedDir)'))</RimWorldManagedDir>
</PropertyGroup>
...
The user.targets file might contain
<Project>
<PropertyGroup>
<RimWorldManagedDir Condition="'$(RimWorldManagedDir)' == ''">/home/nicole/.local/share/Steam/steamapps/common/RimWorld/RimWorldLinux_Data/Managed/</RimWorldManagedDir>
</PropertyGroup>
</Project>
If there are some common conventions for install locations, you could test for those locations.
<Import Project="user.targets" Condition="Exists('user.targets')" />
<PropertyGroup>
<_localSteamApps>$([System.Environment]::GetFolderPath(SpecialFolder.UserProfile)).local/share/Steam/steamapps/common/RimWorld/RimWorldLinux_Data/Managed/</_localSteamApps>
<RimWorldManagedDir Condition="'$(RimWorldManagedDir)' == '' and Exists('$(_localSteamApps)')">$(_localSteamApps)</RimWorldManagedDir>
<!-- assumes a RimWorld subdirectory of the project directory -->
<RimWorldManagedDir Condition="'$(RimWorldManagedDir)' == ''">RimWorld/RimWorldLinux_Data/Managed/</RimWorldManagedDir>
<!-- normalize the directory path to always end with a slash -->
<RimWorldManagedDir>$([MSBuild]::EnsureTrailingSlash('$(RimWorldManagedDir)'))</RimWorldManagedDir>
</PropertyGroup>
...
Now you have a cascade in the following order of precedence:
- Use the
RimWorldManagedDir environment variable if it exists.
- Otherwise use the property value on the command line (the
-p or -property switch) if it exists.
- Import the user.targets file if it exists. In the file a user can set a specific value for the property. In the example user.targets file, the property is set with a value when it doesn't already have a value (from the environment or command line).
- Otherwise test for a conventional location.
- Otherwise use a default value.