Compare commits

..

2 Commits

Author SHA1 Message Date
Silver
d49075a970 Update and clean up Prototype manager methods 2022-02-11 00:27:34 -07:00
Silver
a67acd453c Split out Interface and Attribute 2022-02-11 00:26:58 -07:00
2065 changed files with 61501 additions and 170943 deletions

View File

@@ -10,8 +10,5 @@ charset = utf-8
[*.{csproj,xml,yml,dll.config,targets,props}]
indent_size = 2
[nuget.config]
indent_size = 2
[*.gdsl]
indent_style = tab

22
.github/CODEOWNERS vendored
View File

@@ -1,12 +1,20 @@
# Last match in file takes precedence.
# Ping for all PRs
* @PJB3005 @DrSmugleaf
* @Acruid @PJB3005 @Silvertorch5
# commands commands commands commands
**/Toolshed/** @moonheart08
*Command.cs @moonheart08
*Commands.cs @moonheart08
/Robust.*/Audio/Midi/ @Zumorica
# Physics
**/Robust.Shared/Physics/** @metalgearsloth
/Robust.Client.NameGenerator @PaulRitter
/Robust.Client.Injectors @PaulRitter
/Robust.Generators @PaulRitter
/Robust.Analyzers @PaulRitter
/Robust.*/GameStates @PaulRitter
/Robust.Shared/Analyzers @PaulRitter
/Robust.*/Serialization @PaulRitter
/Robust.*/Prototypes @PaulRitter
/Robust.Shared/GameObjects/ComponentDependencies @PaulRitter
/Robust.*/Containers @PaulRitter
# Be they Fluent translations or Freemarker templates, I know them both!
*.ftl @RemieRichards

View File

@@ -1,41 +0,0 @@
name: Benchmarks
on:
workflow_dispatch:
schedule:
- cron: '0 5 * * *'
push:
tags:
- 'v*'
concurrency: benchmarks
jobs:
benchmark:
name: Run Benchmarks
runs-on: ubuntu-latest
steps:
- name: Run script on centcomm
uses: appleboy/ssh-action@master
with:
host: centcomm.spacestation14.io
username: robust-benchmark-runner
key: ${{ secrets.CENTCOMM_ROBUST_BENCHMARK_RUNNER_KEY }}
command_timeout: 100000m
script: |
mkdir benchmark_run_${{ github.sha }}
cd benchmark_run_${{ github.sha }}
git clone https://github.com/space-wizards/RobustToolbox.git repo_dir --recursive
cd repo_dir
git checkout ${{ github.sha }}
cd Robust.Benchmarks
dotnet restore
export ROBUST_BENCHMARKS_ENABLE_SQL=1
export ROBUST_BENCHMARKS_SQL_ADDRESS="${{ secrets.BENCHMARKS_WRITE_ADDRESS }}"
export ROBUST_BENCHMARKS_SQL_PORT="${{ secrets.BENCHMARKS_WRITE_PORT }}"
export ROBUST_BENCHMARKS_SQL_USER="${{ secrets.BENCHMARKS_WRITE_USER }}"
export ROBUST_BENCHMARKS_SQL_PASSWORD="${{ secrets.BENCHMARKS_WRITE_PASSWORD }}"
export ROBUST_BENCHMARKS_SQL_DATABASE="benchmarks"
export GITHUB_SHA="${{ github.sha }}"
dotnet run --filter '*' --configuration Release
cd ../../..
rm -rf benchmark_run_${{ github.sha }}

View File

@@ -1,34 +0,0 @@
name: Build & Publish DocFX
on:
schedule:
- cron: "0 0 * * 0"
jobs:
docfx:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3.6.0
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v3.2.0
with:
dotnet-version: 8.0.x
- name: Install dependencies
run: dotnet restore
- name: Build Project
run: dotnet build --no-restore /p:WarningsAsErrors=nullable
- name: Build DocFX
uses: nikeee/docfx-action@v1.0.0
with:
args: Robust.Docfx/docfx.json
- name: Publish Docfx Documentation on GitHub Pages
uses: maxheld83/ghpages@master
env:
BUILD_DIR: Robust.Docfx/_robust-site
GH_PAT: ${{ secrets.GH_PAT }}

View File

@@ -15,19 +15,17 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3.6.0
- uses: actions/checkout@v2
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: 8.0.x
dotnet-version: 6.0.100
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore /p:WarningsAsErrors=nullable
- name: Test Engine
run: dotnet test --no-build Robust.UnitTesting/Robust.UnitTesting.csproj -- NUnit.ConsoleOut=0
run: dotnet test --no-build Robust.UnitTesting/Robust.UnitTesting.csproj -v n

View File

@@ -35,14 +35,14 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3.6.0
uses: actions/checkout@v2
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: 7.0.x
dotnet-version: 6.0.100
- name: Build
run: dotnet build

View File

@@ -16,14 +16,14 @@ jobs:
$ver = [regex]::Match($env:GITHUB_REF, "refs/tags/v?(.+)").Groups[1].Value
echo ("::set-output name=version::{0}" -f $ver)
- uses: actions/checkout@v3.6.0
- uses: actions/checkout@v2
with:
submodules: true
- name: Setup .NET Core
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: 8.0.x
dotnet-version: 6.0.100
- name: Package client
run: Tools/package_client_build.py -p windows mac linux

View File

@@ -13,15 +13,15 @@ jobs:
steps:
- name: Check out content
uses: actions/checkout@v3.6.0
uses: actions/checkout@v2
with:
repository: space-wizards/space-station-14
submodules: recursive
- name: Setup .NET Core
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: 8.0.x
dotnet-version: 6.0.100
- name: Disable submodule autoupdate
run: touch BuildChecker/DISABLE_SUBMODULE_AUTOUPDATE
@@ -34,7 +34,7 @@ jobs:
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Tools --no-restore
run: dotnet build --configuration Release --no-restore
- name: Content.Tests
run: dotnet test --no-build Content.Tests/Content.Tests.csproj -v n
- name: Content.IntegrationTests

2
.gitignore vendored
View File

@@ -76,5 +76,3 @@ MSBuild/Robust.Custom.targets
release/
Robust.Docfx/*-site
Robust.Docfx/api

3
.gitmodules vendored
View File

@@ -10,6 +10,9 @@
[submodule "Robust.LoaderApi"]
path = Robust.LoaderApi
url = https://github.com/space-wizards/Robust.LoaderApi.git
[submodule "ManagedHttpListener"]
path = ManagedHttpListener
url = https://github.com/space-wizards/ManagedHttpListener.git
[submodule "cefglue"]
path = cefglue
url = https://github.com/space-wizards/cefglue.git

View File

@@ -1,3 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\MSBuild\Robust.Engine.props" />
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -1,61 +0,0 @@
<Project>
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.13.12" />
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageVersion Include="ILReader.Core" Version="1.0.0.4" />
<PackageVersion Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageVersion Include="JetBrains.Profiler.Api" Version="1.4.0" />
<PackageVersion Include="Linguini.Bundle" Version="0.1.3" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzer.Testing" Version="1.1.1"/>
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.NUnit" Version="1.1.1"/>
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Features" Version="4.8.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.8.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.8.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="4.8.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.8.0" />
<PackageVersion Include="Microsoft.CodeCoverage" Version="17.8.0" />
<PackageVersion Include="Microsoft.Data.Sqlite.Core" Version="8.0.0" />
<PackageVersion Include="Microsoft.DotNet.RemoteExecutor" Version="8.0.0-beta.24059.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.ObjectPool" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="8.0.0" />
<PackageVersion Include="Microsoft.ILVerification" Version="8.0.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
<PackageVersion Include="Microsoft.NET.ILLink.Tasks" Version="8.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageVersion Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageVersion Include="Moq" Version="4.20.70" />
<PackageVersion Include="NUnit" Version="4.0.1" />
<PackageVersion Include="NUnit.Analyzers" Version="3.10.0" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageVersion Include="Nett" Version="0.15.0" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.4" />
<PackageVersion Include="OpenTK.OpenAL" Version="4.7.7" />
<PackageVersion Include="OpenToolkit.Graphics" Version="4.0.0-pre9.1" />
<PackageVersion Include="Pidgin" Version="3.2.2" />
<PackageVersion Include="Robust.Natives" Version="0.1.1" />
<PackageVersion Include="Robust.Natives.Cef" Version="120.1.9" />
<PackageVersion Include="Robust.Shared.AuthLib" Version="0.1.2" />
<PackageVersion Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.7" />
<PackageVersion Include="SQLitePCLRaw.provider.sqlite3" Version="2.1.7" />
<PackageVersion Include="Serilog" Version="3.1.1" />
<PackageVersion Include="Serilog.Sinks.Loki" Version="4.0.0-beta3" />
<PackageVersion Include="SharpZstd.Interop" Version="1.5.2-beta2" />
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.2" />
<PackageVersion Include="SpaceWizards.HttpListener" Version="0.1.0" />
<PackageVersion Include="SpaceWizards.NFluidsynth" Version="0.1.1" />
<PackageVersion Include="SpaceWizards.SharpFont" Version="1.0.2" />
<PackageVersion Include="SpaceWizards.Sodium" Version="0.2.1" />
<PackageVersion Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageVersion Include="TerraFX.Interop.Windows" Version="10.0.22621.5" />
<PackageVersion Include="TerraFX.Interop.Xlib" Version="6.4.0" />
<PackageVersion Include="VorbisPizza" Version="1.3.0" />
<PackageVersion Include="YamlDotNet" Version="13.7.1" />
<PackageVersion Include="prometheus-net" Version="8.2.1" />
<PackageVersion Include="prometheus-net.DotNetRuntime" Version="4.4.0" />
</ItemGroup>
</Project>

View File

@@ -1,9 +0,0 @@
using System.Runtime.CompilerServices;
// So I wanted to mess with NetIncomingMessage and NetOutgoingMessage from tests.
// Now.. the instructors are internal...
// Unless...
// I mean we have this project here from the weird way we're compiling Lidgren.
// I could just put this in here... it wouldn't touch the main Lidgren repo at all...
[assembly: InternalsVisibleTo("Robust.UnitTesting")]

View File

@@ -1,28 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>SpaceWizards.Lidgren.Network</AssemblyName>
<TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<DefaultItemExcludes>Lidgren.Network/**/*</DefaultItemExcludes>
<DefineConstants>$(DefineConstants);USE_RELEASE_STATISTICS</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<SkipRobustAnalyzer>true</SkipRobustAnalyzer>
<Nullable>enable</Nullable>
<LangVersion>12.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="CursedHorrorsBeyondOurWildestImagination.cs" />
<Compile Include="Lidgren.Network\Lidgren.Network\**\*.cs">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
</Compile>
<Compile Remove="Lidgren.Network\Lidgren.Network\obj\**\*.cs" />
</ItemGroup>
<Import Project="../MSBuild/Robust.Properties.targets" />
</Project>

View File

@@ -1,5 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<ItemGroup>
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\Robust.Shared.CompNetworkGenerator\Robust.Shared.CompNetworkGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
</Project>

View File

@@ -1,37 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Build configurations -->
<PropertyGroup>
<!-- Avoid SDK defining DEBUG/RELEASE/DEBUGOPT/TOOLS itself. -->
<DisableImplicitConfigurationDefines>true</DisableImplicitConfigurationDefines>
<!-- Project configurations -->
<Configurations>Debug;Release;Tools;DebugOpt</Configurations>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<!-- Debug configuration: asserts, tools, no optimizations -->
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<DebugSymbols Condition="'$(DebugSymbols)' == ''">true</DebugSymbols>
<Optimize Condition="'$(Optimize)' == ''">false</Optimize>
<RobustToolsBuild Condition="'$(RobustToolsBuild)' == ''">true</RobustToolsBuild>
<DefineConstants>DEBUG;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<!-- DebugOpt configuration: asserts, tools, optimizations -->
<PropertyGroup Condition="'$(Configuration)' == 'DebugOpt'">
<DebugSymbols Condition="'$(DebugSymbols)' == ''">true</DebugSymbols>
<Optimize Condition="'$(Optimize)' == ''">true</Optimize>
<RobustToolsBuild Condition="'$(RobustToolsBuild)' == ''">true</RobustToolsBuild>
<DefineConstants>DEBUG;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<!-- Tools configuration: no asserts, tools, optimizations -->
<PropertyGroup Condition="'$(Configuration)' == 'Tools'">
<DebugSymbols Condition="'$(DebugSymbols)' == ''">true</DebugSymbols>
<Optimize Condition="'$(Optimize)' == ''">true</Optimize>
<RobustToolsBuild Condition="'$(RobustToolsBuild)' == ''">true</RobustToolsBuild>
</PropertyGroup>
<!-- Release configuration: no asserts, no tools, optimizations -->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<Optimize Condition="'$(Optimize)' == ''">true</Optimize>
<RobustToolsBuild Condition="'$(RobustToolsBuild)' == ''">false</RobustToolsBuild>
<DefineConstants>RELEASE;$(DefineConstants)</DefineConstants>
</PropertyGroup>
</Project>

View File

@@ -20,19 +20,10 @@
<PropertyGroup Condition="'$(FullRelease)' == 'True'">
<DefineConstants>$(DefineConstants);FULL_RELEASE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(FullRelease)' != 'True'">
<DefineConstants>$(DefineConstants);DEVELOPMENT</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release' Or '$(Configuration)' == 'Tools'">
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DefineConstants>$(DefineConstants);EXCEPTION_TOLERANCE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(EnableClientScripting)' == 'True'">
<DefineConstants>$(DefineConstants);CLIENT_SCRIPTING</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(UseSystemSqlite)' == 'True'">
<DefineConstants>$(DefineConstants);USE_SYSTEM_SQLITE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(RobustToolsBuild)' == 'true'">
<DefineConstants>$(DefineConstants);TOOLS</DefineConstants>
</PropertyGroup>
</Project>

View File

@@ -1,4 +1,4 @@
<Project>
<!-- This file automatically reset by Tools/version.py -->
<Project>
<!-- This file automatically reset by Tools/version.py -->
<PropertyGroup><Version>0.8.52</Version></PropertyGroup>
</Project>

View File

@@ -1,8 +1,8 @@
<Project>
<!-- Engine-specific properties. Content should not use this file. -->
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>12</LangVersion>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>10</LangVersion>
<Nullable>enable</Nullable>
<WarningsAsErrors>nullable</WarningsAsErrors>
</PropertyGroup>

View File

@@ -1,35 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- MSBuild hurts and I can't find a foolproof way to detect platform. -->
<PropertyGroup>
<OS Condition="'$(OS)' == ''">Windows_NT</OS>
</PropertyGroup>
<Choose>
<When Condition="'$(OS)' != 'Unix'">
<PropertyGroup>
<ActualOS>Windows</ActualOS>
</PropertyGroup>
</When>
<!-- Folders that *probably* only exist on MacOS and not Linux. -->
<When Condition="Exists('/Volumes') And Exists('/System') And Exists('/Library')" >
<PropertyGroup>
<ActualOS>MacOS</ActualOS>
</PropertyGroup>
</When>
<When Condition="$([MSBuild]::IsOSPlatform('FreeBSD'))">
<PropertyGroup>
<ActualOS>FreeBSD</ActualOS>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<ActualOS>Linux</ActualOS>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup>
<TargetOS Condition="'$(TargetOS)' == ''">$(ActualOS)</TargetOS>
<Python>python3</Python>
<Python Condition="'$(ActualOS)' == 'Windows'">py -3</Python>
<UseSystemSqlite Condition="'$(TargetOS)' == 'FreeBSD'">True</UseSystemSqlite>
</PropertyGroup>
</Project>

View File

@@ -1,32 +1,34 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Properties for both engine and content. -->
<!-- Import this at the end of any project files in Robust and Content. -->
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<Import Project="Robust.Custom.targets" Condition="Exists('Robust.Custom.targets')"/>
<!-- Configuration logic -->
<Import Project="Robust.Configurations.props" />
<!-- Some platform management logic -->
<Import Project="Robust.Platform.props" />
<!-- MSBuild hurts and I can't find a foolproof way to detect platform. -->
<PropertyGroup>
<EnableClientScripting>False</EnableClientScripting>
<!-- Client scripting is only enabled on tools builds for security and size reasons. -->
<EnableClientScripting Condition="'$(RobustToolsBuild)' == 'true'">True</EnableClientScripting>
<OS Condition="'$(OS)' == ''">Windows_NT</OS>
</PropertyGroup>
<Choose>
<When Condition="'$(OS)' != 'Unix'">
<PropertyGroup>
<ActualOS>Windows</ActualOS>
</PropertyGroup>
</When>
<!-- Folders that *probably* only exist on MacOS and not Linux. -->
<When Condition="Exists('/Volumes') And Exists('/System') And Exists('/Library')" >
<PropertyGroup>
<ActualOS>MacOS</ActualOS>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<ActualOS>Linux</ActualOS>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup>
<TargetOS Condition="'$(TargetOS)' == ''">$(ActualOS)</TargetOS>
<Python>python3</Python>
<Python Condition="'$(ActualOS)' == 'Windows'">py -3</Python>
<TargetFramework>net6.0</TargetFramework>
<EnableClientScripting>True</EnableClientScripting>
<!-- Client scripting is disabled on full release builds for security and size reasons. -->
<EnableClientScripting Condition="'$(FullRelease)' == 'True'">False</EnableClientScripting>
</PropertyGroup>
<!-- built-in define constants -->
<Import Project="Robust.DefineConstants.targets" />
<!-- analyzer -->
<Import Project="Robust.Analyzers.targets" Condition="'$(SkipRobustAnalyzer)' != 'true'" />
<!-- serialization generator -->
<Import Project="Robust.Serialization.Generator.targets" Condition="'$(SkipRobustAnalyzer)' != 'true'" />
</Project>

View File

@@ -1,5 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<ItemGroup>
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\Robust.Serialization.Generator\Robust.Serialization.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
</Project>

View File

@@ -19,17 +19,10 @@
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\Robust.Client.Injectors\Robust.Client.Injectors.csproj" ReferenceOutputAssembly="false"/>
</ItemGroup>
<!-- XamlIL does not make use of special Robust configurations like DebugOpt. Convert these down. -->
<PropertyGroup>
<RobustInjectorsConfiguration>$(Configuration)</RobustInjectorsConfiguration>
<RobustInjectorsConfiguration Condition="'$(Configuration)' == 'DebugOpt'">Debug</RobustInjectorsConfiguration>
<RobustInjectorsConfiguration Condition="'$(Configuration)' == 'Tools'">Release</RobustInjectorsConfiguration>
</PropertyGroup>
<UsingTask
Condition="'$(_RobustUseExternalMSBuild)' != 'true' And $(DesignTimeBuild) != true"
TaskName="CompileRobustXamlTask"
AssemblyFile="$(MSBuildThisFileDirectory)\..\Robust.Client.Injectors\bin\$(RobustInjectorsConfiguration)\netstandard2.0\Robust.Client.Injectors.dll"/>
AssemblyFile="$(MSBuildThisFileDirectory)\..\Robust.Client.Injectors\bin\$(Configuration)\netstandard2.0\Robust.Client.Injectors.dll"/>
<Target
Name="CompileRobustXaml"
Condition="Exists('@(IntermediateAssembly)')"

1
ManagedHttpListener Submodule

Submodule ManagedHttpListener added at ae0539e66f

View File

@@ -10,6 +10,7 @@
using System;
using System.Runtime.InteropServices;
using static OpenToolkit.GraphicsLibraryFramework.GLFWNative;
using static Robust.Shared.Utility.MarshalHelper;
namespace OpenToolkit.GraphicsLibraryFramework
{
@@ -210,7 +211,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// <seealso cref="GetVersion"/>
public static unsafe string GetVersionString()
{
return Marshal.PtrToStringUTF8((IntPtr) glfwGetVersionString());
return PtrToStringUTF8(glfwGetVersionString());
}
/// <summary>
@@ -271,7 +272,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
{
byte* desc;
var code = glfwGetError(&desc);
description = Marshal.PtrToStringUTF8((IntPtr) desc);
description = PtrToStringUTF8(desc);
return code;
}
@@ -589,7 +590,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// </remarks>
public static unsafe string GetMonitorName(Monitor* monitor)
{
return Marshal.PtrToStringUTF8((IntPtr) glfwGetMonitorName(monitor));
return PtrToStringUTF8(glfwGetMonitorName(monitor));
}
/// <summary>
@@ -901,7 +902,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// </remarks>
public static unsafe void WindowHint(WindowHintString hint, string value)
{
var ptr = Marshal.StringToCoTaskMemUTF8(value);
var ptr = StringToCoTaskMemUTF8(value);
try
{
@@ -1363,7 +1364,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// </remarks>
public static unsafe string GetKeyName(Keys key, int scanCode)
{
return Marshal.PtrToStringUTF8((IntPtr) glfwGetKeyName(key, scanCode));
return PtrToStringUTF8(glfwGetKeyName(key, scanCode));
}
/// <summary>
@@ -2277,7 +2278,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// </remarks>
public static unsafe string GetJoystickName(int jid)
{
return Marshal.PtrToStringUTF8((IntPtr) glfwGetJoystickName(jid));
return PtrToStringUTF8(glfwGetJoystickName(jid));
}
/// <summary>
@@ -2350,7 +2351,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// </remarks>
public static unsafe string GetJoystickGUID(int jid)
{
return Marshal.PtrToStringUTF8((IntPtr) glfwGetJoystickGUID(jid));
return PtrToStringUTF8(glfwGetJoystickGUID(jid));
}
/// <summary>
@@ -2508,7 +2509,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// </remarks>
public static unsafe bool UpdateGamepadMappings(string newMapping)
{
var ptr = Marshal.StringToCoTaskMemUTF8(newMapping);
var ptr = StringToCoTaskMemUTF8(newMapping);
try
{
return glfwUpdateGamepadMappings((byte*)ptr) == GLFW_TRUE;
@@ -2584,7 +2585,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// </remarks>
public static unsafe string GetGamepadName(int jid)
{
return Marshal.PtrToStringUTF8((IntPtr) glfwGetGamepadName(jid));
return PtrToStringUTF8(glfwGetGamepadName(jid));
}
/// <summary>
@@ -2853,7 +2854,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// </remarks>
public static unsafe bool ExtensionSupported(string extensionName)
{
var ptr = Marshal.StringToCoTaskMemUTF8(extensionName);
var ptr = StringToCoTaskMemUTF8(extensionName);
try
{
@@ -2892,7 +2893,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// <seealso cref="ExtensionSupported" />
public static unsafe IntPtr GetProcAddress(string procName)
{
var ptr = Marshal.StringToCoTaskMemUTF8(procName);
var ptr = StringToCoTaskMemUTF8(procName);
try
{
@@ -3084,7 +3085,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// </remarks>
public static unsafe Window* CreateWindow(int width, int height, string title, Monitor* monitor, Window* share)
{
var ptr = Marshal.StringToCoTaskMemUTF8(title);
var ptr = StringToCoTaskMemUTF8(title);
try
{
@@ -3305,7 +3306,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// <seealso cref="SetClipboardString"/>
public static unsafe string GetClipboardString(Window* window)
{
return Marshal.PtrToStringUTF8((IntPtr) glfwGetClipboardString(window));
return PtrToStringUTF8(glfwGetClipboardString(window));
}
/// <summary>
@@ -3916,7 +3917,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// <seealso cref="GetClipboardString"/>
public static unsafe void SetClipboardString(Window* window, string data)
{
var ptr = Marshal.StringToCoTaskMemUTF8(data);
var ptr = StringToCoTaskMemUTF8(data);
try
{
@@ -4750,7 +4751,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// </remarks>
public static unsafe void SetWindowTitle(Window* window, string title)
{
var ptr = Marshal.StringToCoTaskMemUTF8(title);
var ptr = StringToCoTaskMemUTF8(title);
try
{
@@ -5339,7 +5340,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
var array = new string[count];
for (var i = 0; i < count; i++)
{
array[i] = Marshal.PtrToStringUTF8((IntPtr) ptr[i]);
array[i] = PtrToStringUTF8(ptr[i]);
}
return array;
@@ -5385,7 +5386,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
/// <returns>The address of the function, or <c>null</c> if an error occurred.</returns>
public static unsafe IntPtr GetInstanceProcAddress(VkHandle instance, string procName)
{
var ptr = Marshal.StringToCoTaskMemUTF8(procName);
var ptr = StringToCoTaskMemUTF8(procName);
try
{

View File

@@ -61,5 +61,18 @@ namespace OpenToolkit.GraphicsLibraryFramework
: base(message, innerException)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="GLFWException"/> class with the specified context
/// and the serialization information.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/> associated with this exception.</param>
/// <param name="context">
/// A <see cref="StreamingContext"/> that represents the context of this exception.
/// </param>
protected GLFWException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}

View File

@@ -25,7 +25,7 @@ namespace OpenToolkit.GraphicsLibraryFramework
}
string rName = null;
if (OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD()) rName = "libglfw.so.3";
if (OperatingSystem.IsLinux()) rName = "libglfw.so.3";
else if (OperatingSystem.IsMacOS()) rName = "libglfw.3.dylib";
if ((rName != null) && NativeLibrary.TryLoad(rName, assembly, path, out var handle))

View File

@@ -1,9 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\MSBuild\Robust.Properties.targets" />
<PropertyGroup>
<!-- Work around https://github.com/dotnet/project-system/issues/4314 -->
<TargetFramework>$(TargetFramework)</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>9.0</LangVersion>
<SkipRobustAnalyzer>true</SkipRobustAnalyzer>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<Import Project="..\MSBuild\Robust.Properties.targets" />
<Import Project="..\MSBuild\Robust.DefineConstants.targets" />
<ItemGroup>
<PackageReference Condition="'$(TargetFramework)' == 'net472'" Include="System.Memory" Version="4.5.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Robust.Shared\Robust.Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -18,7 +18,7 @@ We are happy to accept contributions from anybody. Get in Discord or IRC if you
## Building
This repository is the **engine** part of SS14. It's the base engine all SS14 servers will be built on. As such, it does not start on its own: it needs the [content repo](https://github.com/space-wizards/space-station-14). Think of Robust Toolbox as BYOND in the context of Space Station 13.
This repository is the **engine** part of SS14. It's the base engine all SS14 servers will be built on. As such, it does not start on its own: it needs the [content repo](https://github.com/space-wizards/space-station-14). Think of Robust Toolbox as BYOND in the context of Spacestation 13.
## Legal Info

File diff suppressed because it is too large Load Diff

View File

@@ -1546,31 +1546,6 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
- name: FastNoise
license: |
MIT License
Copyright(c) 2020 Jordan Peck (jordan.me2@gmail.com)
Copyright(c) 2020 Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
- name: OpenAL soft
license: |
GNU LIBRARY GENERAL PUBLIC LICENSE

View File

@@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,5 +0,0 @@
- type: entity
id: Audio
name: Audio
description: Audio entity used by engine
save: false

File diff suppressed because it is too large Load Diff

View File

@@ -1,34 +0,0 @@
- type: entity
id: debugRotation
abstract: true
categories: [ debug ]
components:
- type: Sprite
netsync: false
visible: true
sprite: debugRotation.rsi
state: direction1
- type: entity
id: debugRotation1
parent: debugRotation
name: dbg_rotation1
components:
- type: Sprite
state: direction1
- type: entity
id: debugRotation4
parent: debugRotation
name: dbg_rotation4
components:
- type: Sprite
state: direction4
- type: entity
id: debugRotationTex
parent: debugRotation
name: dbg_rotationTex
components:
- type: Sprite
state: direction1

View File

@@ -1,44 +0,0 @@
- type: uiTheme
id: Default
path: /Textures/Interface/Default/
colors:
# Root
rootBackground: "#000000"
# Windows
windowBackground: "#111111"
windowBorder: "#444444"
windowHeader: "#001e3d"
windowCloseButton: "#FFFFFF"
windowCloseButtonHover: "#FF7F7F"
windowCloseButtonPressed: "#FF0000"
# Scrollbars
scrollBarDefault: "#80808059"
scrollBarHovered: "#8C8C8C59"
scrollBarGrabbed: "#8C8C8C59"
# Buttons
buttonBackground: "#171717"
buttonBackgroundHovered: "#272727"
buttonBackgroundPressed: "#173717"
buttonBorder: "#444444"
buttonBorderHovered: "#444444"
buttonBorderPressed: "#447044"
buttonBackgroundDisabled: "#333333"
buttonBorderDisabled: "#222222"
# LineEdit
lineEditUneditableText: "#444444"
lineEditPlaceholderText: "#7d7d7d"
lineEditBackground: "#000000"
lineEditBorder: "#444444"
# TabContainer
tabContainerBackground: "#000000"
tabContainerBorder: "#444444"
tabContainerActiveTabBackground: "#173717"
tabContainerActiveTabBorder: "#447044"
tabContainerInactiveTabBackground: "#171717"
tabContainerInactiveTabBorder: "#444444"

View File

@@ -1,17 +0,0 @@
# debug related entities
- type: entityCategory
id: debug
name: entity-category-name-debug
description: entity-category-desc-debug
# entities that spawn other entities
- type: entityCategory
id: spawner
name: entity-category-name-spawner
description: entity-category-desc-spawner
# entities that should be hidden from the spawn menu
- type: entityCategory
id: hideSpawnMenu
name: entity-category-name-hide
description: entity-category-desc-hide

View File

@@ -1,63 +0,0 @@
# Used internally by the THE() function.
zzzz-the = { PROPER($ent) ->
*[false] the { $ent }
[true] { $ent }
}
# Used internally by the SUBJECT() function.
zzzz-subject-pronoun = { GENDER($ent) ->
[male] he
[female] she
[epicene] they
*[neuter] it
}
# Used internally by the OBJECT() function.
zzzz-object-pronoun = { GENDER($ent) ->
[male] him
[female] her
[epicene] them
*[neuter] it
}
# Used internally by the POSS-PRONOUN() function.
zzzz-possessive-pronoun = { GENDER($ent) ->
[male] his
[female] hers
[epicene] theirs
*[neuter] its
}
# Used internally by the POSS-ADJ() function.
zzzz-possessive-adjective = { GENDER($ent) ->
[male] his
[female] her
[epicene] their
*[neuter] its
}
# Used internally by the REFLEXIVE() function.
zzzz-reflexive-pronoun = { GENDER($ent) ->
[male] himself
[female] herself
[epicene] themselves
*[neuter] itself
}
# Used internally by the CONJUGATE-BE() function.
zzzz-conjugate-be = { GENDER($ent) ->
[epicene] are
*[other] is
}
# Used internally by the CONJUGATE-HAVE() function.
zzzz-conjugate-have = { GENDER($ent) ->
[epicene] have
*[other] has
}
# Used internally by the CONJUGATE-BASIC() function.
zzzz-conjugate-basic = { GENDER($ent) ->
[epicene] { $first }
*[other] { $second }
}

View File

@@ -1,16 +0,0 @@
# Loc strings for various entity state & client-side PVS related commands
cmd-reset-ent-help = Usage: resetent <Entity UID>
cmd-reset-ent-desc = Reset an entity to the most recently received server state. This will also reset entities that have been detached to null-space.
cmd-reset-all-ents-help = Usage: resetallents
cmd-reset-all-ents-desc = Resets all entities to the most recently received server state. This only impacts entities that have not been detached to null-space.
cmd-detach-ent-help = Usage: detachent <Entity UID>
cmd-detach-ent-desc = Detach an entity to null-space, as if it had left PVS range.
cmd-local-delete-help = Usage: localdelete <Entity UID>
cmd-local-delete-desc = Deletes an entity. Unlike the normal delete command, this is CLIENT-SIDE. Unless the entity is a client-side entity, this will likely cause errors.
cmd-full-state-reset-help = Usage: fullstatereset
cmd-full-state-reset-desc = Discards any entity state information and requests a full-state from the server.

View File

@@ -1,568 +0,0 @@
### Localization for engine console commands
## generic command errors
cmd-invalid-arg-number-error = Invalid number of arguments.
cmd-parse-failure-integer = {$arg} is not a valid integer.
cmd-parse-failure-float = {$arg} is not a valid float.
cmd-parse-failure-bool = {$arg} is not a valid bool.
cmd-parse-failure-uid = {$arg} is not a valid entity UID.
cmd-parse-failure-mapid = {$arg} is not a valid MapId.
cmd-parse-failure-grid = {$arg} is not a valid grid.
cmd-parse-failure-entity-exist = UID {$arg} does not correspond to an existing entity.
cmd-error-file-not-found = Could not find file: {$file}.
cmd-error-dir-not-found = Could not find directory: {$dir}.
cmd-failure-no-attached-entity = There is no entity attached to this shell.
## 'help' command
cmd-help-desc = Display general help or help text for a specific command
cmd-help-help = Usage: help [command name]
When no command name is provided, displays general-purpose help text. If a command name is provided, displays help text for that command.
cmd-help-no-args = To display help for a specific command, write 'help <command>'. To list all available commands, write 'list'. To search for commands, use 'list <filter>'.
cmd-help-unknown = Unknown command: { $command }
cmd-help-top = { $command } - { $description }
cmd-help-invalid-args = Invalid amount of arguments.
cmd-help-arg-cmdname = [command name]
## 'cvar' command
cmd-cvar-desc = Gets or sets a CVar.
cmd-cvar-help = Usage: cvar <name | ?> [value]
If a value is passed, the value is parsed and stored as the new value of the CVar.
If not, the current value of the CVar is displayed.
Use 'cvar ?' to get a list of all registered CVars.
cmd-cvar-invalid-args = Must provide exactly one or two arguments.
cmd-cvar-not-registered = CVar '{ $cvar }' is not registered. Use 'cvar ?' to get a list of all registered CVars.
cmd-cvar-parse-error = Input value is in incorrect format for type { $type }
cmd-cvar-compl-list = List available CVars
cmd-cvar-arg-name = <name | ?>
cmd-cvar-value-hidden = <value hidden>
## 'list' command
cmd-list-desc = Lists available commands, with optional search filter
cmd-list-help = Usage: list [filter]
Lists all available commands. If an argument is provided, it will be used to filter commands by name.
cmd-list-heading = SIDE NAME DESC{"\u000A"}-------------------------{"\u000A"}
cmd-list-arg-filter = [filter]
## '>' command, aka remote exec
cmd-remoteexec-desc = Executes server-side commands
cmd-remoteexec-help = Usage: > <command> [arg] [arg] [arg...]
Executes a command on the server. This is necessary if a command with the same name exists on the client, as simply running the command would run the client command first.
## 'gc' command
cmd-gc-desc = Run the GC (Garbage Collector)
cmd-gc-help = Usage: gc [generation]
Uses GC.Collect() to execute the Garbage Collector.
If an argument is provided, it is parsed as a GC generation number and GC.Collect(int) is used.
Use the 'gfc' command to do an LOH-compacting full GC.
cmd-gc-failed-parse = Failed to parse argument.
cmd-gc-arg-generation = [generation]
## 'gcf' command
cmd-gcf-desc = Run the GC, fully, compacting LOH and everything.
cmd-gcf-help = Usage: gcf
Does a full GC.Collect(2, GCCollectionMode.Forced, true, true) while also compacting LOH.
This will probably lock up for hundreds of milliseconds, be warned.
## 'gc_mode' command
cmd-gc_mode-desc = Change/Read the GC Latency mode
cmd-gc_mode-help = Usage: gc_mode [type]
If no argument is provided, returns the current GC latency mode.
If an argument is passed, it is parsed as GCLatencyMode and set as the GC latency mode.
cmd-gc_mode-current = current gc latency mode: { $prevMode }
cmd-gc_mode-possible = possible modes:
cmd-gc_mode-option = - { $mode }
cmd-gc_mode-unknown = unknown gc latency mode: { $arg }
cmd-gc_mode-attempt = attempting gc latency mode change: { $prevMode } -> { $mode }
cmd-gc_mode-result = resulting gc latency mode: { $mode }
cmd-gc_mode-arg-type = [type]
## 'mem' command
cmd-mem-desc = Prints managed memory info
cmd-mem-help = Usage: mem
cmd-mem-report = Heap Size: { TOSTRING($heapSize, "N0") }
Total Allocated: { TOSTRING($totalAllocated, "N0") }
## 'physics' command
cmd-physics-overlay = {$overlay} is not a recognised overlay
## 'lsasm' command
cmd-lsasm-desc = Lists loaded assemblies by load context
cmd-lsasm-help = Usage: lsasm
## 'exec' command
cmd-exec-desc = Executes a script file from the game's writeable user data
cmd-exec-help = Usage: exec <fileName>
Each line in the file is executed as a single command, unless it starts with a #
cmd-exec-arg-filename = <fileName>
## 'dump_net_comps' command
cmd-dump_net_comps-desc = Prints the table of networked components.
cmd-dump_net_comps-help = Usage: dump_net-comps
cmd-dump_net_comps-error-writeable = Registration still writeable, network ids have not been generated.
cmd-dump_net_comps-header = Networked Component Registrations:
## 'dump_event_tables' command
cmd-dump_event_tables-desc = Prints directed event tables for an entity.
cmd-dump_event_tables-help = Usage: dump_event_tables <entityUid>
cmd-dump_event_tables-missing-arg-entity = Missing entity argument
cmd-dump_event_tables-error-entity = Invalid entity
cmd-dump_event_tables-arg-entity = <entityUid>
## 'monitor' command
cmd-monitor-desc = Toggles a debug monitor in the F3 menu.
cmd-monitor-help = Usage: monitor <name>
Possible monitors are: { $monitors }
You can also use the special values "-all" and "+all" to hide or show all monitors, respectively.
cmd-monitor-arg-monitor = <monitor>
cmd-monitor-invalid-name = Invalid monitor name
cmd-monitor-arg-count = Missing monitor argument
cmd-monitor-minus-all-hint = Hides all monitors
cmd-monitor-plus-all-hint = Shows all monitors
## 'setambientlight' command
cmd-set-ambient-light-desc = Allows you to set the ambient light for the specified map, in SRGB.
cmd-set-ambient-light-help = setambientlight [mapid] [r g b a]
cmd-set-ambient-light-parse = Unable to parse args as a byte values for a color.
## Mapping commands
cmd-savemap-desc = Serializes a map to disk. Will not save a post-init map unless forced.
cmd-savemap-help = savemap <MapID> <Path> [force]
cmd-savemap-not-exist = Target map does not exist.
cmd-savemap-init-warning = Attempted to save a post-init map without forcing the save.
cmd-savemap-attempt = Attempting to save map {$mapId} to {$path}.
cmd-savemap-success = Map successfully saved.
cmd-hint-savemap-id = <MapID>
cmd-hint-savemap-path = <Path>
cmd-hint-savemap-force = [bool]
cmd-loadmap-desc = Loads a map from disk into the game.
cmd-loadmap-help = loadmap <MapID> <Path> [x] [y] [rotation] [consistentUids]
cmd-loadmap-nullspace = You cannot load into map 0.
cmd-loadmap-exists = Map {$mapId} already exists.
cmd-loadmap-success = Map {$mapId} has been loaded from {$path}.
cmd-loadmap-error = An error occurred while loading map from {$path}.
cmd-hint-loadmap-x-position = [x-position]
cmd-hint-loadmap-y-position = [y-position]
cmd-hint-loadmap-rotation = [rotation]
cmd-hint-loadmap-uids = [float]
cmd-hint-savebp-id = <Grid EntityID>
## 'flushcookies' command
# Note: the flushcookies command is from Robust.Client.WebView, it's not in the main engine code.
cmd-flushcookies-desc = Flush CEF cookie storage to disk
cmd-flushcookies-help = This ensure cookies are properly saved to disk in the event of unclean shutdowns.
Note that the actual operation is asynchronous.
cmd-ldrsc-desc = Pre-caches a resource.
cmd-ldrsc-help = Usage: ldrsc <path> <type>
cmd-rldrsc-desc = Reloads a resource.
cmd-rldrsc-help = Usage: rldrsc <path> <type>
cmd-gridtc-desc = Gets the tile count of a grid.
cmd-gridtc-help = Usage: gridtc <gridId>
# Client-side commands
cmd-guidump-desc = Dump GUI tree to /guidump.txt in user data.
cmd-guidump-help = Usage: guidump
cmd-uitest-desc = Open a dummy UI testing window
cmd-uitest-help = Usage: uitest
## 'uitest2' command
cmd-uitest2-desc = Opens a UI control testing OS window
cmd-uitest2-help = Usage: uitest2 <tab>
cmd-uitest2-arg-tab = <tab>
cmd-uitest2-error-args = Expected at most one argument
cmd-uitest2-error-tab = Invalid tab: '{$value}'
cmd-uitest2-title = UITest2
cmd-setclipboard-desc = Sets the system clipboard
cmd-setclipboard-help = Usage: setclipboard <text>
cmd-getclipboard-desc = Gets the system clipboard
cmd-getclipboard-help = Usage: Getclipboard
cmd-togglelight-desc = Toggles light rendering.
cmd-togglelight-help = Usage: togglelight
cmd-togglefov-desc = Toggles fov for client.
cmd-togglefov-help = Usage: togglefov
cmd-togglehardfov-desc = Toggles hard fov for client. (for debugging space-station-14#2353)
cmd-togglehardfov-help = Usage: togglehardfov
cmd-toggleshadows-desc = Toggles shadow rendering.
cmd-toggleshadows-help = Usage: toggleshadows
cmd-togglelightbuf-desc = Toggles lighting rendering. This includes shadows but not FOV.
cmd-togglelightbuf-help = Usage: togglelightbuf
cmd-chunkinfo-desc = Gets info about a chunk under your mouse cursor.
cmd-chunkinfo-help = Usage: chunkinfo
cmd-rldshader-desc = Reloads all shaders.
cmd-rldshader-help = Usage: rldshader
cmd-cldbglyr-desc = Toggle fov and light debug layers.
cmd-cldbglyr-help= Usage: cldbglyr <layer>: Toggle <layer>
cldbglyr: Turn all Layers off
cmd-key-info-desc = Keys key info for a key.
cmd-key-info-help = Usage: keyinfo <Key>
## 'bind' command
cmd-bind-desc = Binds an input key combination to an input command.
cmd-bind-help = Usage: bind { cmd-bind-arg-key } { cmd-bind-arg-mode } { cmd-bind-arg-command }
Note that this DOES NOT automatically save bindings.
Use the 'svbind' command to save binding configuration.
cmd-bind-arg-key = <KeyName>
cmd-bind-arg-mode = <BindMode>
cmd-bind-arg-command = <InputCommand>
cmd-net-draw-interp-desc = Toggles the debug drawing of the network interpolation.
cmd-net-draw-interp-help = Usage: net_draw_interp
cmd-net-draw-interp-desc = Toggles the debug drawing of the network interpolation.
cmd-net-draw-interp-help = Usage: net_draw_interp
cmd-net-watch-ent-desc = Dumps all network updates for an EntityId to the console.
cmd-net-watch-ent-help = Usage: net_watchent <0|EntityUid>
cmd-net-refresh-desc = Requests a full server state.
cmd-net-refresh-help = Usage: net_refresh
cmd-net-entity-report-desc = Toggles the net entity report panel.
cmd-net-entity-report-help = Usage: net_entityreport
cmd-fill-desc = Fill up the console for debugging.
cmd-fill-help = Fills the console with some nonsense for debugging.
cmd-cls-desc = Clears the console.
cmd-cls-help = Clears the debug console of all messages.
cmd-sendgarbage-desc = Sends garbage to the server.
cmd-sendgarbage-help = The server will reply with 'no u'
cmd-loadgrid-desc = Loads a grid from a file into an existing map.
cmd-loadgrid-help = loadgrid <MapID> <Path> [x y] [rotation] [storeUids]
cmd-loc-desc = Prints the absolute location of the player's entity to console.
cmd-loc-help = loc
cmd-tpgrid-desc = Teleports a grid to a new location.
cmd-tpgrid-help = tpgrid <gridId> <X> <Y> [<MapId>]
cmd-rmgrid-desc = Removes a grid from a map. You cannot remove the default grid.
cmd-rmgrid-help = rmgrid <gridId>
cmd-mapinit-desc = Runs map init on a map.
cmd-mapinit-help = mapinit <mapID>
cmd-lsmap-desc = Lists maps.
cmd-lsmap-help = lsmap
cmd-lsgrid-desc = Lists grids.
cmd-lsgrid-help = lsgrid
cmd-addmap-desc = Adds a new empty map to the round. If the mapID already exists, this command does nothing.
cmd-addmap-help = addmap <mapID> [initialize]
cmd-rmmap-desc = Removes a map from the world. You cannot remove nullspace.
cmd-rmmap-help = rmmap <mapId>
cmd-savegrid-desc = Serializes a grid to disk.
cmd-savegrid-help = savegrid <gridID> <Path>
cmd-testbed-desc = Loads a physics testbed on the specified map.
cmd-testbed-help = testbed <mapid> <test>
cmd-saveconfig-desc = Saves the client configuration to the config file.
cmd-saveconfig-help = saveconfig
## 'flushcookies' command
# Note: the flushcookies command is from Robust.Client.WebView, it's not in the main engine code.
cmd-flushcookies-desc = Flush CEF cookie storage to disk
cmd-flushcookies-help = This ensure cookies are properly saved to disk in the event of unclean shutdowns.
Note that the actual operation is asynchronous.
## 'addcomp' command
cmd-addcomp-desc = Adds a component to an entity.
cmd-addcomp-help = addcomp <uid> <componentName>
cmd-addcompc-desc = Adds a component to an entity on the client.
cmd-addcompc-help = addcompc <uid> <componentName>
## 'rmcomp' command
cmd-rmcomp-desc = Removes a component from an entity.
cmd-rmcomp-help = rmcomp <uid> <componentName>
cmd-rmcompc-desc = Removes a component from an entity on the client.
cmd-rmcompc-help = rmcomp <uid> <componentName>
## 'addview' command
cmd-addview-desc = Allows you to subscribe to an entity's view for debugging purposes.
cmd-addview-help = addview <entityUid>
cmd-addviewc-desc = Allows you to subscribe to an entity's view for debugging purposes.
cmd-addviewc-help = addview <entityUid>
## 'removeview' command
cmd-removeview-desc = Allows you to unsubscribe to an entity's view for debugging purposes.
cmd-removeview-help = removeview <entityUid>
## 'loglevel' command
cmd-loglevel-desc = Changes the log level for a provided sawmill.
cmd-loglevel-help = Usage: loglevel <sawmill> <level>
sawmill: A label prefixing log messages. This is the one you're setting the level for.
level: The log level. Must match one of the values of the LogLevel enum.
cmd-testlog-desc = Writes a test log to a sawmill.
cmd-testlog-help = Usage: testlog <sawmill> <level> <message>
sawmill: A label prefixing the logged message.
level: The log level. Must match one of the values of the LogLevel enum.
message: The message to be logged. Wrap this in double quotes if you want to use spaces.
## 'vv' command
cmd-vv-desc = Opens View Variables.
cmd-vv-help = Usage: vv <entity ID|IoC interface name|SIoC interface name>
## 'showvelocities' command
cmd-showvelocities-desc = Displays your angular and linear velocities.
cmd-showvelocities-help = Usage: showvelocities
## 'setinputcontext' command
cmd-setinputcontext-desc = Sets the active input context.
cmd-setinputcontext-help = Usage: setinputcontext <context>
## 'forall' command
cmd-forall-desc = Runs a command over all entities with a given component.
cmd-forall-help = Usage: forall <bql query> do <command...>
## 'delete' command
cmd-delete-desc = Deletes the entity with the specified ID.
cmd-delete-help = delete <entity UID>
# System commands
cmd-showtime-desc = Shows the server time.
cmd-showtime-help = showtime
cmd-restart-desc = Gracefully restarts the server (not just the round).
cmd-restart-help = restart
cmd-shutdown-desc = Gracefully shuts down the server.
cmd-shutdown-help = shutdown
cmd-saveconfig-desc = Saves the server configuration to the config file.
cmd-saveconfig-help = saveconfig
cmd-netaudit-desc = Prints into about NetMsg security.
cmd-netaudit-help = netaudit
# Player commands
cmd-tp-desc = Teleports a player to any location in the round.
cmd-tp-help = tp <x> <y> [<mapID>]
cmd-tpto-desc = Teleports the current player or the specified players/entities to the location of the first player/entity.
cmd-tpto-help = tpto <username|uid> [username|uid]...
cmd-tpto-destination-hint = destination (uid or username)
cmd-tpto-victim-hint = entity to teleport (uid or username)
cmd-tpto-parse-error = Cant resolve entity or player: {$str}
cmd-listplayers-desc = Lists all players currently connected.
cmd-listplayers-help = listplayers
cmd-kick-desc = Kicks a connected player out of the server, disconnecting them.
cmd-kick-help = kick <PlayerIndex> [<Reason>]
# Spin command
cmd-spin-desc = Causes an entity to spin. Default entity is the attached player's parent.
cmd-spin-help = spin velocity [drag] [entityUid]
# Localization command
cmd-rldloc-desc = Reloads localization (client & server).
cmd-rldloc-help = Usage: rldloc
# Debug entity controls
cmd-spawn-desc = Spawns an entity with specific type.
cmd-spawn-help = spawn <prototype> OR spawn <prototype> <relative entity ID> OR spawn <prototype> <x> <y>
cmd-cspawn-desc = Spawns a client-side entity with specific type at your feet.
cmd-cspawn-help = cspawn <entity type>
cmd-scale-desc = Increases or decreases an entity's size naively.
cmd-scale-help = scale <entityUid> <float>
cmd-dumpentities-desc = Dump entity list.
cmd-dumpentities-help = Dumps entity list of UIDs and prototype.
cmd-getcomponentregistration-desc = Gets component registration information.
cmd-getcomponentregistration-help = Usage: getcomponentregistration <componentName>
cmd-showrays-desc = Toggles debug drawing of physics rays. An integer for <raylifetime> must be provided.
cmd-showrays-help = Usage: showrays <raylifetime>
cmd-disconnect-desc = Immediately disconnect from the server and go back to the main menu.
cmd-disconnect-help = Usage: disconnect
cmd-entfo-desc = Displays verbose diagnostics for an entity.
cmd-entfo-help = Usage: entfo <entityuid>
The entity UID can be prefixed with 'c' to convert it to a client entity UID.
cmd-fuck-desc = Throws an exception
cmd-fuck-help = Throws an exception
cmd-showpos-desc = Enables debug drawing over all entity positions in the game.
cmd-showpos-help = Usage: showpos
cmd-sggcell-desc = Lists entities on a snap grid cell.
cmd-sggcell-help = Usage: sggcell <gridID> <vector2i>\nThat vector2i param is in the form x<int>,y<int>.
cmd-overrideplayername-desc = Changes the name used when attempting to connect to the server.
cmd-overrideplayername-help = Usage: overrideplayername <name>
cmd-showanchored-desc = Shows anchored entities on a particular tile
cmd-showanchored-help = Usage: showanchored
cmd-dmetamem-desc = Dumps a type's members in a format suitable for the sandbox configuration file.
cmd-dmetamem-help = Usage: dmetamem <type>
cmd-dmetamem-desc = Displays chunk bounds for the purposes of rendering.
cmd-dmetamem-help = Usage: showchunkbb <type>
cmd-launchauth-desc = Load authentication tokens from launcher data to aid in testing of live servers.
cmd-launchauth-help = Usage: launchauth <account name>
cmd-lightbb-desc = Toggles whether to show light bounding boxes.
cmd-lightbb-help = Usage: lightbb
cmd-monitorinfo-desc = Monitors info
cmd-monitorinfo-help = Usage: monitorinfo <id>
cmd-setmonitor-desc = Set monitor
cmd-setmonitor-help = Usage: setmonitor <id>
cmd-physics-desc = Shows a debug physics overlay. The arg supplied specifies the overlay.
cmd-physics-help = Usage: physics <aabbs / com / contactnormals / contactpoints / distance / joints / shapeinfo / shapes>
cmd-hardquit-desc = Kills the game client instantly.
cmd-hardquit-help = Kills the game client instantly, leaving no traces. No telling the server goodbye.
cmd-quit-desc = Shuts down the game client gracefully.
cmd-quit-help = Properly shuts down the game client, notifying the connected server and such.
cmd-csi-desc = Opens a C# interactive console.
cmd-csi-help = Usage: csi
cmd-scsi-desc = Opens a C# interactive console on the server.
cmd-scsi-help = Usage: scsi
cmd-watch-desc = Opens a variable watch window.
cmd-watch-help = Usage: watch
cmd-showspritebb-desc = Toggle whether sprite bounds are shown
cmd-showspritebb-help = Usage: showspritebb
cmd-togglelookup-desc = Shows / hides entitylookup bounds via an overlay.
cmd-togglelookup-help = Usage: togglelookup
cmd-net_entityreport-desc = Toggles the net entity report panel.
cmd-net_entityreport-help = Usage: net_entityreport
cmd-net_refresh-desc = Requests a full server state.
cmd-net_refresh-help = Usage: net_refresh
cmd-net_graph-desc = Toggles the net statistics pannel.
cmd-net_graph-help = Usage: net_graph
cmd-net_watchent-desc = Dumps all network updates for an EntityId to the console.
cmd-net_watchent-help = Usage: net_watchent <0|EntityUid>
cmd-net_draw_interp-desc = Toggles the debug drawing of the network interpolation.
cmd-net_draw_interp-help = Usage: net_draw_interp <0|EntityUid>
cmd-vram-desc = Displays video memory usage statics by the game.
cmd-vram-help = Usage: vram
cmd-showislands-desc = Shows the current physics bodies involved in each physics island.
cmd-showislands-help = Usage: showislands
cmd-showgridnodes-desc = Shows the nodes for grid split purposes.
cmd-showgridnodes-help = Usage: showgridnodes
cmd-profsnap-desc = Make a profiling snapshot.
cmd-profsnap-help = Usage: profsnap
cmd-devwindow-desc = Dev Window
cmd-devwindow-help = Usage: devwindow
cmd-devwindow-desc = Open file
cmd-devwindow-help = Usage: testopenfile
cmd-scene-desc = Immediately changes the UI scene/state.
cmd-scene-help = Usage: scene <className>
cmd-szr_stats-desc = Report serializer statistics.
cmd-szr_stats-help = Usage: szr_stats
cmd-hwid-desc = Returns the current HWID (HardWare ID).
cmd-hwid-help = Usage: hwid
cmd-vvread-desc = Retrieve a path's value using VV (View Variables).
cmd-vvread-desc = Usage: vvread <path>
cmd-vvwrite-desc = Modify a path's value using VV (View Variables).
cmd-vvwrite-help = Usage: vvwrite <path>
cmd-vv-desc = Opens View Variables (VV).
cmd-vv-help = Usage: vv <path|entity ID|guihover>
cmd-vvinvoke-desc = Invoke/Call a path with arguments using VV.
cmd-vvinvoke-help = Usage: vvinvoke <path> [arguments...]
cmd-dump_dependency_injectors-desc = Dump IoCManager's dependency injector cache.
cmd-dump_dependency_injectors-help = Usage: dump_dependency_injectors
cmd-dump_dependency_injectors-total-count = Total count: { $total }
cmd-dump_netserializer_type_map-desc = Dump NetSerializer's type map and serializer hash.
cmd-dump_netserializer_type_map-help = Usage: dump_netserializer_type_map
cmd-hub_advertise_now-desc = Immediately advertise to the master hub server
cmd-hub_advertise_now-help = Usage: hub_advertise_now
cmd-echo-desc = Echo arguments back to the console
cmd-echo-help = Usage: echo "<message>"
## 'vfs_ls' command
cmd-vfs_ls-desc = List directory contents in the VFS.
cmd-vfs_ls-help = Usage: vfs_list <path>
Example:
vfs_list /Assemblies
cmd-vfs_ls-err-args = Need exactly 1 argument.
cmd-vfs_ls-hint-path = <path>
cmd-reloadtiletextures-desc = Reloads the tile texture atlas to allow hot reloading tile sprites
cmd-reloadtiletextures-help = Usage: reloadtiletextures
cmd-audio_length-desc = Shows the length of an audio file
cmd-audio_length-help = Usage: audio_length { cmd-audio_length-arg-file-name }
cmd-audio_length-arg-file-name = <file name>

View File

@@ -1,10 +0,0 @@
color-selector-sliders-red = R
color-selector-sliders-green = G
color-selector-sliders-blue = B
color-selector-sliders-hue = H
color-selector-sliders-saturation = S
color-selector-sliders-value = V
color-selector-sliders-alpha = A
color-selector-sliders-rgb = RGB
color-selector-sliders-hsv = HSV

View File

@@ -3,7 +3,6 @@
entity-spawn-window-title = Entity Spawn Panel
entity-spawn-window-search-bar-placeholder = search
entity-spawn-window-clear-button = Clear
entity-spawn-window-replace-button-text = Replace
entity-spawn-window-erase-button-text = Erase Mode
entity-spawn-window-override-menu-tooltip = Override placement

View File

@@ -1,3 +0,0 @@
debug-builtin-connection-screen-invalid-username-with-reason = The given username is invalid: {$invalidreason}
debug-builtin-connection-screen-invalid-username = Invalid Username.
debug-builtin-connection-screen-failed-to-connect = Failed to connect: {$reason}

View File

@@ -1,5 +0,0 @@
discord-rpc-in-main-menu = In Main Menu
discord-rpc-in-main-menu-logo-text = I think coolsville SUCKS
discord-rpc-character = Username: {$username}
discord-rpc-on-server = On Server: {$servername}
discord-rpc-players = Players: {$players}/{$maxplayers}

View File

@@ -1,8 +0,0 @@
entity-category-name-debug = Debug
entity-category-desc-debug = Entity prototypes intended for debugging & testing.
entity-category-name-spawner = Spawner
entity-category-desc-spawner = Entity prototypes that spawn other entities.
entity-category-name-hide = Hidden
entity-category-desc-hide = Entity prototypes that should be hidden from the spawn menu

View File

@@ -18,15 +18,6 @@ input-key-F12 = F12
input-key-F13 = F13
input-key-F14 = F14
input-key-F15 = F15
input-key-F16 = F16
input-key-F17 = F17
input-key-F18 = F18
input-key-F19 = F19
input-key-F20 = F20
input-key-F21 = F21
input-key-F22 = F22
input-key-F23 = F23
input-key-F24 = F24
input-key-Pause = Pause
input-key-Left = Left
input-key-Up = Up
@@ -34,22 +25,7 @@ input-key-Down = Down
input-key-Right = Right
input-key-Space = Space
input-key-Return = Return
input-key-NumpadEnter = Numpad Enter
input-key-NumpadNum0 = Numpad 0
input-key-NumpadNum1 = Numpad 1
input-key-NumpadNum2 = Numpad 2
input-key-NumpadNum3 = Numpad 3
input-key-NumpadNum4 = Numpad 4
input-key-NumpadNum5 = Numpad 5
input-key-NumpadNum6 = Numpad 6
input-key-NumpadNum7 = Numpad 7
input-key-NumpadNum8 = Numpad 8
input-key-NumpadNum9 = Numpad 9
input-key-NumpadAdd = Numpad Add
input-key-NumpadSubtract = Numpad Subtract
input-key-NumpadDivide = Numpad Divide
input-key-NumpadMultiply = Numpad Multiply
input-key-NumpadDecimal = Numpad Decimal
input-key-NumpadEnter = Num Enter
input-key-BackSpace = Backspace
input-key-Tab = Tab
input-key-PageUp = Page Up

View File

@@ -1 +0,0 @@
cmd-midipanic-desc = Turns off every note for every active MIDI renderer.

View File

@@ -1,8 +0,0 @@
cmd-merge_grids-desc = Combines 2 grids into 1 grid
cmd-merge_grids-help = merge_grids <gridUid1> <gridUid2> <offsetX> <offsetY> [angle]
cmd-merge_grids-hintA = Grid A
cmd-merge_grids-hintB = Grid B
cmd-merge_grids-xOffset = X offset
cmd-merge_grids-yOffset = Y offset
cmd-merge_grids-angle = [Angle]

View File

@@ -1,59 +0,0 @@
# Playback Commands
cmd-replay-play-desc = Resume replay playback.
cmd-replay-play-help = replay_play
cmd-replay-pause-desc = Pause replay playback
cmd-replay-pause-help = replay_pause
cmd-replay-toggle-desc = Resume or pause replay playback.
cmd-replay-toggle-help = replay_toggle
cmd-replay-stop-desc = Stop and unload a replay.
cmd-replay-stop-help = replay_stop
cmd-replay-load-desc = Load and start a replay.
cmd-replay-load-help = replay_load <replay folder>
cmd-replay-load-hint = Replay folder
cmd-replay-skip-desc = Skip forwards or backwards in time.
cmd-replay-skip-help = replay_skip <tick or timespan>
cmd-replay-skip-hint = Ticks or timespan (HH:MM:SS).
cmd-replay-set-time-desc = Jump forwards or backwards to some specific time.
cmd-replay-set-time-help = replay_set <tick or time>
cmd-replay-set-time-hint = Tick or timespan (HH:MM:SS), starting from
cmd-replay-error-time = "{$time}" is not an integer or timespan.
cmd-replay-error-args = Wrong number of arguments.
cmd-replay-error-no-replay = Not currently playing a replay.
cmd-replay-error-already-loaded = A replay is already loaded.
cmd-replay-error-run-level = You cannot load a replay while connected to a server.
# Recording commands
cmd-replay-recording-start-desc = Starts a replay recording, optionally with some time limit.
cmd-replay-recording-start-help = Usage: replay_recording_start [name] [overwrite] [time limit]
cmd-replay-recording-start-success = Started recording a replay.
cmd-replay-recording-start-already-recording = Already recording a replay.
cmd-replay-recording-start-error = An error occurred while trying to start the recording.
cmd-replay-recording-start-hint-time = [time limit (minutes)]
cmd-replay-recording-start-hint-name = [name]
cmd-replay-recording-start-hint-overwrite = [overwrite (bool)]
cmd-replay-recording-stop-desc = Stops a replay recording.
cmd-replay-recording-stop-help = Usage: replay_recording_stop
cmd-replay-recording-stop-success = Stopped recording a replay.
cmd-replay-recording-stop-not-recording = Not currently recording a replay.
cmd-replay-recording-stats-desc = Displays information about the current replay recording.
cmd-replay-recording-stats-help = Usage: replay_recording_stats
cmd-replay-recording-stats-result = Duration: {$time} min, Ticks: {$ticks}, Size: {$size} MB, rate: {$rate} MB/min.
# Time Control UI
replay-time-box-scrubbing-label = Dynamic Scrubbing
replay-time-box-replay-time-label = Recording Time: {$current} / {$end} ({$percentage}%)
replay-time-box-server-time-label = Server Time: {$current} / {$end}
replay-time-box-index-label = Index: {$current} / {$total}
replay-time-box-tick-label = Tick: {$current} / {$total}

View File

@@ -1,423 +0,0 @@
command-description-tpto =
Teleport the given entities to some target entity.
command-description-player-list =
Returns a list of all player sessions.
command-description-player-self =
Returns the current player session.
command-description-player-imm =
Returns the session associated with the player given as argument.
command-description-player-entity =
Returns the entities of the input sessions.
command-description-self =
Returns the current attached entity.
command-description-physics-velocity =
Returns the velocity of the input entities.
command-description-physics-angular-velocity =
Returns the angular velocity of the input entities.
command-description-buildinfo =
Provides information about the build of the game.
command-description-cmd-list =
Returns a list of all commands, for this side.
command-description-explain =
Explains the given expression, providing command descriptions and signatures.
command-description-search =
Searches through the input for the provided value.
command-description-stopwatch =
Measures the execution time of the given expression.
command-description-types-consumers =
Provides all commands that can consume the given type.
command-description-types-tree =
Debug tool to return all types the command interpreter can downcast the input to.
command-description-types-gettype =
Returns the type of the input.
command-description-types-fullname =
Returns the full name of the input type according to CoreCLR.
command-description-as =
Casts the input to the given type.
Effectively a type hint if you know the type but the interpreter does not.
command-description-count =
Counts the amount of entries in it's input, returning an integer.
command-description-map =
Maps the input over the given block, with the provided expected return type.
This command may be modified to not need an explicit return type in the future.
command-description-select =
Selects N objects or N% of objects from the input.
One can additionally invert this command with not to make it select everything except N objects instead.
command-description-comp =
Returns the given component from the input entities, discarding entities without that component.
command-description-delete =
Deletes the input entities.
command-description-ent =
Returns the provided entity ID.
command-description-entities =
Returns all entities on the server.
command-description-paused =
Filters the input entities by whether or not they are paused.
This command can be inverted with not.
command-description-with =
Filters the input entities by whether or not they have the given component.
This command can be inverted with not.
command-description-fuck =
Throws an exception.
command-description-ecscomp-listty =
Lists every type of component registered.
command-description-cd =
Changes the session's current directory to the given relative or absolute path.
command-description-ls-here =
Lists the contents of the current directory.
command-description-ls-in =
Lists the contents of the given relative or absolute path.
command-description-methods-get =
Returns all methods associated with the input type.
command-description-methods-overrides =
Returns all methods overriden on the input type.
command-description-methods-overridesfrom =
Returns all methods overriden from the given type on the input type.
command-description-cmd-moo =
Asks the important questions.
command-description-cmd-descloc =
Returns the localization string for a command's description.
command-description-cmd-getshim =
Returns a command's execution shim.
command-description-help =
Provides a quick rundown of how to use toolshed.
command-description-ioc-registered =
Returns all the types registered with IoCManager on the current thread (usually the game thread)
command-description-ioc-get =
Gets an instance of an IoC registration.
command-description-loc-tryloc =
Tries to get a localization string, returning null if unable.
command-description-loc-loc =
Gets a localization string, returning the unlocalized string if unable.
command-description-physics-angular_velocity =
Returns the angular velocity of the given entities.
command-description-vars =
Provides a list of all variables set in this session.
command-description-any =
Returns true if there's any values in the input, otherwise false.
command-description-ArrowCommand =
Assigns the input to a variable.
command-description-isempty =
Returns true if the input is empty, otherwise false.
command-description-isnull =
Returns true if the input is null, otherwise false.
command-description-unique =
Filters the input sequence for uniqueness, removing duplicate values.
command-description-where =
Given some input sequence IEnumerable<T>, takes a block of signature T -> bool that decides if each input value should be included in the output sequence.
command-description-do =
Backwards compatibility with BQL, applies the given old commands over the input sequence.
command-description-named =
Filters the input entities by their name, with the regex ^selector$.
command-description-prototyped =
Filters the input entities by their prototype.
command-description-nearby =
Creates a new list of all entities nearby the inputs within the given range.
command-description-first =
Returns the first entry of the given enumerable.
command-description-splat =
"Splats" a block, value, or variable, creating N copies of it in a list.
command-description-val =
Casts the given value, block, or variable to the given type. This is mostly a workaround for current limitations of variables.
command-description-actor-controlled =
Filters entities by whether or not they're actively controlled.
command-description-actor-session =
Returns the sessions associated with the input entities.
command-description-physics-parent =
Returns the parent(s) of the input entities.
command-description-emplace =
Runs the given block over it's inputs, with the input value placed into the variable $value within the block.
Additionally breaks out $wx, $wy, $proto, $desc, $name, and $paused for entities.
Can also have breakout values for other types, consult the documentation for that type for further info.
command-description-AddCommand =
Performs numeric addition.
command-description-SubtractCommand =
Performs numeric subtraction.
command-description-MultiplyCommand =
Performs numeric multiplication.
command-description-DivideCommand =
Performs numeric division.
command-description-min =
Returns the minimum of two values.
command-description-max =
Returns the maximum of two values.
command-description-BitAndCommand =
Performs bitwise AND.
command-description-BitOrCommand =
Performs bitwise OR.
command-description-BitXorCommand =
Performs bitwise XOR.
command-description-neg =
Negates the input.
command-description-GreaterThanCommand =
Performs a greater-than comparison, x > y.
command-description-LessThanCommand =
Performs a less-than comparison, x < y.
command-description-GreaterThanOrEqualCommand =
Performs a greater-than-or-equal comparison, x >= y.
command-description-LessThanOrEqualCommand =
Performs a less-than-or-equal comparison, x <= y.
command-description-EqualCommand =
Performs an equality comparison, returning true if the inputs are equal.
command-description-NotEqualCommand =
Performs an equality comparison, returning true if the inputs are not equal.
command-description-append =
Appends a value to the input enumerable.
command-description-DefaultIfNullCommand =
Replaces the input with the type's default value if it is null, albeit only for value types (not objects).
command-description-OrValueCommand =
If the input is null, uses the provided alternate value.
command-description-DebugPrintCommand =
Prints the given value transparently, for debug prints in a command run.
command-description-i =
Integer constant.
command-description-f =
Float constant.
command-description-s =
String constant.
command-description-b =
Bool constant.
command-description-join =
Joins two sequences together into one sequence.
command-description-reduce =
Given a block to use as a reducer, turns a sequence into a single value.
The left hand side of the block is implied, and the right hand is stored in $value.
command-description-rep =
Repeats the input value N times to form a sequence.
command-description-take =
Takes N values from the input sequence
command-description-spawn-at =
Spawns an entity at the given coordinates.
command-description-spawn-on =
Spawns an entity on the given entity, at it's coordinates.
command-description-spawn-attached =
Spawns an entity attached to the given entity, at (0 0) relative to it.
command-description-mappos =
Returns an entity's coordinates relative to it's current map.
command-description-pos =
Returns an entity's coordinates.
command-description-tp-coords =
Teleports the target to the given coordinates.
command-description-tp-to =
Teleports the target to the given other entity.
command-description-tp-into =
Teleports the target "into" the given other entity, attaching it at (0 0) relative to it.
command-description-comp-get =
Gets the given component from the given entity.
command-description-comp-add =
Adds the given component to the given entity.
command-description-comp-ensure =
Ensures the given entity has the given component.
command-description-comp-has =
Check if the given entity has the given component.
command-description-AddVecCommand =
Adds a scalar (single value) to every element in the input.
command-description-SubVecCommand =
Subtracts a scalar (single value) from every element in the input.
command-description-MulVecCommand =
Multiplies a scalar (single value) by every element in the input.
command-description-DivVecCommand =
Divides every element in the input by a scalar (single value).
command-description-rng-to =
Returns a number from its input to its argument (i.e. n..m inclusive)
command-description-rng-from =
Returns a number to its input from its argument (i.e. m..n inclusive)
command-description-rng-prob =
Returns a boolean based on the input probability/chance (from 0 to 1)
command-description-sum =
Computes the sum of the input.
command-description-bin =
"Bins" the input, counting up how many times each unique element occurs.
command-description-extremes =
Returns the two extreme ends of a list, interwoven.
command-description-sortby =
Sorts the input least to greatest by the computed key.
command-description-sortmapby =
Sorts the input least to greatest by the computed key, replacing the value with it's computed key afterward.
command-description-sort =
Sorts the input least to greatest.
command-description-sortdownby =
Sorts the input greatest to least by the computed key.
command-description-sortmapdownby =
Sorts the input greatest to least by the computed key, replacing the value with it's computed key afterward.
command-description-sortdown =
Sorts the input greatest to least.
command-description-iota =
Returns a list of numbers 1 to N.
command-description-to =
Returns a list of numbers N to M.
command-description-curtick =
The current game tick.
command-description-curtime =
The current game time (a TimeSpan)
command-description-realtime =
The current realtime since startup (a TimeSpan)
command-description-servertime =
The current server game time, or zero if we are the server (a TimeSpan)
command-description-replace =
Replaces the input entities with the given prototype, preserving position and rotation (but nothing else)
command-description-allcomps =
Returns all components on the given entity.
command-description-entitysystemupdateorder-tick =
Lists the tick update order of entity systems.
command-description-entitysystemupdateorder-frame =
Lists the frame update order of entity systems.
command-description-more =
Prints the contents of $more, i.e. any extras that Toolshed didn't print from the last command.
command-description-ModulusCommand =
Computes the modulus of two values.
This is usually remainder, check C#'s documentation for the type.
command-description-ModVecCommand =
Performs the modulus operation over the input with the given constant right-hand value.
command-description-BitAndNotCommand =
Performs bitwise AND-NOT over the input.
command-description-BitOrNotCommand =
Performs bitwise OR-NOT over the input.
command-description-BitXnorCommand =
Performs bitwise XNOR over the input.
command-description-BitNotCommand =
Performs bitwise NOT on the input.
command-description-abs =
Computes the absolute value of the input (removing the sign)
command-description-average =
Computes the average (arithmetic mean) of the input.
command-description-bibytecount =
Returns the size of the input in bytes, given that the input implements IBinaryInteger.
This is NOT sizeof.
command-description-shortestbitlength =
Returns the minimum number of bits needed to represent the input value.
command-description-countleadzeros =
Counts the number of leading binary zeros in the input value.
command-description-counttrailingzeros =
Counts the number of trailing binary zeros in the input value.
command-description-fpi =
pi (3.14159...) as a float.
command-description-fe =
e (2.71828...) as a float.
command-description-ftau =
tau (6.28318...) as a float.
command-description-fepsilon =
The epsilon value for a float, exactly 1.4e-45.
command-description-dpi =
pi (3.14159...) as a double.
command-description-de =
e (2.71828...) as a double.
command-description-dtau =
tau (6.28318...) as a double.
command-description-depsilon =
The epsilon value for a double, exactly 4.9406564584124654E-324.
command-description-hpi =
pi (3.14...) as a half.
command-description-he =
e (2.71...) as a half.
command-description-htau =
tau (6.28...) as a half.
command-description-hepsilon =
The epsilon value for a half, exactly 5.9604645E-08.
command-description-floor =
Returns the floor of the input value (rounding toward zero).
command-description-ceil =
Returns the ceil of the input value (rounding away from zero).
command-description-round =
Rounds the input value.
command-description-trunc =
Truncates the input value.
command-description-round2frac =
Rounds the input value to the specified number of fractional digits.
command-description-exponentbytecount =
Returns the number of bytes required to store the exponent.
command-description-significandbytecount =
Returns the number of bytes required to store the significand.
command-description-significandbitcount =
Returns the exact bit length of the significand.
command-description-exponentshortestbitcount =
Returns the minimum number of bits to store the exponent.
command-description-stepnext =
Steps to the next float value, adding one to the significand with carry.
command-description-stepprev =
Steps to the previous float value, subtracting one from the significand with carry.
command-description-checkedto =
Converts from the input numeric type to the target, erroring if not possible.
command-description-saturateto =
Converts from the input numeric type to the target, saturating if the value is out of range.
For example, converting 382 to a byte would saturate to 255 (the maximum value of a byte).
command-description-truncto =
Converts from the input numeric type to the target, with truncation.
In the case of integers, this is a bit cast with sign extension.
command-description-iscanonical =
Returns whether the input is in canonical form.
command-description-iscomplex =
Returns whether the input is a complex number (by value, not by type)
command-description-iseven =
Returns whether the input is even.
Not a javascript package.
command-description-isodd =
Returns whether the input is odd.
command-description-isfinite =
Returns whether the input is finite.
command-description-isimaginary =
Returns whether the input is purely imaginary (no real part).
command-description-isinfinite =
Returns whether the input is infinite.
command-description-isinteger =
Returns whether the input is an integer (by value, not by type)
command-description-isnan =
Returns whether the input is Not a Number (NaN).
This is a special floating point value, so this is by value, not by type.
command-description-isnegative =
Returns whether the input is negative.
command-description-ispositive =
Returns whether the input is positive.
command-description-isreal =
Returns whether the input is purely real (no imaginary part).
command-description-issubnormal =
Returns whether the input is in sub-normal form.
command-description-iszero =
Returns whether the input is zero.
command-description-pow =
Computes the power of its lefthand to its righthand. x^y.
command-description-sqrt =
Computes the square root of its input.
command-description-cbrt =
Computes the cube root of its input.
command-description-root =
Computes the Nth root of its input.
command-description-hypot =
Computes the hypotenuse of a triangle with the given sides A and B.
command-description-sin =
Computes the sine of the input.
command-description-sinpi =
Computes the sine of the input multiplied by pi.
command-description-asin =
Computes the arcsine of the input.
command-description-asinpi =
Computes the arcsine of the input multiplied by pi.
command-description-cos =
Computes the cosine of the input.
command-description-cospi =
Computes the cosine of the input multiplied by pi.
command-description-acos =
Computes the arcosine of the input.
command-description-acospi =
Computes the arcosine of the input multiplied by pi.
command-description-tan =
Computes the tangent of the input.
command-description-tanpi =
Computes the tangent of the input multiplied by pi.
command-description-atan =
Computes the arctangent of the input.
command-description-atanpi =
Computes the arctangent of the input multiplied by pi.
command-description-iterate =
Iterates the given function over the input N times, returning a list of results.
Think of this like successively applying the function to a value, tracking all the intermediate values.
command-description-pick =
Picks a random value from the input.
command-description-tee =
Tees the input into the given block, ignoring the block's result.
This essentially lets you have a branch in your code to do multiple operations on one value.
command-description-cmd-info =
Returns a CommandSpec for the given command.
On it's own, this means it'll print the comamnd's help message.
command-description-comp-rm =
Removes the given component from the entity.

View File

@@ -1,7 +0,0 @@
uploadfolder-command-description = Uploads a folder from your UserData folder recursively to the server contentDB.
uploadfolder-command-help = uploadfolder [folder you want to upload in userdata/UploadFolder]
uploadfolder-command-wrong-args = Wrong number of arguments!
uploadfolder-command-folder-not-found = Folder {$folder} not found!
uploadfolder-command-resource-upload-disabled = Network Resource Uploading is currently disabled. check Server CVars.
uploadfolder-command-file-too-big = File {$filename} above the current size limit! It must be smaller than {$sizeLimit} MB. skipping.
uploadfolder-command-success = Uploaded {$fileCount} files

View File

@@ -1,6 +1,5 @@
## ViewVariablesInstanceEntity
view-variables = View Variables
view-variable-instance-entity-server-components-add-component-button-placeholder = Add Component
view-variable-instance-entity-client-variables-tab-title = Client Variables
view-variable-instance-entity-client-components-tab-title = Client Components
@@ -9,4 +8,4 @@ view-variable-instance-entity-server-components-tab-title = Server Components
view-variable-instance-entity-client-components-search-bar-placeholder = Search
view-variable-instance-entity-server-components-search-bar-placeholder = Search
view-variable-instance-entity-add-window-server-components = Add Component [S]
view-variable-instance-entity-add-window-client-components = Add Component [C]
view-variable-instance-entity-add-window-client-components = Add Component [C]

View File

@@ -1,63 +0,0 @@
# Used internally by the THE() function.
zzzz-the = { PROPER($ent) ->
*[false] a { $ent }
[true] { $ent }
}
# Used internally by the SUBJECT() function.
zzzz-subject-pronoun = { GENDER($ent) ->
[male] ele
[female] ela
[epicene] eles
*[neuter] ele
}
# Used internally by the OBJECT() function.
zzzz-object-pronoun = { GENDER($ent) ->
[male] ele
[female] ela
[epicene] eles
*[neuter] isso
}
# Used internally by the POSS-PRONOUN() function.
zzzz-possessive-pronoun = { GENDER($ent) ->
[male] dele
[female] dela
[epicene] deles
*[neuter] dele
}
# Used internally by the POSS-ADJ() function.
zzzz-possessive-adjective = { GENDER($ent) ->
[male] dele
[female] dela
[epicene] deles
*[neuter] dele
}
# Used internally by the REFLEXIVE() function.
zzzz-reflexive-pronoun = { GENDER($ent) ->
[male] ele mesmo
[female] ela mesmo
[epicene] eles mesmos
*[neuter] ele mesmo
}
# Used internally by the CONJUGATE-BE() function.
zzzz-conjugate-be = { GENDER($ent) ->
[epicene] é
*[other] é
}
# Used internally by the CONJUGATE-HAVE() function.
zzzz-conjugate-have = { GENDER($ent) ->
[epicene] tenho
*[other] tem
}
# Used internally by the CONJUGATE-BASIC() function.
zzzz-conjugate-basic = { GENDER($ent) ->
[epicene] { $first }
*[other] { $second }
}

View File

@@ -1,16 +0,0 @@
# Strings Loc para vários comandos relacionados ao estado da entidade e ao PVS do lado do cliente
cmd-reset-ent-help = Uso: resetent <Entity UID>
cmd-reset-ent-desc = Redefina uma entidade para o estado do servidor recebido mais recentemente. Isso também redefinirá as entidades que foram desanexadas para espaço nulo.
cmd-reset-all-ents-help = Uso: resetallents
cmd-reset-all-ents-desc = Redefine todas as entidades para o estado do servidor recebido mais recentemente. Isso afeta apenas as entidades que não foram desanexadas ao espaço nulo.
cmd-detach-ent-help = Uso: detachent <Entity UID>
cmd-detach-ent-desc = Desanexar uma entidade para espaço nulo, como se tivesse saído do intervalo PVS.
cmd-local-delete-help = Uso: localdelete <Entity UID>
cmd-local-delete-desc = Exclui uma entidade. Ao contrário do comando delete normal, este é CLIENT-SIDE. A menos que a entidade seja uma entidade do lado do cliente, isso provavelmente causará erros.
cmd-full-state-reset-help = Uso: fullstatereset
cmd-full-state-reset-desc = Descarta qualquer informação de estado da entidade e solicita um estado completo do servidor.

View File

@@ -1,161 +0,0 @@
### Localization for engine console commands
## generic
cmd-invalid-arg-number-error = Número inválido de argumentos.
cmd-parse-failure-integer = {$arg} não é um inteiro válido.
cmd-parse-failure-float = {$arg} não é um float válido.
cmd-parse-failure-bool = {$arg} não é um booleano válido.
cmd-parse-failure-uid = {$arg} não é um UID de entidade válido.
cmd-parse-failure-entity-exist = UID {$arg} não corresponde a uma entidade existente.
## 'help' command
cmd-help-desc = Exibir ajuda geral ou texto de ajuda para um comando específico
cmd-help-help = Uso: help [command name]
Quando nenhum nome de comando é fornecido, exibe o texto de ajuda geral. Se um nome de comando for fornecido, exibe o texto de ajuda para esse comando.
cmd-help-no-args = Para exibir a ajuda de um comando específico, escreva 'help <command>'. Para listar todos os comandos disponíveis, escreva 'list'. Para procurar comandos, use 'list <filter>'.
cmd-help-unknown = Comando desconhecido: { $command }
cmd-help-top = { $command } - { $description }
cmd-help-invalid-args = Quantidade de argumentos inválida.
cmd-help-arg-cmdname = [command name]
## 'cvar' command
cmd-cvar-desc = Obtém ou define um CVar.
cmd-cvar-help = Uso: cvar <name | ?> [value]
Se um valor for passado, o valor será analisado e armazenado como o novo valor do CVar.
Caso contrário, o valor atual do CVar é exibido.
Use 'cvar ?' para obter uma lista de todos os CVars registrados.
cmd-cvar-invalid-args = Deve fornecer exatamente um ou dois argumentos.
cmd-cvar-not-registered = CVar '{ $cvar }' não está registrado. Use 'cvar ?' para obter uma lista de todos os CVars registrados.
cmd-cvar-parse-error = O valor de entrada está no formato incorreto para o tipo { $type }
cmd-cvar-compl-list = Listar CVars disponíveis
cmd-cvar-arg-name = <name | ?>
cmd-cvar-value-hidden = <value hidden>
## 'list' command
cmd-list-desc = Lista os comandos disponíveis, com filtro de pesquisa opcional
cmd-list-help = Uso: list [filter]
Lista todos os comandos disponíveis. Se um argumento for fornecido, ele será usado para filtrar comandos por nome.
cmd-list-heading = NOME DESC{"\u000A"}-------------------------{"\u000A"}
cmd-list-arg-filter = [filter]
## '>' command, aka remote exec
cmd-remoteexec-desc = Executa comandos do lado do servidor
cmd-remoteexec-help = Uso: > <command> [arg] [arg] [arg...]
Executa um comando no servidor. Isso é necessário se um comando com o mesmo nome existir no cliente, pois a simples execução do comando executaria o comando do cliente primeiro.
## 'gc' command
cmd-gc-desc = Execute o GC (coletor de lixo)
cmd-gc-help = Uso: gc [generation]
Usa GC.Collect() para executar o Garbage Collector.
Se um argumento for fornecido, ele será analisado como um número de geração do GC e GC.Collect(int) será usado.
Use o comando 'gfc' para fazer um GC completo compactando LOH.
cmd-gc-failed-parse = Falha ao analisar o argumento.
cmd-gc-arg-generation = [generation]
## 'gcf' command
cmd-gcf-desc = Execute o GC, totalmente, compactando LOH e tudo.
cmd-gcf-help = Uso: gcf
Faz um GC.Collect(2, GCCollectionMode.Forced, true, true) completo enquanto também compacta LOH.
Isso provavelmente será bloqueado por centenas de milissegundos, esteja avisado.
## 'gc_mode' command
cmd-gc_mode-desc = Alterar/ler o modo de latência do GC
cmd-gc_mode-help = Uso: gc_mode [type]
Se nenhum argumento for fornecido, retornará o modo de latência do GC atual.
Se um argumento for passado, ele será analisado como GCLatencyMode e definido como o modo de latência do GC.
cmd-gc_mode-current = modo de latência atual do gc: { $prevMode }
cmd-gc_mode-possible = modos possíveis:
cmd-gc_mode-option = - { $mode }
cmd-gc_mode-unknown = modo de latência gc desconhecido: { $arg }
cmd-gc_mode-attempt = tentando alterar o modo de latência do gc: { $prevMode } -> { $mode }
cmd-gc_mode-result = modo de latência gc resultante: { $mode }
cmd-gc_mode-arg-type = [type]
## 'mem' command
cmd-mem-desc = Imprime informações de memória gerenciada
cmd-mem-help = Uso: mem
cmd-mem-report = Tamanho da pilha: { TOSTRING($heapSize, "N0") }
Total alocado: { TOSTRING($totalAllocated, "N0") }
## 'physics' command
cmd-physics-overlay = {$overlay} não é uma sobreposição reconhecida
## 'lsasm' command
cmd-lsasm-desc = Lista assemblies carregados por contexto de carregamento
cmd-lsasm-help = Uso: lsasm
## 'exec' command
cmd-exec-desc = Executa um arquivo de script dos dados de usuário graváveis do jogo
cmd-exec-help = Uso: exec <fileName>
Cada linha no arquivo é executada como um único comando, a menos que comece com um #
cmd-exec-arg-filename = <fileName>
## 'dump_net_comps' command
cmd-dump_net_comps-desc = Imprime a tabela de componentes em rede.
cmd-dump_net_comps-help = Uso: dump_net-comps
cmd-dump_net_comps-error-writeable = Registro ainda gravável, IDs de rede não foram gerados.
cmd-dump_net_comps-header = Registros de componentes em rede:
## 'dump_event_tables' command
cmd-dump_event_tables-desc = Imprime tabelas de eventos direcionados para uma entidade.
cmd-dump_event_tables-help = Uso: dump_event_tables <entityUid>
cmd-dump_event_tables-missing-arg-entity = Argumento de entidade ausente
cmd-dump_event_tables-error-entity = Entidade inválida
cmd-dump_event_tables-arg-entity = <entityUid>
## 'monitor' command
cmd-monitor-desc = Alterna um monitor de depuração no menu F3.
cmd-monitor-help = Uso: monitor <name>
Os monitores possíveis são: { $monitors }
Você também pode usar os valores especiais "-all" e "+all" para ocultar ou mostrar todos os monitores, respectivamente.
cmd-monitor-arg-monitor = <monitor>
cmd-monitor-invalid-name = Nome do monitor inválido
cmd-monitor-arg-count = Argumento do monitor ausente
cmd-monitor-minus-all-hint = Esconde todos os monitores
cmd-monitor-plus-all-hint = Mostra todos os monitores
## Mapping commands
cmd-savemap-desc = Serializa um mapa para o disco. Não salvará um mapa pós-inicialização a menos que seja forçado.
cmd-savemap-help = savemap <MapID> <Path> [force]
cmd-savemap-not-exist = O mapa de destino não existe.
cmd-savemap-init-warning = Tentativa de salvar um mapa pós-inicialização sem forçar o salvamento.
cmd-savemap-attempt = Tentando salvar o mapa {$mapId} em {$path}.
cmd-savemap-success = Mapa salvo com sucesso.
cmd-hint-savemap-id = <MapID>
cmd-hint-savemap-path = <Path>
cmd-hint-savemap-force = [bool]
cmd-loadmap-desc = Carrega um mapa do disco para o jogo.
cmd-loadmap-help = loadmap <MapID> <Path> [x] [y] [rotation] [consistentUids]
cmd-loadmap-nullspace = Você não pode carregar no mapa 0.
cmd-loadmap-exists = Mapa {$mapId} já existe.
cmd-loadmap-success = Mapa {$mapId} foi carregado em {$path}.
cmd-loadmap-error = Ocorreu um erro ao carregar o mapa de {$path}.
cmd-hint-loadmap-x-position = [x-position]
cmd-hint-loadmap-y-position = [y-position]
cmd-hint-loadmap-rotation = [rotation]
cmd-hint-loadmap-uids = [float]
cmd-hint-savebp-id = <Grid EntityID>
## 'flushcookies' command
# Note: the flushcookies command is from Robust.Client.WebView, it's not in the main engine code.
cmd-flushcookies-desc = Liberar o armazenamento de cookies CEF para o disco
cmd-flushcookies-help = Isso garante que os cookies sejam salvos corretamente no disco no caso de desligamentos impróprios.
Observe que a operação real é assíncrona.

View File

@@ -1,10 +0,0 @@
color-selector-sliders-red = R
color-selector-sliders-green = G
color-selector-sliders-blue = B
color-selector-sliders-hue = H
color-selector-sliders-saturation = S
color-selector-sliders-value = V
color-selector-sliders-alpha = A
color-selector-sliders-rgb = RGB
color-selector-sliders-hsv = HSV

View File

@@ -1,11 +0,0 @@
## EntitySpawnWindow
entity-spawn-window-title = Painel de Criação de Entidade
entity-spawn-window-search-bar-placeholder = pesquisar
entity-spawn-window-clear-button = Limpar
entity-spawn-window-erase-button-text = Modo Apagar
entity-spawn-window-override-menu-tooltip = Substituir posicionamento
## Console
console-line-edit-placeholder = Comando aqui

View File

@@ -1 +0,0 @@
defaultwindow-placeholder-title = Exemplo de título de janela aqui

View File

@@ -1,54 +0,0 @@
input-key-Escape = Escape
input-key-Control = Control
input-key-Shift = Shift
input-key-Alt = Alt
input-key-Menu = Menu
input-key-F1 = F1
input-key-F2 = F2
input-key-F3 = F3
input-key-F4 = F4
input-key-F5 = F5
input-key-F6 = F6
input-key-F7 = F7
input-key-F8 = F8
input-key-F9 = F9
input-key-F10 = F10
input-key-F11 = F11
input-key-F12 = F12
input-key-F13 = F13
input-key-F14 = F14
input-key-F15 = F15
input-key-Pause = Pause
input-key-Left = Left
input-key-Up = Up
input-key-Down = Down
input-key-Right = Right
input-key-Space = Space
input-key-Return = Return
input-key-NumpadEnter = Num Enter
input-key-BackSpace = Backspace
input-key-Tab = Tab
input-key-PageUp = Page Up
input-key-PageDown = Page Down
input-key-End = End
input-key-Home = Home
input-key-Insert = Insert
input-key-Delete = Delete
input-key-MouseLeft = Mouse Left
input-key-MouseRight = Mouse Right
input-key-MouseMiddle = Mouse Middle
input-key-MouseButton4 = Mouse 4
input-key-MouseButton5 = Mouse 5
input-key-MouseButton6 = Mouse 6
input-key-MouseButton7 = Mouse 7
input-key-MouseButton8 = Mouse 8
input-key-MouseButton9 = Mouse 9
input-key-LSystem-win = Left Win
input-key-RSystem-win = Right Win
input-key-LSystem-mac = Left Cmd
input-key-RSystem-mac = Right Cmd
input-key-LSystem-linux = Left Meta
input-key-RSystem-linux = Right Meta
input-key-unknown = <unknown key>

View File

@@ -1 +0,0 @@
cmd-midipanic-desc = Desliga cada nota para cada renderizador MIDI ativo.

View File

@@ -1 +0,0 @@
tab-container-not-tab-title-provided = Sem título

View File

@@ -1,11 +0,0 @@
## ViewVariablesInstanceEntity
view-variable-instance-entity-server-components-add-component-button-placeholder = Adicionar Componente
view-variable-instance-entity-client-variables-tab-title = Variávies do Cliente
view-variable-instance-entity-client-components-tab-title = Componentes do Cliente
view-variable-instance-entity-server-variables-tab-title = Variávies do Servidor
view-variable-instance-entity-server-components-tab-title = Componentes do Servidor
view-variable-instance-entity-client-components-search-bar-placeholder = Pesquisar
view-variable-instance-entity-server-components-search-bar-placeholder = Pesquisar
view-variable-instance-entity-add-window-server-components = Adicionar Componente [S]
view-variable-instance-entity-add-window-client-components = Adicionar Componente [C]

View File

@@ -12,8 +12,3 @@
id: bgra
kind: source
path: "/Shaders/Internal/bgra.swsl"
- type: shader
id: ColorPicker
kind: source
path: "/Shaders/color_picker.swsl"

View File

@@ -5,7 +5,6 @@ preset raw;
#include "/Shaders/Internal/fov_shared.swsl"
const highp float g_MinVariance = 0.0;
uniform highp vec4 occludeColor;
void fragment()
{
@@ -20,5 +19,5 @@ void fragment()
discard;
}
COLOR = vec4(occludeColor.rgb, 1.0 - occlusion);
COLOR = vec4(0.0, 0.0, 0.0, 1.0 - occlusion);
}

View File

@@ -5,7 +5,6 @@ preset raw;
#include "/Shaders/Internal/fov_shared.swsl"
const highp float g_MinVariance = 0.0;
uniform highp vec4 occludeColor;
void fragment()
{
@@ -19,5 +18,5 @@ void fragment()
discard;
}
COLOR = vec4(occludeColor.rgb, 1.0);
COLOR = vec4(0.0, 0.0, 0.0, 1.0);
}

View File

@@ -1,46 +0,0 @@
// Simple shader for creating a box with colours varying along the x and y axes.
uniform highp vec2 size;
uniform highp vec2 offset;
uniform highp vec4 xAxis;
uniform highp vec4 yAxis;
uniform highp vec4 baseColor;
uniform bool hsv;
void fragment()
{
// Calculate local uv coordinates.
// I.e., if using this shader to draw a box to the screen, (0,0) is the bottom left of the box.
highp float yCoords = 1.0/SCREEN_PIXEL_SIZE.y - FRAGCOORD.y;
highp vec2 uv = vec2(FRAGCOORD.x - offset.x, yCoords - offset.y);
uv /= size;
uv.y = 1.0 - uv.y;
highp vec4 modulate = baseColor + uv.x * xAxis + uv.y * yAxis;
if (hsv)
{
modulate.xyz = hsv2rgb(modulate.xyz);
}
// The UV used for the texture lookup is the TEXTURE UV coordinate, which is different from the coordinates computed above.
COLOR = zTexture(UV) * modulate;
}
// hsv to RGB conversion taken from www.shadertoy.com/view/MsS3Wc
// The MIT License
// Copyright © 2014 Inigo Quilez
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// https://www.youtube.com/c/InigoQuilez
// https://iquilezles.org
highp vec3 hsv2rgb( in highp vec3 c )
{
highp vec3 rgb = clamp( abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0 );
return c.z * mix( vec3(1.0), rgb, c.y);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 B

View File

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 535 B

View File

@@ -1,822 +0,0 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Testing;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.CodeAnalysis.Testing.Verifiers;
using NUnit.Framework;
using Robust.Analyzers;
using VerifyCS = Microsoft.CodeAnalysis.CSharp.Testing.NUnit.AnalyzerVerifier<Robust.Analyzers.AccessAnalyzer>;
using static Microsoft.CodeAnalysis.Testing.DiagnosticResult;
namespace Robust.Analyzers.Tests;
[Parallelizable(ParallelScope.All | ParallelScope.Fixtures)]
[TestFixture]
public sealed class AccessAnalyzer_Test
{
public Task Verifier(string code, params DiagnosticResult[] expected)
{
var test = new CSharpAnalyzerTest<AccessAnalyzer, NUnitVerifier>()
{
TestState =
{
AdditionalReferences = { typeof(AccessAnalyzer).Assembly },
Sources = { code }
},
};
// ExpectedDiagnostics cannot be set, so we need to AddRange here...
test.TestState.ExpectedDiagnostics.AddRange(expected);
return test.RunAsync();
}
/*
*
*/
[Test]
public async Task ReadTest()
{
const string code = @"
using System;
using Robust.Shared.Analyzers;
// ReSharper disable RedundantAssignment
// ReSharper disable UnusedVariable
// ReSharper disable ArrangeThisQualifier
// ReSharper disable UnusedMember.Global
// ReSharper disable UnusedType.Global
public struct MyData
{
public int MyField;
public static bool operator ==(MyData lhs, MyData rhs) => lhs.MyField == rhs.MyField;
public static bool operator !=(MyData lhs, MyData rhs) => lhs.MyField != rhs.MyField;
}
[Access(typeof(FriendlyClass),
Self = AccessPermissions.None,
Friend = AccessPermissions.None,
Other = AccessPermissions.None)]
public sealed class TypeNobodyCanRead
{
public MyData Data = default;
[Access(typeof(FriendlyClass),
Self = AccessPermissions.Read,
Friend = AccessPermissions.Read,
Other = AccessPermissions.Read)]
public MyData Data2 = default;
public void TestTypeNobodyCanRead(TypeNobodyCanRead obj)
{
// None of these accesses should be allowed.
var copy = Data;
var copy2 = this.Data;
var copy3 = obj.Data;
copy = Data;
copy = this.Data;
copy = obj.Data;
var copy4 = Data.MyField;
var copy5 = this.Data.MyField;
var copy6 = obj.Data.MyField;
if (Data == copy) {}
if (this.Data == copy) {}
if (obj.Data == copy) {}
if(Data.MyField == 0) {}
if(this.Data.MyField == 0) {}
if(obj.Data.MyField == 0) {}
// All of these accesses should be fine.
var copy7 = Data2;
var copy8 = this.Data2;
var copy9 = obj.Data2;
copy = Data2;
copy = this.Data2;
copy = obj.Data2;
var copy10 = Data2.MyField;
var copy11 = this.Data2.MyField;
var copy12 = obj.Data2.MyField;
if (Data2 == copy) {}
if (this.Data2 == copy) {}
if (obj.Data2 == copy) {}
if(Data2.MyField == 0) {}
if(this.Data2.MyField == 0) {}
if(obj.Data2.MyField == 0) {}
}
}
[Access(typeof(FriendlyClass),
Self = AccessPermissions.Read,
Friend = AccessPermissions.Read,
Other = AccessPermissions.Read)]
public sealed class MemberNobodyCanRead
{
[Access(typeof(FriendlyClass),
Self = AccessPermissions.None,
Friend = AccessPermissions.None,
Other = AccessPermissions.None)]
public MyData Data = default;
public MyData Data2 = default;
public void TestMemberNobodyCanRead(TypeNobodyCanRead obj)
{
// None of these accesses should be allowed.
var copy = Data;
var copy2 = this.Data;
var copy3 = obj.Data;
copy = Data;
copy = this.Data;
copy = obj.Data;
var copy4 = Data.MyField;
var copy5 = this.Data.MyField;
var copy6 = obj.Data.MyField;
if (Data == copy) {}
if (this.Data == copy) {}
if (obj.Data == copy) {}
if(Data.MyField == 0) {}
if(this.Data.MyField == 0) {}
if(obj.Data.MyField == 0) {}
// All of these accesses should be fine.
var copy7 = Data2;
var copy8 = this.Data2;
var copy9 = obj.Data2;
copy = Data2;
copy = this.Data2;
copy = obj.Data2;
var copy10 = Data2.MyField;
var copy11 = this.Data2.MyField;
var copy12 = obj.Data2.MyField;
if (Data2 == copy) {}
if (this.Data2 == copy) {}
if (obj.Data2 == copy) {}
if(Data2.MyField == 0) {}
if(this.Data2.MyField == 0) {}
if(obj.Data2.MyField == 0) {}
}
}
public sealed class FriendlyClass
{
public void TestTypeNobodyCanRead(TypeNobodyCanRead obj)
{
// We shouldn't be able to access any of these, even if we're a friend..
var copy = obj.Data;
copy = obj.Data;
var copy2 = obj.Data.MyField;
copy2 = obj.Data.MyField;
if (obj.Data == copy) {}
if(obj.Data.MyField == 0) {}
// We should be allowed to access all of these, we're friends!
var copy3 = obj.Data2;
copy = obj.Data2;
var copy4 = obj.Data2.MyField;
copy4 = obj.Data2.MyField;
if(obj.Data2 == copy) {}
if(obj.Data2.MyField == 0) {}
}
public void TestMemberNobodyCanRead(MemberNobodyCanRead obj)
{
// We shouldn't be able to access any of these, even if we're a friend..
var copy = obj.Data;
copy = obj.Data;
var copy2 = obj.Data.MyField;
copy2 = obj.Data.MyField;
if (obj.Data == copy) {}
if(obj.Data.MyField == 0) {}
// We should be allowed to access all of these, we're friends!
var copy3 = obj.Data2;
copy = obj.Data2;
var copy4 = obj.Data2.MyField;
copy4 = obj.Data2.MyField;
if(obj.Data2 == copy) {}
if(obj.Data2.MyField == 0) {}
}
}
public sealed class OtherClass
{
public void TestTypeNobodyCanRead(TypeNobodyCanRead obj)
{
// We shouldn't be able to access any of these, as 'other types' can't..
var copy = obj.Data;
copy = obj.Data;
var copy2 = obj.Data.MyField;
copy2 = obj.Data.MyField;
if (obj.Data == copy) {}
if(obj.Data.MyField == 0) {}
// We should be allowed to access all of these, they let others read it!
var copy3 = obj.Data2;
copy = obj.Data2;
var copy4 = obj.Data2.MyField;
copy4 = obj.Data2.MyField;
if(obj.Data2 == copy) {}
if(obj.Data2.MyField == 0) {}
}
public void TestMemberNobodyCanRead(MemberNobodyCanRead obj)
{
// We shouldn't be able to access any of these, as 'other types' can't..
var copy = obj.Data;
copy = obj.Data;
var copy2 = obj.Data.MyField;
copy2 = obj.Data.MyField;
if (obj.Data == copy) {}
if(obj.Data.MyField == 0) {}
// We should be allowed to access all of these, they let others read it!
var copy3 = obj.Data2;
copy = obj.Data2;
var copy4 = obj.Data2.MyField;
copy4 = obj.Data2.MyField;
if(obj.Data2 == copy) {}
if(obj.Data2.MyField == 0) {}
}
}";
await Verifier(code,
// AUTO-GENERATED DIAGNOSTICS BELOW //
// /0/Test0.cs(35,20): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(35, 20, 35, 24).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(36,21): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(36, 21, 36, 30).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(37,21): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(37, 21, 37, 29).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(39,16): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(39, 16, 39, 20).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(40,16): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(40, 16, 40, 25).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(41,16): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(41, 16, 41, 24).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(43,21): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(43, 21, 43, 25).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(44,21): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(44, 21, 44, 30).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(45,21): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(45, 21, 45, 29).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(47,13): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(47, 13, 47, 17).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(48,13): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(48, 13, 48, 22).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(49,13): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(49, 13, 49, 21).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(51,12): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(51, 12, 51, 16).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(52,12): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(52, 12, 52, 21).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(53,12): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(53, 12, 53, 20).WithArguments("a 'Read' same-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(95,20): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(95, 20, 95, 24).WithArguments("a 'Read' same-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(96,21): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(96, 21, 96, 30).WithArguments("a 'Read' same-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(97,21): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(97, 21, 97, 29).WithArguments("a 'Read' other-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(99,16): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(99, 16, 99, 20).WithArguments("a 'Read' same-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(100,16): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(100, 16, 100, 25).WithArguments("a 'Read' same-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(101,16): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(101, 16, 101, 24).WithArguments("a 'Read' other-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(103,21): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(103, 21, 103, 25).WithArguments("a 'Read' same-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(104,21): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(104, 21, 104, 30).WithArguments("a 'Read' same-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(105,21): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(105, 21, 105, 29).WithArguments("a 'Read' other-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(107,13): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(107, 13, 107, 17).WithArguments("a 'Read' same-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(108,13): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(108, 13, 108, 22).WithArguments("a 'Read' same-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(109,13): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(109, 13, 109, 21).WithArguments("a 'Read' other-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(111,12): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(111, 12, 111, 16).WithArguments("a 'Read' same-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(112,12): error RA0002: Tried to perform a 'Read' same-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(112, 12, 112, 21).WithArguments("a 'Read' same-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(113,12): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(113, 12, 113, 20).WithArguments("a 'Read' other-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(143,20): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(143, 20, 143, 28).WithArguments("a 'Read' friend-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(144,16): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(144, 16, 144, 24).WithArguments("a 'Read' friend-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(146,21): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(146, 21, 146, 29).WithArguments("a 'Read' friend-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(147,17): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(147, 17, 147, 25).WithArguments("a 'Read' friend-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(149,13): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(149, 13, 149, 21).WithArguments("a 'Read' friend-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(150,12): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(150, 12, 150, 20).WithArguments("a 'Read' friend-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(166,20): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(166, 20, 166, 28).WithArguments("a 'Read' friend-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(167,16): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(167, 16, 167, 24).WithArguments("a 'Read' friend-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(169,21): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(169, 21, 169, 29).WithArguments("a 'Read' friend-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(170,17): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(170, 17, 170, 25).WithArguments("a 'Read' friend-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(172,13): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(172, 13, 172, 21).WithArguments("a 'Read' friend-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(173,12): error RA0002: Tried to perform a 'Read' friend-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(173, 12, 173, 20).WithArguments("a 'Read' friend-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(192,20): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(192, 20, 192, 28).WithArguments("a 'Read' other-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(193,16): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(193, 16, 193, 24).WithArguments("a 'Read' other-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(195,21): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(195, 21, 195, 29).WithArguments("a 'Read' other-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(196,17): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(196, 17, 196, 25).WithArguments("a 'Read' other-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(198,13): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(198, 13, 198, 21).WithArguments("a 'Read' other-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(199,12): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'TypeNobodyCanRead', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(199, 12, 199, 20).WithArguments("a 'Read' other-type", "Data", "TypeNobodyCanRead", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(215,20): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(215, 20, 215, 28).WithArguments("a 'Read' other-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(216,16): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(216, 16, 216, 24).WithArguments("a 'Read' other-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(218,21): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(218, 21, 218, 29).WithArguments("a 'Read' other-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(219,17): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(219, 17, 219, 25).WithArguments("a 'Read' other-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(221,13): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(221, 13, 221, 21).WithArguments("a 'Read' other-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(222,12): error RA0002: Tried to perform a 'Read' other-type access to member 'Data' in type 'MemberNobodyCanRead', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(222, 12, 222, 20).WithArguments("a 'Read' other-type", "Data", "MemberNobodyCanRead", "having no", "Member Permissions: ---------")
);
}
[Test]
public async Task WriteTest()
{
const string code = @"
using System;
using Robust.Shared.Analyzers;
// ReSharper disable RedundantAssignment
// ReSharper disable UnusedVariable
// ReSharper disable ArrangeThisQualifier
// ReSharper disable UnusedMember.Global
// ReSharper disable UnusedType.Global
// ReSharper disable NotAccessedField.Global
// ReSharper disable RedundantDefaultMemberInitializer
public struct MyData
{
public int MyField;
}
[Access(typeof(FriendlyClass),
Self = AccessPermissions.None,
Friend = AccessPermissions.None,
Other = AccessPermissions.None)]
public sealed class TypeNobodyCanWrite
{
public MyData Data = default;
[Access(typeof(FriendlyClass),
Self = AccessPermissions.Write,
Friend = AccessPermissions.Write,
Other = AccessPermissions.Write)]
public MyData Data2 = default;
public void TestTypeNobodyCanWrite(TypeNobodyCanWrite obj)
{
// None of these accesses should be allowed.
Data = default;
this.Data = default;
obj.Data = default;
Data.MyField = 0;
this.Data.MyField = 0;
obj.Data.MyField = 0;
// All of these accesses should be fine.
Data2 = default;
this.Data2 = default;
obj.Data2 = default;
Data2.MyField = 0;
this.Data2.MyField = 0;
obj.Data2.MyField = 0;
}
}
[Access(typeof(FriendlyClass),
Self = AccessPermissions.Write,
Friend = AccessPermissions.Write,
Other = AccessPermissions.Write)]
public sealed class MemberNobodyCanWrite
{
[Access(typeof(FriendlyClass),
Self = AccessPermissions.None,
Friend = AccessPermissions.None,
Other = AccessPermissions.None)]
public MyData Data = default;
public MyData Data2 = default;
public void TestMemberNobodyCanWrite(TypeNobodyCanWrite obj)
{
// None of these accesses should be allowed.
Data = default;
this.Data = default;
obj.Data = default;
Data.MyField = 0;
this.Data.MyField = 0;
obj.Data.MyField = 0;
// All of these accesses should be fine.
Data2 = default;
this.Data2 = default;
obj.Data2 = default;
Data2.MyField = 0;
this.Data2.MyField = 0;
obj.Data2.MyField = 0;
}
}
public sealed class FriendlyClass
{
public void TestTypeNobodyCanWrite(TypeNobodyCanWrite obj)
{
// We shouldn't be able to access any of these, even if we're a friend..
obj.Data = default;
obj.Data.MyField = 0;
// We should be allowed to access all of these, we're friends!
obj.Data2 = default;
obj.Data2.MyField = 0;
}
public void TestMemberNobodyCanWrite(MemberNobodyCanWrite obj)
{
// We shouldn't be able to access any of these, even if we're a friend..
obj.Data = default;
obj.Data.MyField = 0;
// We should be allowed to access all of these, we're friends!
obj.Data2 = default;
obj.Data2.MyField = 0;
}
}
public sealed class OtherClass
{
public void TestTypeNobodyCanWrite(TypeNobodyCanWrite obj)
{
// We shouldn't be able to access any of these, as 'other types' can't..
obj.Data = default;
obj.Data.MyField = 0;
// We should be allowed to access all of these, they let others write!
obj.Data2 = default;
obj.Data2.MyField = 0;
}
public void TestMemberNobodyCanWrite(MemberNobodyCanWrite obj)
{
// We shouldn't be able to access any of these, as 'other types' can't..
obj.Data = default;
obj.Data.MyField = 0;
// We should be allowed to access all of these, they let others write!
obj.Data2 = default;
obj.Data2.MyField = 0;
}
}";
await Verifier(code,
// AUTO-GENERATED DIAGNOSTICS BELOW //
// /0/Test0.cs(34,9): error RA0002: Tried to perform a 'Write' same-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(34, 9, 34, 13).WithArguments("a 'Write' same-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(35,9): error RA0002: Tried to perform a 'Write' same-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(35, 9, 35, 18).WithArguments("a 'Write' same-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(36,9): error RA0002: Tried to perform a 'Write' same-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(36, 9, 36, 17).WithArguments("a 'Write' same-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(38,9): error RA0002: Tried to perform a 'Write' same-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(38, 9, 38, 13).WithArguments("a 'Write' same-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(39,9): error RA0002: Tried to perform a 'Write' same-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(39, 9, 39, 18).WithArguments("a 'Write' same-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(40,9): error RA0002: Tried to perform a 'Write' same-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(40, 9, 40, 17).WithArguments("a 'Write' same-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(70,9): error RA0002: Tried to perform a 'Write' same-type access to member 'Data' in type 'MemberNobodyCanWrite', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(70, 9, 70, 13).WithArguments("a 'Write' same-type", "Data", "MemberNobodyCanWrite", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(71,9): error RA0002: Tried to perform a 'Write' same-type access to member 'Data' in type 'MemberNobodyCanWrite', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(71, 9, 71, 18).WithArguments("a 'Write' same-type", "Data", "MemberNobodyCanWrite", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(72,9): error RA0002: Tried to perform a 'Write' other-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(72, 9, 72, 17).WithArguments("a 'Write' other-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(74,9): error RA0002: Tried to perform a 'Write' same-type access to member 'Data' in type 'MemberNobodyCanWrite', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(74, 9, 74, 13).WithArguments("a 'Write' same-type", "Data", "MemberNobodyCanWrite", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(75,9): error RA0002: Tried to perform a 'Write' same-type access to member 'Data' in type 'MemberNobodyCanWrite', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(75, 9, 75, 18).WithArguments("a 'Write' same-type", "Data", "MemberNobodyCanWrite", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(76,9): error RA0002: Tried to perform a 'Write' other-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(76, 9, 76, 17).WithArguments("a 'Write' other-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(94,9): error RA0002: Tried to perform a 'Write' friend-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(94, 9, 94, 17).WithArguments("a 'Write' friend-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(95,9): error RA0002: Tried to perform a 'Write' friend-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(95, 9, 95, 17).WithArguments("a 'Write' friend-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(105,9): error RA0002: Tried to perform a 'Write' friend-type access to member 'Data' in type 'MemberNobodyCanWrite', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(105, 9, 105, 17).WithArguments("a 'Write' friend-type", "Data", "MemberNobodyCanWrite", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(106,9): error RA0002: Tried to perform a 'Write' friend-type access to member 'Data' in type 'MemberNobodyCanWrite', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(106, 9, 106, 17).WithArguments("a 'Write' friend-type", "Data", "MemberNobodyCanWrite", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(119,9): error RA0002: Tried to perform a 'Write' other-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(119, 9, 119, 17).WithArguments("a 'Write' other-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(120,9): error RA0002: Tried to perform a 'Write' other-type access to member 'Data' in type 'TypeNobodyCanWrite', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(120, 9, 120, 17).WithArguments("a 'Write' other-type", "Data", "TypeNobodyCanWrite", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(130,9): error RA0002: Tried to perform a 'Write' other-type access to member 'Data' in type 'MemberNobodyCanWrite', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(130, 9, 130, 17).WithArguments("a 'Write' other-type", "Data", "MemberNobodyCanWrite", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(131,9): error RA0002: Tried to perform a 'Write' other-type access to member 'Data' in type 'MemberNobodyCanWrite', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(131, 9, 131, 17).WithArguments("a 'Write' other-type", "Data", "MemberNobodyCanWrite", "having no", "Member Permissions: ---------")
);
}
[Test]
public async Task ExecuteTest()
{
const string code = @"
using System;
using Robust.Shared.Analyzers;
// ReSharper disable RedundantAssignment
// ReSharper disable UnusedVariable
// ReSharper disable ArrangeThisQualifier
// ReSharper disable UnusedMember.Global
// ReSharper disable UnusedType.Global
// ReSharper disable NotAccessedField.Global
// ReSharper disable RedundantDefaultMemberInitializer
// ReSharper disable ReturnValueOfPureMethodIsNotUsed
public struct MyData
{
public int MyField;
public void MyMethod() {}
}
[Access(typeof(FriendlyClass),
Self = AccessPermissions.None,
Friend = AccessPermissions.None,
Other = AccessPermissions.None)]
public sealed class TypeNobodyCanExecute
{
public MyData Data = default;
[Access(typeof(FriendlyClass),
Self = AccessPermissions.Execute,
Friend = AccessPermissions.Execute,
Other = AccessPermissions.Execute)]
public MyData Data2 = default;
public void MyMethod() {}
[Access(typeof(FriendlyClass),
Self = AccessPermissions.Execute,
Friend = AccessPermissions.Execute,
Other = AccessPermissions.Execute)]
public void MyMethod2() {}
public void TestTypeNobodyCanExecute(TypeNobodyCanExecute obj)
{
// None of these accesses should be allowed.
MyMethod();
this.MyMethod();
obj.MyMethod();
Data.MyMethod();
this.Data.MyMethod();
obj.Data.MyMethod();
Data.MyField.ToString();
this.Data.MyField.ToString();
obj.Data.MyField.ToString();
// All of these accesses should be fine.
MyMethod2();
this.MyMethod2();
obj.MyMethod2();
Data2.MyMethod();
this.Data2.MyMethod();
obj.Data2.MyMethod();
Data2.MyField.ToString();
this.Data2.ToString();
obj.Data2.ToString();
}
}
[Access(typeof(FriendlyClass),
Self = AccessPermissions.Execute,
Friend = AccessPermissions.Execute,
Other = AccessPermissions.Execute)]
public sealed class MemberNobodyCanExecute
{
[Access(typeof(FriendlyClass),
Self = AccessPermissions.None,
Friend = AccessPermissions.None,
Other = AccessPermissions.None)]
public MyData Data = default;
public MyData Data2 = default;
[Access(typeof(FriendlyClass),
Self = AccessPermissions.None,
Friend = AccessPermissions.None,
Other = AccessPermissions.None)]
public void MyMethod() {}
public void MyMethod2() {}
public void TestMemberNobodyCanExecute(TypeNobodyCanExecute obj)
{
// None of these accesses should be allowed.
MyMethod();
this.MyMethod();
obj.MyMethod();
Data.MyMethod();
this.Data.MyMethod();
obj.Data.MyMethod();
Data.MyField.ToString();
this.Data.MyField.ToString();
obj.Data.MyField.ToString();
// All of these accesses should be fine.
MyMethod2();
this.MyMethod2();
obj.MyMethod2();
Data2.MyMethod();
this.Data2.MyMethod();
obj.Data2.MyMethod();
Data2.MyField.ToString();
this.Data2.ToString();
obj.Data2.ToString();
}
}
public sealed class FriendlyClass
{
public void TestTypeNobodyCanExecute(TypeNobodyCanExecute obj)
{
// We shouldn't be able to access any of these, even if we're a friend..
obj.MyMethod();
obj.Data.MyMethod();
obj.Data.MyField.ToString();
// We should be allowed to access all of these, we're friends!
obj.MyMethod2();
obj.Data2.MyMethod();
obj.Data2.MyField.ToString();
}
public void TestMemberNobodyCanExecute(MemberNobodyCanExecute obj)
{
// We shouldn't be able to access any of these, even if we're a friend..
obj.MyMethod();
obj.Data.MyMethod();
obj.Data.MyField.ToString();
// We should be allowed to access all of these, we're friends!
obj.MyMethod2();
obj.Data2.MyMethod();
obj.Data2.MyField.ToString();
}
}
public sealed class OtherClass
{
public void TestTypeNobodyCanExecute(TypeNobodyCanExecute obj)
{
// We shouldn't be able to access any of these, as 'other types' can't..
obj.MyMethod();
obj.Data.MyMethod();
obj.Data.MyField.ToString();
// We should be allowed to access all of these, they let others Execute!
obj.MyMethod2();
obj.Data2.MyMethod();
obj.Data2.MyField.ToString();
}
public void TestMemberNobodyCanExecute(MemberNobodyCanExecute obj)
{
// We shouldn't be able to access any of these, as 'other types' can't..
obj.MyMethod();
obj.Data.MyMethod();
obj.Data.MyField.ToString();
// We should be allowed to access all of these, they let others Execute!
obj.MyMethod2();
obj.Data2.MyMethod();
obj.Data2.MyField.ToString();
}
}";
await Verifier(code,
// AUTO-GENERATED DIAGNOSTICS BELOW //
// /0/Test0.cs(44,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'MyMethod' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(44, 9, 44, 19).WithArguments("an 'Execute' same-type", "MyMethod", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(45,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'MyMethod' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(45, 9, 45, 24).WithArguments("an 'Execute' same-type", "MyMethod", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(46,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'MyMethod' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(46, 9, 46, 23).WithArguments("an 'Execute' same-type", "MyMethod", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(48,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(48, 9, 48, 13).WithArguments("an 'Execute' same-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(49,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(49, 9, 49, 18).WithArguments("an 'Execute' same-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(50,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(50, 9, 50, 17).WithArguments("an 'Execute' same-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(52,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(52, 9, 52, 13).WithArguments("an 'Execute' same-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(53,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(53, 9, 53, 18).WithArguments("an 'Execute' same-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(54,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(54, 9, 54, 17).WithArguments("an 'Execute' same-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(96,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'MyMethod' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(96, 9, 96, 19).WithArguments("an 'Execute' same-type", "MyMethod", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(97,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'MyMethod' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(97, 9, 97, 24).WithArguments("an 'Execute' same-type", "MyMethod", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(98,9): error RA0002: Tried to perform an 'Execute' other-type access to member 'MyMethod' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(98, 9, 98, 23).WithArguments("an 'Execute' other-type", "MyMethod", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(100,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'Data' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(100, 9, 100, 13).WithArguments("an 'Execute' same-type", "Data", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(101,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'Data' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(101, 9, 101, 18).WithArguments("an 'Execute' same-type", "Data", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(102,9): error RA0002: Tried to perform an 'Execute' other-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(102, 9, 102, 17).WithArguments("an 'Execute' other-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(104,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'Data' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(104, 9, 104, 13).WithArguments("an 'Execute' same-type", "Data", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(105,9): error RA0002: Tried to perform an 'Execute' same-type access to member 'Data' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(105, 9, 105, 18).WithArguments("an 'Execute' same-type", "Data", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(106,9): error RA0002: Tried to perform an 'Execute' other-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(106, 9, 106, 17).WithArguments("an 'Execute' other-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(128,9): error RA0002: Tried to perform an 'Execute' friend-type access to member 'MyMethod' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(128, 9, 128, 23).WithArguments("an 'Execute' friend-type", "MyMethod", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(129,9): error RA0002: Tried to perform an 'Execute' friend-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(129, 9, 129, 17).WithArguments("an 'Execute' friend-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(130,9): error RA0002: Tried to perform an 'Execute' friend-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(130, 9, 130, 17).WithArguments("an 'Execute' friend-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(141,9): error RA0002: Tried to perform an 'Execute' friend-type access to member 'MyMethod' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(141, 9, 141, 23).WithArguments("an 'Execute' friend-type", "MyMethod", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(142,9): error RA0002: Tried to perform an 'Execute' friend-type access to member 'Data' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(142, 9, 142, 17).WithArguments("an 'Execute' friend-type", "Data", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(143,9): error RA0002: Tried to perform an 'Execute' friend-type access to member 'Data' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(143, 9, 143, 17).WithArguments("an 'Execute' friend-type", "Data", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(157,9): error RA0002: Tried to perform an 'Execute' other-type access to member 'MyMethod' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(157, 9, 157, 23).WithArguments("an 'Execute' other-type", "MyMethod", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(158,9): error RA0002: Tried to perform an 'Execute' other-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(158, 9, 158, 17).WithArguments("an 'Execute' other-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(159,9): error RA0002: Tried to perform an 'Execute' other-type access to member 'Data' in type 'TypeNobodyCanExecute', despite having no access. Type Permissions: ---------
VerifyCS.Diagnostic().WithSpan(159, 9, 159, 17).WithArguments("an 'Execute' other-type", "Data", "TypeNobodyCanExecute", "having no", "Type Permissions: ---------"),
// /0/Test0.cs(170,9): error RA0002: Tried to perform an 'Execute' other-type access to member 'MyMethod' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(170, 9, 170, 23).WithArguments("an 'Execute' other-type", "MyMethod", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(171,9): error RA0002: Tried to perform an 'Execute' other-type access to member 'Data' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(171, 9, 171, 17).WithArguments("an 'Execute' other-type", "Data", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------"),
// /0/Test0.cs(172,9): error RA0002: Tried to perform an 'Execute' other-type access to member 'Data' in type 'MemberNobodyCanExecute', despite having no access. Member Permissions: ---------
VerifyCS.Diagnostic().WithSpan(172, 9, 172, 17).WithArguments("an 'Execute' other-type", "Data", "MemberNobodyCanExecute", "having no", "Member Permissions: ---------")
);
}
}

View File

@@ -1,27 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\MSBuild\Robust.Properties.targets"/>
<Import Project="..\MSBuild\Robust.Engine.props"/>
<PropertyGroup>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageVersion Update="NUnit" Version="3.14.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzer.Testing"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.NUnit"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces"/>
<PackageReference Include="NUnit"/>
<PackageReference Include="NUnit3TestAdapter"/>
<PackageReference Include="NUnit.Analyzers"/>
<PackageReference Include="Microsoft.NET.Test.Sdk"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Robust.Analyzers\Robust.Analyzers.csproj"/>
</ItemGroup>
</Project>

View File

@@ -1,264 +0,0 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
using Robust.Shared.Analyzers.Implementation;
namespace Robust.Analyzers
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class AccessAnalyzer : DiagnosticAnalyzer
{
private const string AccessAttributeType = "Robust.Shared.Analyzers.AccessAttribute";
private const string RobustAutoGeneratedAttributeType = "Robust.Shared.Analyzers.RobustAutoGeneratedAttribute";
private const string PureAttributeType = "System.Diagnostics.Contracts.PureAttribute";
[SuppressMessage("ReSharper", "RS2008")]
private static readonly DiagnosticDescriptor AccessRule = new (
Diagnostics.IdAccess,
"Invalid access",
"Tried to perform {0} access to member '{1}' in type '{2}', despite {3} access. {4}.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to give the accessing type the correct access permissions.");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
ImmutableArray.Create(AccessRule);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.EnableConcurrentExecution();
context.RegisterOperationAction(CheckFriendship,
OperationKind.FieldReference,
OperationKind.PropertyReference,
OperationKind.MethodReference,
OperationKind.Invocation);
}
private void CheckFriendship(OperationAnalysisContext context)
{
var operation = context.Operation;
// The symbol representing the member being accessed.
ISymbol member;
// The operation to target when determining access type.
IOperation targetAccess;
switch (operation)
{
case IMemberReferenceOperation memberRef:
{
member = memberRef.Member;
targetAccess = memberRef.Parent;
break;
}
case IInvocationOperation invocation:
{
member = invocation.TargetMethod;
targetAccess = invocation;
break;
}
default:
return;
}
// Get the info of the type defining the member, so we can check the attributes later...
var accessedType = member.ContainingType;
// Get the attributes
var friendAttribute = context.Compilation.GetTypeByMetadataName(AccessAttributeType);
var autoGenAttribute = context.Compilation.GetTypeByMetadataName(RobustAutoGeneratedAttributeType);
// Get the type that is containing this expression, or, the type where this is happening.
if (context.ContainingSymbol?.ContainingType is not {} accessingType)
return;
// Should we ignore the access attempt due to the accessing type being auto-generated?
if (accessingType.GetAttributes().FirstOrDefault(a =>
a.AttributeClass != null &&
a.AttributeClass.Equals(autoGenAttribute, SymbolEqualityComparer.Default)) is { } attr)
{
return;
}
// Determine which type of access is happening here... Read, write or execute?
var accessAttempt = DetermineAccess(context, targetAccess, operation);
// Check whether this is a "self" access, including inheritors.
var selfAccess = InheritsFromOrEquals(accessingType, accessedType);
// Helper function to deduplicate attribute-checking code.
bool CheckAttributeFriendship(AttributeData attribute, bool isMemberAttribute)
{
// If the attribute isn't the friend attribute, we don't care about it.
if (!SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, friendAttribute))
return false;
var self = AccessAttribute.SelfDefaultPermissions;
var friends = AccessAttribute.FriendDefaultPermissions;
var others = AccessAttribute.OtherDefaultPermissions;
foreach (var kv in attribute.NamedArguments)
{
if (kv.Value.Value is not byte value)
continue;
var permissions = (AccessPermissions) value;
switch (kv.Key)
{
case nameof(AccessAttribute.Self):
{
self = permissions;
break;
}
case nameof(AccessAttribute.Friend):
{
friends = permissions;
break;
}
case nameof(AccessAttribute.Other):
{
others = permissions;
break;
}
default:
continue;
}
}
// By default, we will check the "other" permissions unless we find we're dealing with a friend or self.
var permissionCheck = others;
// Human-readable relation between accessing and accessed types.
var accessingRelation = "other-type";
if (!selfAccess)
{
// This is not a self-access, so we need to determine whether the accessing type is a friend.
// Check all types allowed in the friend attribute. (We assume there's only one constructor arg.)
var types = attribute.ConstructorArguments[0].Values;
foreach (var constant in types)
{
// Check if the value is a type...
if (constant.Value is not INamedTypeSymbol friendType)
continue;
// Check if the accessing type is specified in the attribute...
if (!InheritsFromOrEquals(accessingType, friendType))
continue;
// Set the permissions check to the friend permissions!
permissionCheck = friends;
accessingRelation = "friend-type";
break;
}
}
else
{
// Self-access, so simply set the permissions check to self.
permissionCheck = self;
accessingRelation = "same-type";
}
// If we allow this access, return! All is good.
if ((accessAttempt & permissionCheck) != 0)
return true;
// Access denied! Report an error.
context.ReportDiagnostic(
Diagnostic.Create(AccessRule, operation.Syntax.GetLocation(),
$"a{(accessAttempt == AccessPermissions.Execute ? "n" : "")} '{accessAttempt}' {accessingRelation}",
$"{member.Name}",
$"{accessedType.Name}",
$"{(permissionCheck == AccessPermissions.None ? "having no" : $"only having '{permissionCheck}'")}",
$"{(isMemberAttribute ? "Member" : "Type")} Permissions: {self.ToUnixPermissions()}{friends.ToUnixPermissions()}{others.ToUnixPermissions()}"));
// Only return ONE error.
return true;
}
// Check attributes in the member first, since they take priority and can override type restrictions.
foreach (var attribute in member.GetAttributes())
{
if(CheckAttributeFriendship(attribute, true))
return;
}
// Check attributes in the type containing the member last.
foreach (var attribute in accessedType.GetAttributes())
{
if(CheckAttributeFriendship(attribute, false))
return;
}
}
private static AccessPermissions DetermineAccess(OperationAnalysisContext context, IOperation operation, IOperation original)
{
switch (operation)
{
case IAssignmentOperation assign:
{
return assign.Target.Equals(original) ? AccessPermissions.Write : AccessPermissions.Read;
}
case IInvocationOperation invoke:
{
var pureAttribute = context.Compilation.GetTypeByMetadataName(PureAttributeType);
foreach (var attribute in invoke.TargetMethod.GetAttributes())
{
// Pure methods are treated as read accesses.
if (SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, pureAttribute))
return AccessPermissions.Read;
}
return AccessPermissions.Execute;
}
case IMemberReferenceOperation member:
{
return DetermineAccess(context, member.Parent, operation);
}
default:
{
return AccessPermissions.Read;
}
}
}
private bool InheritsFromOrEquals(INamedTypeSymbol type, INamedTypeSymbol baseType)
{
foreach (var otherType in GetBaseTypesAndThis(type))
{
if (SymbolEqualityComparer.Default.Equals(otherType, baseType))
return true;
}
return false;
}
private IEnumerable<INamedTypeSymbol> GetBaseTypesAndThis(INamedTypeSymbol namedType)
{
var current = namedType;
while (current != null)
{
yield return current;
current = current.BaseType;
}
}
}
}

View File

@@ -1,133 +0,0 @@
#nullable enable
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
using static Microsoft.CodeAnalysis.SymbolEqualityComparer;
namespace Robust.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class ByRefEventAnalyzer : DiagnosticAnalyzer
{
private const string ByRefAttribute = "Robust.Shared.GameObjects.ByRefEventAttribute";
private static readonly DiagnosticDescriptor ByRefEventSubscribedByValueRule = new(
Diagnostics.IdByRefEventSubscribedByValue,
"By-ref event subscribed to by value",
"Tried to subscribe to a by-ref event '{0}' by value.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure that methods subscribing to a ref event have the ref keyword for the event argument."
);
private static readonly DiagnosticDescriptor ByRefEventRaisedByValueRule = new(
Diagnostics.IdByRefEventRaisedByValue,
"By-ref event raised by value",
"Tried to raise a by-ref event '{0}' by value.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to use the ref keyword when raising ref events."
);
private static readonly DiagnosticDescriptor ByValueEventRaisedByRefRule = new(
Diagnostics.IdValueEventRaisedByRef,
"Value event raised by-ref",
"Tried to raise a value event '{0}' by-ref.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to not use the ref keyword when raising value events."
);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
ByRefEventSubscribedByValueRule,
ByRefEventRaisedByValueRule,
ByValueEventRaisedByRefRule
);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.EnableConcurrentExecution();
context.RegisterOperationAction(CheckEventRaise, OperationKind.Invocation);
}
private void CheckEventRaise(OperationAnalysisContext context)
{
if (context.Operation is not IInvocationOperation operation)
return;
var raiseMethods = context.Compilation
.GetTypeByMetadataName("Robust.Shared.GameObjects.EntitySystem")?
.GetMembers()
.Where(m => m.Name.Contains("RaiseLocalEvent") && m.Kind == SymbolKind.Method)
.Cast<IMethodSymbol>();
var busRaiseMethods = context.Compilation
.GetTypeByMetadataName("Robust.Shared.GameObjects.EntityEventBus")?
.GetMembers()
.Where(m => m.Name.Contains("RaiseLocalEvent") && m.Kind == SymbolKind.Method)
.Cast<IMethodSymbol>();
if (raiseMethods == null)
return;
if (busRaiseMethods != null)
raiseMethods = raiseMethods.Concat(busRaiseMethods);
if (!raiseMethods.Any(m => m.Equals(operation.TargetMethod.OriginalDefinition, Default)))
{
// If you try to do this normally by concatenating like busRaiseMethods above
// the analyzer does not run without any errors
// I don't know man
const string directedBusMethod = "Robust.Shared.GameObjects.IDirectedEventBus.RaiseLocalEvent";
if (!operation.TargetMethod.ToString().StartsWith(directedBusMethod))
return;
}
var arguments = operation.Arguments;
IArgumentOperation eventArgument;
switch (arguments.Length)
{
case 1:
eventArgument = arguments[0];
break;
case 2:
case 3:
eventArgument = arguments[1];
break;
default:
return;
}
var eventParameter = eventArgument.Parameter;
// TODO have a way to check generic type parameters
if (eventParameter == null ||
eventParameter.Type.SpecialType == SpecialType.System_Object ||
eventParameter.Type.TypeKind == TypeKind.TypeParameter)
{
return;
}
var byRefAttribute = context.Compilation.GetTypeByMetadataName(ByRefAttribute);
if (byRefAttribute == null)
return;
var isByRefEventType = eventParameter.Type
.GetAttributes()
.Any(attribute => attribute.AttributeClass?.Equals(byRefAttribute, Default) ?? false);
var parameterIsRef = eventParameter.RefKind == RefKind.Ref;
if (isByRefEventType != parameterIsRef)
{
var descriptor = isByRefEventType ? ByRefEventRaisedByValueRule : ByValueEventRaisedByRefRule;
var diagnostic = Diagnostic.Create(descriptor, eventArgument.Syntax.GetLocation(), eventParameter.Type);
context.ReportDiagnostic(diagnostic);
}
}
}

View File

@@ -1,293 +0,0 @@
#nullable enable
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Robust.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class DataDefinitionAnalyzer : DiagnosticAnalyzer
{
private const string DataDefinitionNamespace = "Robust.Shared.Serialization.Manager.Attributes.DataDefinitionAttribute";
private const string ImplicitDataDefinitionNamespace = "Robust.Shared.Serialization.Manager.Attributes.ImplicitDataDefinitionForInheritorsAttribute";
private const string DataFieldBaseNamespace = "Robust.Shared.Serialization.Manager.Attributes.DataFieldBaseAttribute";
private static readonly DiagnosticDescriptor DataDefinitionPartialRule = new(
Diagnostics.IdDataDefinitionPartial,
"Type must be partial",
"Type {0} is a DataDefinition but is not partial.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to mark any type that is a data definition as partial."
);
private static readonly DiagnosticDescriptor NestedDataDefinitionPartialRule = new(
Diagnostics.IdNestedDataDefinitionPartial,
"Type must be partial",
"Type {0} contains nested data definition {1} but is not partial.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to mark any type containing a nested data definition as partial."
);
private static readonly DiagnosticDescriptor DataFieldWritableRule = new(
Diagnostics.IdDataFieldWritable,
"Data field must not be readonly",
"Data field {0} in data definition {1} is readonly.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to remove the readonly modifier."
);
private static readonly DiagnosticDescriptor DataFieldPropertyWritableRule = new(
Diagnostics.IdDataFieldPropertyWritable,
"Data field property must have a setter",
"Data field property {0} in data definition {1} does not have a setter.",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to add a setter."
);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
DataDefinitionPartialRule, NestedDataDefinitionPartialRule, DataFieldWritableRule, DataFieldPropertyWritableRule
);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.ClassDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.StructDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.RecordDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.RecordStructDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataDefinition, SyntaxKind.InterfaceDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataField, SyntaxKind.FieldDeclaration);
context.RegisterSyntaxNodeAction(AnalyzeDataFieldProperty, SyntaxKind.PropertyDeclaration);
}
private void AnalyzeDataDefinition(SyntaxNodeAnalysisContext context)
{
if (context.Node is not TypeDeclarationSyntax declaration)
return;
var type = context.SemanticModel.GetDeclaredSymbol(declaration)!;
if (!IsDataDefinition(type))
return;
if (!IsPartial(declaration))
{
context.ReportDiagnostic(Diagnostic.Create(DataDefinitionPartialRule, declaration.Keyword.GetLocation(), type.Name));
}
var containingType = type.ContainingType;
while (containingType != null)
{
var containingTypeDeclaration = (TypeDeclarationSyntax) containingType.DeclaringSyntaxReferences[0].GetSyntax();
if (!IsPartial(containingTypeDeclaration))
{
context.ReportDiagnostic(Diagnostic.Create(NestedDataDefinitionPartialRule, containingTypeDeclaration.Keyword.GetLocation(), containingType.Name, type.Name));
}
containingType = containingType.ContainingType;
}
}
private void AnalyzeDataField(SyntaxNodeAnalysisContext context)
{
if (context.Node is not FieldDeclarationSyntax field)
return;
var typeDeclaration = field.FirstAncestorOrSelf<TypeDeclarationSyntax>();
if (typeDeclaration == null)
return;
var type = context.SemanticModel.GetDeclaredSymbol(typeDeclaration)!;
if (!IsDataDefinition(type))
return;
foreach (var variable in field.Declaration.Variables)
{
var fieldSymbol = context.SemanticModel.GetDeclaredSymbol(variable);
if (fieldSymbol == null)
continue;
if (IsReadOnlyDataField(type, fieldSymbol))
{
context.ReportDiagnostic(Diagnostic.Create(DataFieldWritableRule, context.Node.GetLocation(), fieldSymbol.Name, type.Name));
}
}
}
private void AnalyzeDataFieldProperty(SyntaxNodeAnalysisContext context)
{
if (context.Node is not PropertyDeclarationSyntax property)
return;
var typeDeclaration = property.FirstAncestorOrSelf<TypeDeclarationSyntax>();
if (typeDeclaration == null)
return;
var type = context.SemanticModel.GetDeclaredSymbol(typeDeclaration)!;
if (!IsDataDefinition(type) || type.IsRecord || type.IsValueType)
return;
var propertySymbol = context.SemanticModel.GetDeclaredSymbol(property);
if (propertySymbol == null)
return;
if (IsReadOnlyDataField(type, propertySymbol))
{
context.ReportDiagnostic(Diagnostic.Create(DataFieldPropertyWritableRule, context.Node.GetLocation(), propertySymbol.Name, type.Name));
}
}
private static bool IsReadOnlyDataField(ITypeSymbol type, ISymbol field)
{
if (!IsDataField(field, out _, out _))
return false;
return IsReadOnlyMember(type, field);
}
private static bool IsPartial(TypeDeclarationSyntax type)
{
return type.Modifiers.IndexOf(SyntaxKind.PartialKeyword) != -1;
}
private static bool IsDataDefinition(ITypeSymbol? type)
{
if (type == null)
return false;
return HasAttribute(type, DataDefinitionNamespace) ||
IsImplicitDataDefinition(type);
}
private static bool IsDataField(ISymbol member, out ITypeSymbol type, out AttributeData attribute)
{
// TODO data records and other attributes
if (member is IFieldSymbol field)
{
foreach (var attr in field.GetAttributes())
{
if (attr.AttributeClass != null && Inherits(attr.AttributeClass, DataFieldBaseNamespace))
{
type = field.Type;
attribute = attr;
return true;
}
}
}
else if (member is IPropertySymbol property)
{
foreach (var attr in property.GetAttributes())
{
if (attr.AttributeClass != null && Inherits(attr.AttributeClass, DataFieldBaseNamespace))
{
type = property.Type;
attribute = attr;
return true;
}
}
}
type = null!;
attribute = null!;
return false;
}
private static bool Inherits(ITypeSymbol type, string parent)
{
foreach (var baseType in GetBaseTypes(type))
{
if (baseType.ToDisplayString() == parent)
return true;
}
return false;
}
private static bool IsReadOnlyMember(ITypeSymbol type, ISymbol member)
{
if (member is IFieldSymbol field)
{
return field.IsReadOnly;
}
else if (member is IPropertySymbol property)
{
if (property.SetMethod == null)
return true;
if (property.SetMethod.IsInitOnly)
return type.IsReferenceType;
return false;
}
return false;
}
private static bool HasAttribute(ITypeSymbol type, string attributeName)
{
foreach (var attribute in type.GetAttributes())
{
if (attribute.AttributeClass?.ToDisplayString() == attributeName)
return true;
}
return false;
}
private static bool IsImplicitDataDefinition(ITypeSymbol type)
{
if (HasAttribute(type, ImplicitDataDefinitionNamespace))
return true;
foreach (var baseType in GetBaseTypes(type))
{
if (HasAttribute(baseType, ImplicitDataDefinitionNamespace))
return true;
}
foreach (var @interface in type.AllInterfaces)
{
if (IsImplicitDataDefinitionInterface(@interface))
return true;
}
return false;
}
private static bool IsImplicitDataDefinitionInterface(ITypeSymbol @interface)
{
if (HasAttribute(@interface, ImplicitDataDefinitionNamespace))
return true;
foreach (var subInterface in @interface.AllInterfaces)
{
if (HasAttribute(subInterface, ImplicitDataDefinitionNamespace))
return true;
}
return false;
}
private static IEnumerable<ITypeSymbol> GetBaseTypes(ITypeSymbol type)
{
var baseType = type.BaseType;
while (baseType != null)
{
yield return baseType;
baseType = baseType.BaseType;
}
}
}

View File

@@ -1,168 +0,0 @@
#nullable enable
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxKind;
using static Robust.Analyzers.Diagnostics;
namespace Robust.Analyzers;
[ExportCodeFixProvider(LanguageNames.CSharp)]
public sealed class DefinitionFixer : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(
IdDataDefinitionPartial, IdNestedDataDefinitionPartial, IdDataFieldWritable, IdDataFieldPropertyWritable
);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
foreach (var diagnostic in context.Diagnostics)
{
switch (diagnostic.Id)
{
case IdDataDefinitionPartial:
return RegisterPartialTypeFix(context, diagnostic);
case IdNestedDataDefinitionPartial:
return RegisterPartialTypeFix(context, diagnostic);
case IdDataFieldWritable:
return RegisterDataFieldFix(context, diagnostic);
case IdDataFieldPropertyWritable:
return RegisterDataFieldPropertyFix(context, diagnostic);
}
}
return Task.CompletedTask;
}
public override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
private static async Task RegisterPartialTypeFix(CodeFixContext context, Diagnostic diagnostic)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
var span = diagnostic.Location.SourceSpan;
var token = root?.FindToken(span.Start).Parent?.AncestorsAndSelf().OfType<TypeDeclarationSyntax>().First();
if (token == null)
return;
context.RegisterCodeFix(CodeAction.Create(
"Make type partial",
c => MakeDataDefinitionPartial(context.Document, token, c),
"Make type partial"
), diagnostic);
}
private static async Task<Document> MakeDataDefinitionPartial(Document document, TypeDeclarationSyntax declaration, CancellationToken cancellation)
{
var root = (CompilationUnitSyntax?) await document.GetSyntaxRootAsync(cancellation);
var token = SyntaxFactory.Token(PartialKeyword);
var newDeclaration = declaration.AddModifiers(token);
root = root!.ReplaceNode(declaration, newDeclaration);
return document.WithSyntaxRoot(root);
}
private static async Task RegisterDataFieldFix(CodeFixContext context, Diagnostic diagnostic)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
var span = diagnostic.Location.SourceSpan;
var field = root?.FindToken(span.Start).Parent?.AncestorsAndSelf().OfType<FieldDeclarationSyntax>().FirstOrDefault();
if (field == null)
return;
context.RegisterCodeFix(CodeAction.Create(
"Make data field writable",
c => MakeFieldWritable(context.Document, field, c),
"Make data field writable"
), diagnostic);
}
private static async Task RegisterDataFieldPropertyFix(CodeFixContext context, Diagnostic diagnostic)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken);
var span = diagnostic.Location.SourceSpan;
var property = root?.FindToken(span.Start).Parent?.AncestorsAndSelf().OfType<PropertyDeclarationSyntax>().FirstOrDefault();
if (property == null)
return;
context.RegisterCodeFix(CodeAction.Create(
"Make data field writable",
c => MakePropertyWritable(context.Document, property, c),
"Make data field writable"
), diagnostic);
}
private static async Task<Document> MakeFieldWritable(Document document, FieldDeclarationSyntax declaration, CancellationToken cancellation)
{
var root = (CompilationUnitSyntax?) await document.GetSyntaxRootAsync(cancellation);
var token = declaration.Modifiers.First(t => t.IsKind(ReadOnlyKeyword));
var newDeclaration = declaration.WithModifiers(declaration.Modifiers.Remove(token));
root = root!.ReplaceNode(declaration, newDeclaration);
return document.WithSyntaxRoot(root);
}
private static async Task<Document> MakePropertyWritable(Document document, PropertyDeclarationSyntax declaration, CancellationToken cancellation)
{
var root = (CompilationUnitSyntax?) await document.GetSyntaxRootAsync(cancellation);
var newDeclaration = declaration;
var privateSet = newDeclaration
.AccessorList?
.Accessors
.FirstOrDefault(s => s.IsKind(SetAccessorDeclaration) || s.IsKind(InitAccessorDeclaration));
if (newDeclaration.AccessorList != null && privateSet != null)
{
newDeclaration = newDeclaration.WithAccessorList(
newDeclaration.AccessorList.WithAccessors(
newDeclaration.AccessorList.Accessors.Remove(privateSet)
)
);
}
AccessorDeclarationSyntax setter;
if (declaration.Modifiers.Any(m => m.IsKind(PrivateKeyword)))
{
setter = SyntaxFactory.AccessorDeclaration(
SetAccessorDeclaration,
default,
default,
SyntaxFactory.Token(SetKeyword),
default,
default,
SyntaxFactory.Token(SemicolonToken)
);
}
else
{
setter = SyntaxFactory.AccessorDeclaration(
SetAccessorDeclaration,
default,
SyntaxFactory.TokenList(SyntaxFactory.Token(PrivateKeyword)),
SyntaxFactory.Token(SetKeyword),
default,
default,
SyntaxFactory.Token(SemicolonToken)
);
}
newDeclaration = newDeclaration.AddAccessorListAccessors(setter);
root = root!.ReplaceNode(declaration, newDeclaration);
return document.WithSyntaxRoot(root);
}
}

View File

@@ -6,24 +6,8 @@ public static class Diagnostics
{
public const string IdExplicitInterface = "RA0000";
public const string IdSerializable = "RA0001";
public const string IdAccess = "RA0002";
public const string IdFriend = "RA0002";
public const string IdExplicitVirtual = "RA0003";
public const string IdTaskResult = "RA0004";
public const string IdUseGenericVariant = "RA0005";
public const string IdUseGenericVariantInvalidUsage = "RA0006";
public const string IdUseGenericVariantAttributeValueError = "RA0007";
public const string IdNotNullableFlagNotSet = "RA0008";
public const string IdInvalidNotNullableFlagValue = "RA0009";
public const string IdInvalidNotNullableFlagImplementation = "RA0010";
public const string IdInvalidNotNullableFlagType = "RA0011";
public const string IdNotNullableFlagValueType = "RA0012";
public const string IdByRefEventSubscribedByValue = "RA0013";
public const string IdByRefEventRaisedByValue = "RA0015";
public const string IdValueEventRaisedByRef = "RA0016";
public const string IdDataDefinitionPartial = "RA0017";
public const string IdNestedDataDefinitionPartial = "RA0018";
public const string IdDataFieldWritable = "RA0019";
public const string IdDataFieldPropertyWritable = "RA0020";
public static SuppressionDescriptor MeansImplicitAssignment =>
new SuppressionDescriptor("RADC1000", "CS0649", "Marked as implicitly assigned.");

View File

@@ -0,0 +1,129 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Robust.Analyzers
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class FriendAnalyzer : DiagnosticAnalyzer
{
const string FriendAttribute = "Robust.Shared.Analyzers.FriendAttribute";
[SuppressMessage("ReSharper", "RS2008")]
private static readonly DiagnosticDescriptor Rule = new (
Diagnostics.IdFriend,
"Tried to access friend-only member",
"Tried to access member \"{0}\" in class \"{1}\" which can only be accessed by friend classes",
"Usage",
DiagnosticSeverity.Error,
true,
"Make sure to specify the accessing class in the friends attribute.");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(CheckFriendship, SyntaxKind.SimpleMemberAccessExpression);
}
private void CheckFriendship(SyntaxNodeAnalysisContext context)
{
if (context.Node is not MemberAccessExpressionSyntax memberAccess)
return;
// We only do something if our parent is one of a few types.
switch (context.Node.Parent)
{
// If we're being assigned...
case AssignmentExpressionSyntax assignParent:
{
if (assignParent.Left != memberAccess)
return;
break;
}
// If we're being invoked...
case InvocationExpressionSyntax:
break;
// Otherwise, do nothing.
default:
return;
}
// Get the friend attribute
var friendAttr = context.Compilation.GetTypeByMetadataName(FriendAttribute);
// Get the type that is containing this expression, or, the class where this is happening.
if (context.ContainingSymbol?.ContainingType is not { } containingType)
return;
// We check all of our children and get only the identifiers.
foreach (var identifier in memberAccess.ChildNodes().Select(node => node as IdentifierNameSyntax))
{
if (identifier == null) continue;
// Get the type info of the identifier, so we can check the attributes...
if (context.SemanticModel.GetTypeInfo(identifier).ConvertedType is not { } type)
continue;
// Same-type access is always fine.
if (SymbolEqualityComparer.Default.Equals(type, containingType))
continue;
// Finally, get all attributes of the type, to check if we have any friend classes.
foreach (var attribute in type.GetAttributes())
{
// If the attribute isn't the friend attribute, continue.
if (!SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, friendAttr))
continue;
// Check all types allowed in the friend attribute. (We assume there's only one constructor arg.)
foreach (var constant in attribute.ConstructorArguments[0].Values)
{
// Check if the value is a type...
if (constant.Value is not INamedTypeSymbol t)
continue;
// If we find that the containing class is specified in the attribute, return! All is good.
if (InheritsFromOrEquals(containingType, t))
return;
}
// Not in a friend class! Report an error.
context.ReportDiagnostic(
Diagnostic.Create(Rule, context.Node.GetLocation(),
$"{context.Node.ToString().Split('.').LastOrDefault()}", $"{type.Name}"));
}
}
}
private bool InheritsFromOrEquals(INamedTypeSymbol type, INamedTypeSymbol baseType)
{
foreach (var otherType in GetBaseTypesAndThis(type))
{
if (SymbolEqualityComparer.Default.Equals(otherType, baseType))
return true;
}
return false;
}
private IEnumerable<INamedTypeSymbol> GetBaseTypesAndThis(INamedTypeSymbol namedType)
{
var current = namedType;
while (current != null)
{
yield return current;
current = current.BaseType;
}
}
}
}

View File

@@ -1,171 +0,0 @@
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
namespace Robust.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class NotNullableFlagAnalyzer : DiagnosticAnalyzer
{
private const string Attribute = "Robust.Shared.Analyzers.NotNullableFlagAttribute";
private static readonly DiagnosticDescriptor NotNullableNotSetRule = new (
Diagnostics.IdNotNullableFlagNotSet,
"Not Nullable Flag not set",
"Class type parameter {0} is not annotated as nullable and notNullableOverride is not set to true",
"Usage",
DiagnosticSeverity.Error,
true,
"Assign true to notNullableOverride or specify the type parameter as nullable.");
private static readonly DiagnosticDescriptor InvalidNotNullableValueRule = new (
Diagnostics.IdInvalidNotNullableFlagValue,
"Not Nullable Flag wrongfully set",
"Class type parameter {0} is annotated as nullable but notNullableOverride is set to true",
"Usage",
DiagnosticSeverity.Error,
true,
"Remove the true assignment to notNullableOverride or remove the nullable specifier of the type parameter.");
private static readonly DiagnosticDescriptor InvalidNotNullableImplementationRule = new (
Diagnostics.IdInvalidNotNullableFlagImplementation,
"Invalid NotNullable flag implementation.",
"NotNullable flag is either not typed as bool, or does not have a default value equaling false",
"Usage",
DiagnosticSeverity.Error,
true,
"Ensure that the notNullable flag is typed bool and has false set as a default value.");
private static readonly DiagnosticDescriptor InvalidNotNullableTypeRule = new (
Diagnostics.IdInvalidNotNullableFlagType,
"Failed to resolve type parameter",
"Failed to resolve type parameter \"{0}\".",
"Usage",
DiagnosticSeverity.Error,
true,
"Use nameof to avoid typos.");
private static readonly DiagnosticDescriptor NotNullableFlagValueTypeRule = new (
Diagnostics.IdNotNullableFlagValueType,
"NotNullable flag not supported for value types.",
"Value types as generic arguments are not supported for NotNullable flags",
"Usage",
DiagnosticSeverity.Error,
true,
"Nullable value types are distinct at runtime when inspected with reflection. Therefore they are not supported for NotNullable flags.");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
ImmutableArray.Create(
NotNullableNotSetRule,
InvalidNotNullableValueRule,
InvalidNotNullableImplementationRule,
InvalidNotNullableTypeRule,
NotNullableFlagValueTypeRule);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.EnableConcurrentExecution();
context.RegisterOperationAction(CheckNotNullableFlag, OperationKind.Invocation);
}
private bool TryGetTypeArgument(IMethodSymbol methodSymbol, string typeParamName, out ITypeSymbol typeArgument)
{
for (var index = 0; index < methodSymbol.TypeParameters.Length; index++)
{
if (methodSymbol.TypeParameters[index].Name != typeParamName)
continue;
typeArgument = methodSymbol.TypeArguments[index];
return true;
}
typeArgument = null;
return false;
}
private void CheckNotNullableFlag(OperationAnalysisContext context)
{
if (context.Operation is not IInvocationOperation invocationOperation || !invocationOperation.TargetMethod.IsGenericMethod)
return;
var attribute = context.Compilation.GetTypeByMetadataName(Attribute);
var @bool = context.Compilation.GetSpecialType(SpecialType.System_Boolean);
foreach (var argument in invocationOperation.Arguments)
{
if(argument.Parameter == null) continue;
foreach (var attributeData in argument.Parameter.GetAttributes())
{
if (!SymbolEqualityComparer.Default.Equals(attributeData.AttributeClass, attribute))
continue;
if (!SymbolEqualityComparer.Default.Equals(argument.Parameter.Type, @bool) ||
!argument.Parameter.HasExplicitDefaultValue ||
argument.Parameter.ExplicitDefaultValue as bool? != false)
{
context.ReportDiagnostic(Diagnostic.Create(
InvalidNotNullableImplementationRule,
argument.Parameter.Locations[0]));
break;
}
if (!TryGetTypeArgument(invocationOperation.TargetMethod,
attributeData.ConstructorArguments[0].Value as string, out var typeArgument))
{
context.ReportDiagnostic(Diagnostic.Create(
InvalidNotNullableTypeRule,
argument.Parameter.Locations[0],
attributeData.ConstructorArguments[0].Value as string));
break;
}
//until i find a way to implement it sanely, generic calls are exempt from this attribute
if(typeArgument is ITypeParameterSymbol) break;
//dont ask me why, argument.ConstantValue just straight up doesnt work.
//i still kept it in here as a fallback, incase it ever starts working again lol -<paul
var constantValue = (argument.Value as ILiteralOperation)?.ConstantValue ?? argument.ConstantValue;
if (typeArgument.IsValueType)
{
if (argument.ArgumentKind != ArgumentKind.DefaultValue)
{
//todo diagnostic only use for struct types
context.ReportDiagnostic(Diagnostic.Create(
NotNullableFlagValueTypeRule,
argument.Syntax.GetLocation()));
}
break;
}
if (typeArgument.NullableAnnotation == NullableAnnotation.None ||
(argument.ArgumentKind != ArgumentKind.DefaultValue && !constantValue.HasValue))
break;
var flagValue = argument.ArgumentKind != ArgumentKind.DefaultValue ||
constantValue.Value as bool? == true;
var nullable = typeArgument.NullableAnnotation == NullableAnnotation.Annotated;
if (nullable && flagValue)
{
context.ReportDiagnostic(Diagnostic.Create(InvalidNotNullableValueRule,
argument.Syntax.GetLocation(),
typeArgument));
}
else if (!nullable && !flagValue)
{
context.ReportDiagnostic(Diagnostic.Create(NotNullableNotSetRule,
argument.Syntax.GetLocation(),
typeArgument));
}
break;
}
}
}
}

View File

@@ -1,238 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
namespace Robust.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class PreferGenericVariantAnalyzer : DiagnosticAnalyzer
{
private const string AttributeType = "Robust.Shared.Analyzers.PreferGenericVariantAttribute";
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
UseGenericVariantDescriptor, UseGenericVariantInvalidUsageDescriptor,
UseGenericVariantAttributeValueErrorDescriptor);
private static readonly DiagnosticDescriptor UseGenericVariantDescriptor = new(
Diagnostics.IdUseGenericVariant,
"Consider using the generic variant of this method",
"Consider using the generic variant of this method to avoid potential allocations",
"Usage",
DiagnosticSeverity.Warning,
true,
"Consider using the generic variant of this method to avoid potential allocations.");
private static readonly DiagnosticDescriptor UseGenericVariantInvalidUsageDescriptor = new(
Diagnostics.IdUseGenericVariantInvalidUsage,
"Invalid generic variant provided",
"Generic variant provided mismatches the amount of type parameters of non-generic variant",
"Usage",
DiagnosticSeverity.Error,
true,
"The non-generic variant should have at least as many type parameter at the beginning of the method as there are generic type parameters on the generic variant.");
private static readonly DiagnosticDescriptor UseGenericVariantAttributeValueErrorDescriptor = new(
Diagnostics.IdUseGenericVariantAttributeValueError,
"Failed resolving generic variant value",
"Failed resolving generic variant value: {0}",
"Usage",
DiagnosticSeverity.Error,
true,
"Consider using nameof to avoid any typos.");
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.ReportDiagnostics | GeneratedCodeAnalysisFlags.Analyze);
context.EnableConcurrentExecution();
context.RegisterOperationAction(CheckForGenericVariant, OperationKind.Invocation);
}
private void CheckForGenericVariant(OperationAnalysisContext obj)
{
if(obj.Operation is not IInvocationOperation invocationOperation) return;
var preferGenericAttribute = obj.Compilation.GetTypeByMetadataName(AttributeType);
string genericVariant = null;
AttributeData foundAttribute = null;
foreach (var attribute in invocationOperation.TargetMethod.GetAttributes())
{
if (!SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, preferGenericAttribute))
continue;
genericVariant = attribute.ConstructorArguments[0].Value as string ?? invocationOperation.TargetMethod.Name;
foundAttribute = attribute;
break;
}
if(genericVariant == null) return;
var maxTypeParams = 0;
var typeTypeSymbol = obj.Compilation.GetTypeByMetadataName("System.Type");
foreach (var parameter in invocationOperation.TargetMethod.Parameters)
{
if(!SymbolEqualityComparer.Default.Equals(parameter.Type, typeTypeSymbol)) break;
maxTypeParams++;
}
if (maxTypeParams == 0)
{
obj.ReportDiagnostic(
Diagnostic.Create(UseGenericVariantInvalidUsageDescriptor,
foundAttribute.ApplicationSyntaxReference?.GetSyntax().GetLocation()));
return;
}
IMethodSymbol genericVariantMethod = null;
foreach (var member in invocationOperation.TargetMethod.ContainingType.GetMembers())
{
if (member is not IMethodSymbol methodSymbol
|| methodSymbol.Name != genericVariant
|| !methodSymbol.IsGenericMethod
|| methodSymbol.TypeParameters.Length > maxTypeParams
|| methodSymbol.Parameters.Length > invocationOperation.TargetMethod.Parameters.Length - methodSymbol.TypeParameters.Length
) continue;
var typeParamCount = methodSymbol.TypeParameters.Length;
var failedParamComparison = false;
var objType = obj.Compilation.GetSpecialType(SpecialType.System_Object);
for (int i = 0; i < methodSymbol.Parameters.Length; i++)
{
if (methodSymbol.Parameters[i].Type is ITypeParameterSymbol && SymbolEqualityComparer.Default.Equals(invocationOperation.TargetMethod.Parameters[i + typeParamCount].Type, objType))
continue;
if (!SymbolEqualityComparer.Default.Equals(methodSymbol.Parameters[i].Type,
invocationOperation.TargetMethod.Parameters[i + typeParamCount].Type))
{
failedParamComparison = true;
break;
}
}
if(failedParamComparison) continue;
genericVariantMethod = methodSymbol;
}
if (genericVariantMethod == null)
{
obj.ReportDiagnostic(Diagnostic.Create(
UseGenericVariantAttributeValueErrorDescriptor,
foundAttribute.ApplicationSyntaxReference?.GetSyntax().GetLocation(),
genericVariant));
return;
}
var typeOperands = new string[genericVariantMethod.TypeParameters.Length];
for (var i = 0; i < genericVariantMethod.TypeParameters.Length; i++)
{
switch (invocationOperation.Arguments[i].Value)
{
//todo figure out if ILocalReferenceOperation, IPropertyReferenceOperation or IFieldReferenceOperation is referencing static typeof assignments
case ITypeOfOperation typeOfOperation:
typeOperands[i] = typeOfOperation.TypeOperand.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
continue;
default:
return;
}
}
obj.ReportDiagnostic(Diagnostic.Create(
UseGenericVariantDescriptor,
invocationOperation.Syntax.GetLocation(),
ImmutableDictionary.CreateRange(new Dictionary<string, string>()
{
{"typeOperands", string.Join(",", typeOperands)}
})));
}
}
[ExportCodeFixProvider(LanguageNames.CSharp)]
public class PreferGenericVariantCodeFixProvider : CodeFixProvider
{
private static string Title(string method, string[] types) => $"Use {method}<{string.Join(",", types)}>.";
public override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var root = await context.Document.GetSyntaxRootAsync();
if(root == null) return;
foreach (var diagnostic in context.Diagnostics)
{
if (!diagnostic.Properties.TryGetValue("typeOperands", out var typeOperandsRaw)
|| typeOperandsRaw == null) continue;
var node = root.FindNode(diagnostic.Location.SourceSpan);
if (node is ArgumentSyntax argumentSyntax)
node = argumentSyntax.Expression;
if(node is not InvocationExpressionSyntax invocationExpression)
continue;
var typeOperands = typeOperandsRaw.Split(',');
context.RegisterCodeFix(
CodeAction.Create(
Title(invocationExpression.Expression.ToString(), typeOperands),
c => FixAsync(context.Document, invocationExpression, typeOperands, c),
Title(invocationExpression.Expression.ToString(), typeOperands)),
diagnostic);
}
}
private async Task<Document> FixAsync(
Document contextDocument,
InvocationExpressionSyntax invocationExpression,
string[] typeOperands,
CancellationToken cancellationToken)
{
var memberAccess = (MemberAccessExpressionSyntax)invocationExpression.Expression;
var root = (CompilationUnitSyntax) await contextDocument.GetSyntaxRootAsync(cancellationToken);
var arguments = new ArgumentSyntax[invocationExpression.ArgumentList.Arguments.Count - typeOperands.Length];
var types = new TypeSyntax[typeOperands.Length];
for (int i = 0; i < typeOperands.Length; i++)
{
types[i] = ((TypeOfExpressionSyntax)invocationExpression.ArgumentList.Arguments[i].Expression).Type;
}
Array.Copy(
invocationExpression.ArgumentList.Arguments.ToArray(),
typeOperands.Length,
arguments,
0,
arguments.Length);
memberAccess = memberAccess.WithName(SyntaxFactory.GenericName(memberAccess.Name.Identifier,
SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(types))));
root = root!.ReplaceNode(invocationExpression,
invocationExpression.WithArgumentList(invocationExpression.ArgumentList.WithArguments(SyntaxFactory.SeparatedList(arguments)))
.WithExpression(memberAccess));
return contextDocument.WithSyntaxRoot(root);
}
public override ImmutableArray<string> FixableDiagnosticIds =>
ImmutableArray.Create(Diagnostics.IdUseGenericVariant);
}

View File

@@ -3,29 +3,12 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>10</LangVersion>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" />
</ItemGroup>
<ItemGroup>
<!-- Needed for NotNullableFlagAnalyzer. -->
<Compile Include="..\Robust.Shared\Analyzers\NotNullableFlagAttribute.cs" />
</ItemGroup>
<ItemGroup>
<!-- Needed for FriendAnalyzer. -->
<Compile Include="..\Robust.Shared\Analyzers\AccessAttribute.cs" />
<Compile Include="..\Robust.Shared\Analyzers\AccessPermissions.cs" />
</ItemGroup>
<ItemGroup>
<!-- Needed for PreferGenericVariantAnalyzer. -->
<Compile Include="..\Robust.Shared\Analyzers\PreferGenericVariantAttribute.cs" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="3.8.0" />
</ItemGroup>
</Project>

View File

@@ -1,44 +0,0 @@
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
namespace Robust.Analyzers;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class TaskResultAnalyzer : DiagnosticAnalyzer
{
[SuppressMessage("ReSharper", "RS2008")]
private static readonly DiagnosticDescriptor ResultRule = new DiagnosticDescriptor(
Diagnostics.IdTaskResult,
"Risk of deadlock from accessing Task<T>.Result",
"Accessing Task<T>.Result is dangerous and can cause deadlocks in some contexts. If you understand how this works and are certain that you aren't causing a deadlock here, mute this error with #pragma.",
"Usage",
DiagnosticSeverity.Error,
true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
ImmutableArray.Create(ResultRule);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterOperationAction(Check, OperationKind.PropertyReference);
}
private static void Check(OperationAnalysisContext context)
{
var taskType = context.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task`1");
var operation = (IPropertyReferenceOperation) context.Operation;
var member = operation.Member;
if (member.Name == "Result" && taskType.Equals(member.ContainingType.ConstructedFrom, SymbolEqualityComparer.Default))
{
var diag = Diagnostic.Create(ResultRule, operation.Syntax.GetLocation());
context.ReportDiagnostic(diag);
}
}
}

View File

@@ -1,62 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using BenchmarkDotNet.Analysers;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.EventProcessors;
using BenchmarkDotNet.Exporters;
using BenchmarkDotNet.Filters;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Order;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Validators;
using Robust.Benchmarks.Exporters;
namespace Robust.Benchmarks.Configs;
public sealed class DefaultSQLConfig : IConfig
{
public static readonly IConfig Instance = new DefaultSQLConfig();
private DefaultSQLConfig(){}
public IEnumerable<IExporter> GetExporters()
{
yield return SQLExporter.Default;
}
public IEnumerable<IColumnProvider> GetColumnProviders() => DefaultConfig.Instance.GetColumnProviders();
public IEnumerable<ILogger> GetLoggers() => DefaultConfig.Instance.GetLoggers();
public IEnumerable<IDiagnoser> GetDiagnosers() => DefaultConfig.Instance.GetDiagnosers();
public IEnumerable<IAnalyser> GetAnalysers() => DefaultConfig.Instance.GetAnalysers();
public IEnumerable<Job> GetJobs() => DefaultConfig.Instance.GetJobs();
public IEnumerable<IValidator> GetValidators() => DefaultConfig.Instance.GetValidators();
public IEnumerable<HardwareCounter> GetHardwareCounters() => DefaultConfig.Instance.GetHardwareCounters();
public IEnumerable<IFilter> GetFilters() => DefaultConfig.Instance.GetFilters();
public IEnumerable<BenchmarkLogicalGroupRule> GetLogicalGroupRules() => DefaultConfig.Instance.GetLogicalGroupRules();
public IEnumerable<EventProcessor> GetEventProcessors() => DefaultConfig.Instance.GetEventProcessors();
public IEnumerable<IColumnHidingRule> GetColumnHidingRules() => DefaultConfig.Instance.GetColumnHidingRules();
public IOrderer Orderer => DefaultConfig.Instance.Orderer!;
public ICategoryDiscoverer? CategoryDiscoverer => DefaultConfig.Instance.CategoryDiscoverer;
public SummaryStyle SummaryStyle => DefaultConfig.Instance.SummaryStyle;
public ConfigUnionRule UnionRule => DefaultConfig.Instance.UnionRule;
public string ArtifactsPath => DefaultConfig.Instance.ArtifactsPath;
public CultureInfo CultureInfo => DefaultConfig.Instance.CultureInfo!;
public ConfigOptions Options => DefaultConfig.Instance.Options;
public TimeSpan BuildTimeout => DefaultConfig.Instance.BuildTimeout;
public IReadOnlyList<Conclusion> ConfigAnalysisConclusion => DefaultConfig.Instance.ConfigAnalysisConclusion;
}

View File

@@ -1,54 +0,0 @@
using BenchmarkDotNet.Attributes;
using JetBrains.Annotations;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
[Virtual]
public partial class AddRemoveComponentBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
[UsedImplicitly]
[Params(1, 10, 100, 1000)]
public int N;
[GlobalSetup]
public void GlobalSetup()
{
_simulation = RobustServerSimulation
.NewSimulation()
.RegisterComponents(f => f.RegisterClass<A>())
.InitializeInstance();
_entityManager = _simulation.Resolve<IEntityManager>();
var coords = new MapCoordinates(0, 0, new MapId(1));
_simulation.AddMap(coords.MapId);
for (var i = 0; i < N; i++)
{
_entityManager.SpawnEntity(null, coords);
}
}
[Benchmark]
public void AddRemoveComponent()
{
for (var i = 2; i <= N+1; i++)
{
var uid = new EntityUid(i);
_entityManager.AddComponent<A>(uid);
_entityManager.RemoveComponent<A>(uid);
}
}
[ComponentProtoName("A")]
public sealed partial class A : Component
{
}
}

View File

@@ -1,225 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using BenchmarkDotNet.Attributes;
using Robust.Shared.GameObjects;
namespace Robust.Benchmarks.EntityManager;
public class ComponentIndexBenchmark
{
// Just a bunch of types to bloat the test lists.
private readonly CompIndexFetcher _compIndexFetcherDirect;
private readonly IFetcher _compIndexFetcher;
private readonly DictFetcher _dictFetcherDirect;
private readonly IFetcher _dictFetcher;
public ComponentIndexBenchmark()
{
_compIndexFetcherDirect = new CompIndexFetcher();
_compIndexFetcher = _compIndexFetcherDirect;
_dictFetcherDirect = new DictFetcher();
_dictFetcher = _dictFetcherDirect;
}
[GlobalSetup]
public void Setup()
{
var types = typeof(ComponentIndexBenchmark)
.GetNestedTypes(BindingFlags.NonPublic)
.Where(t => t.Name.StartsWith("TestType"))
.ToArray();
_compIndexFetcher.Init(types);
_dictFetcher.Init(types);
}
[Benchmark]
public int BenchCompIndex() => _compIndexFetcher.Get<TestType50>();
[Benchmark]
public int BenchDict() => _dictFetcher.Get<TestType50>();
[Benchmark]
public int BenchCompIndexDirect() => _compIndexFetcherDirect.Get<TestType50>();
[Benchmark]
public int BenchDictDirect() => _dictFetcherDirect.Get<TestType50>();
private static CompIdx ArrayIndexFor<T>() => CompArrayIndex<T>.Idx;
private static int _compIndexMaster = -1;
private static class CompArrayIndex<T>
{
// ReSharper disable once StaticMemberInGenericType
public static readonly CompIdx Idx = new(Interlocked.Increment(ref _compIndexMaster));
}
private static CompIdx GetCompIdIndex(Type type)
{
return (CompIdx)typeof(CompArrayIndex<>)
.MakeGenericType(type)
.GetField(nameof(CompArrayIndex<int>.Idx), BindingFlags.Static | BindingFlags.Public)!
.GetValue(null)!;
}
private interface IFetcher
{
void Init(Type[] types);
int Get<T>();
}
private sealed class CompIndexFetcher : IFetcher
{
private int[] _values = Array.Empty<int>();
public void Init(Type[] types)
{
var max = types.Max(t => GetCompIdIndex(t).Value);
_values = new int[max + 1];
var i = 0;
foreach (var type in types)
{
_values[GetCompIdIndex(type).Value] = i++;
}
}
public int Get<T>()
{
return _values[CompArrayIndex<T>.Idx.Value];
}
}
private sealed class DictFetcher : IFetcher
{
private readonly Dictionary<Type, int> _values = new();
public void Init(Type[] types)
{
var i = 0;
foreach (var type in types)
{
_values[type] = i++;
}
}
public int Get<T>()
{
return _values[typeof(T)];
}
}
// Just a bunch of types to pad the size of the arrays and such.
// @formatter:off
// ReSharper disable UnusedType.Local
private sealed class TestType1{}
private sealed class TestType2{}
private sealed class TestType3{}
private sealed class TestType4{}
private sealed class TestType5{}
private sealed class TestType6{}
private sealed class TestType7{}
private sealed class TestType8{}
private sealed class TestType9{}
private sealed class TestType10{}
private sealed class TestType11{}
private sealed class TestType12{}
private sealed class TestType13{}
private sealed class TestType14{}
private sealed class TestType15{}
private sealed class TestType16{}
private sealed class TestType17{}
private sealed class TestType18{}
private sealed class TestType19{}
private sealed class TestType20{}
private sealed class TestType21{}
private sealed class TestType22{}
private sealed class TestType23{}
private sealed class TestType24{}
private sealed class TestType25{}
private sealed class TestType26{}
private sealed class TestType27{}
private sealed class TestType28{}
private sealed class TestType29{}
private sealed class TestType30{}
private sealed class TestType31{}
private sealed class TestType32{}
private sealed class TestType33{}
private sealed class TestType34{}
private sealed class TestType35{}
private sealed class TestType36{}
private sealed class TestType37{}
private sealed class TestType38{}
private sealed class TestType39{}
private sealed class TestType40{}
private sealed class TestType41{}
private sealed class TestType42{}
private sealed class TestType43{}
private sealed class TestType44{}
private sealed class TestType45{}
private sealed class TestType46{}
private sealed class TestType47{}
private sealed class TestType48{}
private sealed class TestType49{}
private sealed class TestType50{}
private sealed class TestType51{}
private sealed class TestType52{}
private sealed class TestType53{}
private sealed class TestType54{}
private sealed class TestType55{}
private sealed class TestType56{}
private sealed class TestType57{}
private sealed class TestType58{}
private sealed class TestType59{}
private sealed class TestType60{}
private sealed class TestType61{}
private sealed class TestType62{}
private sealed class TestType63{}
private sealed class TestType64{}
private sealed class TestType65{}
private sealed class TestType66{}
private sealed class TestType67{}
private sealed class TestType68{}
private sealed class TestType69{}
private sealed class TestType70{}
private sealed class TestType71{}
private sealed class TestType72{}
private sealed class TestType73{}
private sealed class TestType74{}
private sealed class TestType75{}
private sealed class TestType76{}
private sealed class TestType77{}
private sealed class TestType78{}
private sealed class TestType79{}
private sealed class TestType80{}
private sealed class TestType81{}
private sealed class TestType82{}
private sealed class TestType83{}
private sealed class TestType84{}
private sealed class TestType85{}
private sealed class TestType86{}
private sealed class TestType87{}
private sealed class TestType88{}
private sealed class TestType89{}
private sealed class TestType90{}
private sealed class TestType91{}
private sealed class TestType92{}
private sealed class TestType93{}
private sealed class TestType94{}
private sealed class TestType95{}
private sealed class TestType96{}
private sealed class TestType97{}
private sealed class TestType98{}
private sealed class TestType99{}
// ReSharper restore UnusedType.Local
// @formatter:on
}

View File

@@ -1,75 +0,0 @@
using BenchmarkDotNet.Attributes;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
public partial class ComponentIteratorBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
[UsedImplicitly]
[Params(1, 10, 100, 1000)]
public int N;
public A[] Comps = default!;
[GlobalSetup]
public void GlobalSetup()
{
_simulation = RobustServerSimulation
.NewSimulation()
.RegisterComponents(f => f.RegisterClass<A>())
.InitializeInstance();
_entityManager = _simulation.Resolve<IEntityManager>();
Comps = new A[N+2];
var coords = new MapCoordinates(0, 0, new MapId(1));
_simulation.AddMap(coords.MapId);
for (var i = 0; i < N; i++)
{
var uid = _entityManager.SpawnEntity(null, coords);
_entityManager.AddComponent<A>(uid);
}
}
[Benchmark]
public A[] ComponentStructEnumerator()
{
var query = _entityManager.EntityQueryEnumerator<A>();
var i = 0;
while (query.MoveNext(out var comp))
{
Comps[i] = comp;
i++;
}
return Comps;
}
[Benchmark]
public A[] ComponentIEnumerable()
{
var i = 0;
foreach (var comp in _entityManager.EntityQuery<A>())
{
Comps[i] = comp;
i++;
}
return Comps;
}
[ComponentProtoName("A")]
public sealed partial class A : Component
{
}
}

View File

@@ -1,53 +0,0 @@
using BenchmarkDotNet.Attributes;
using Robust.Shared.Analyzers;
using static Robust.Benchmarks.EntityManager.ArchetypeComponentAccessBenchmark;
namespace Robust.Benchmarks.EntityManager;
[MemoryDiagnoser]
[Virtual]
public class ArrayAccessBenchmark
{
[Params(new[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9})]
public int[] Array = default!;
[Params(5)]
public int Element;
[Params(500)]
public int Handle;
public Archetype<int, int, int, int, int, int, int, int, int, int> Archetype = default!;
[GlobalSetup]
public void GlobalSetup()
{
Archetype = new Archetype<int, int, int, int, int, int, int, int, int, int>(1000);
}
[Benchmark]
public int? GetArrayElement()
{
return Consume();
}
[Benchmark]
public int? GetExisting()
{
return Consume(Element);
}
[Benchmark]
public int? GetArchetype()
{
return Consume(Archetype.GetComponentUnsafeHandle<int>(Handle));
}
private int? Consume(int? value = null)
{
if (value == null)
value = Array[5];
return value;
}
}

View File

@@ -1,60 +0,0 @@
using BenchmarkDotNet.Attributes;
using JetBrains.Annotations;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
[Virtual]
public partial class GetComponentBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
[UsedImplicitly]
[Params(1, 10, 100, 1000)]
public int N;
public A[] Comps = default!;
[GlobalSetup]
public void GlobalSetup()
{
_simulation = RobustServerSimulation
.NewSimulation()
.RegisterComponents(f => f.RegisterClass<A>())
.InitializeInstance();
_entityManager = _simulation.Resolve<IEntityManager>();
Comps = new A[N+2];
var coords = new MapCoordinates(0, 0, new MapId(1));
_simulation.AddMap(coords.MapId);
for (var i = 0; i < N; i++)
{
var uid = _entityManager.SpawnEntity(null, coords);
_entityManager.AddComponent<A>(uid);
}
}
[Benchmark]
public A[] GetComponent()
{
for (var i = 2; i <= N+1; i++)
{
Comps[i] = _entityManager.GetComponent<A>(new EntityUid(i));
}
// Return something so the JIT doesn't optimize out all the GetComponent calls.
return Comps;
}
[ComponentProtoName("A")]
public sealed partial class A : Component
{
}
}

View File

@@ -1,62 +0,0 @@
using BenchmarkDotNet.Attributes;
using JetBrains.Annotations;
using Robust.Shared.Analyzers;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.UnitTesting.Server;
namespace Robust.Benchmarks.EntityManager;
[Virtual]
public partial class SpawnDeleteEntityBenchmark
{
private ISimulation _simulation = default!;
private IEntityManager _entityManager = default!;
private MapCoordinates _mapCoords = MapCoordinates.Nullspace;
private EntityCoordinates _entCoords = EntityCoordinates.Invalid;
[UsedImplicitly]
[Params(1, 10, 100, 1000)]
public int N;
[GlobalSetup]
public void GlobalSetup()
{
_simulation = RobustServerSimulation
.NewSimulation()
.RegisterComponents(f => f.RegisterClass<A>())
.InitializeInstance();
_entityManager = _simulation.Resolve<IEntityManager>();
_mapCoords = new MapCoordinates(0, 0, new MapId(1));
var uid = _simulation.AddMap(_mapCoords.MapId);
_entCoords = new EntityCoordinates(uid, 0, 0);
}
[Benchmark(Baseline = true)]
public void SpawnDeleteEntityMapCoords()
{
for (var i = 0; i < N; i++)
{
var uid = _entityManager.SpawnEntity(null, _mapCoords);
_entityManager.DeleteEntity(uid);
}
}
[Benchmark]
public void SpawnDeleteEntityEntCoords()
{
for (var i = 0; i < N; i++)
{
var uid = _entityManager.SpawnEntity(null, _entCoords);
_entityManager.DeleteEntity(uid);
}
}
[ComponentProtoName("A")]
public sealed partial class A : Component
{
}
}

View File

@@ -1,227 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using BenchmarkDotNet.Exporters;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Mathematics;
using BenchmarkDotNet.Parameters;
using BenchmarkDotNet.Reports;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Npgsql;
using Npgsql.Internal;
using Npgsql.Internal.TypeHandlers;
using Npgsql.Internal.TypeHandling;
namespace Robust.Benchmarks.Exporters;
public sealed class SQLExporter : IExporter
{
private static readonly JsonSerializerOptions JsonSerializerOptions = new JsonSerializerOptions
{
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals
};
public static readonly IExporter Default = new SQLExporter();
private SQLExporter(){}
public void ExportToLog(Summary summary, ILogger logger)
{
Export(summary, logger);
}
public IEnumerable<string> ExportToFiles(Summary summary, ILogger consoleLogger)
{
Export(summary, consoleLogger);
return Array.Empty<string>();
}
private bool TryGetEnvironmentVariable(string name, ILogger logger, [NotNullWhen(true)] out string? value)
{
value = Environment.GetEnvironmentVariable(name);
if (value == null)
logger.WriteError($"ROBUST_BENCHMARKS_ENABLE_SQL is set, but {name} is missing.");
return value != null;
}
private void Export(Summary summary, ILogger logger)
{
if (!TryGetEnvironmentVariable("ROBUST_BENCHMARKS_SQL_ADDRESS", logger, out var address) ||
!TryGetEnvironmentVariable("ROBUST_BENCHMARKS_SQL_PORT", logger, out var rawPort) ||
!TryGetEnvironmentVariable("ROBUST_BENCHMARKS_SQL_USER", logger, out var user) ||
!TryGetEnvironmentVariable("ROBUST_BENCHMARKS_SQL_PASSWORD", logger, out var password) ||
!TryGetEnvironmentVariable("ROBUST_BENCHMARKS_SQL_DATABASE", logger, out var db) ||
!TryGetEnvironmentVariable("GITHUB_SHA", logger, out var gitHash))
return;
if (!int.TryParse(rawPort, out var port))
{
logger.WriteError("Failed parsing ROBUST_BENCHMARKS_SQL_PORT to int.");
return;
}
var builder = new DbContextOptionsBuilder<BenchmarkContext>();
var connectionString = new NpgsqlConnectionStringBuilder
{
Host = address,
Port = port,
Database = db,
Username = user,
Password = password
}.ConnectionString;
builder.UseNpgsql(connectionString);
using var ctx = new BenchmarkContext(builder.Options);
try
{
ctx.Database.OpenConnection();
var con = (NpgsqlConnection) ctx.Database.GetDbConnection();
con.TypeMapper.AddTypeResolverFactory(new JsonOverrideTypeHandlerResolverFactory(JsonSerializerOptions));
ctx.Database.Migrate();
foreach (var run in BenchmarkRun.FromSummary(summary, gitHash))
{
ctx.BenchmarkRuns.Add(run);
}
ctx.SaveChanges();
}
finally
{
ctx.Dispose();
}
}
public string Name => "sql";
}
// https://github.com/npgsql/efcore.pg/issues/1107#issuecomment-945126627
class JsonOverrideTypeHandlerResolverFactory : TypeHandlerResolverFactory
{
private readonly JsonSerializerOptions _options;
public JsonOverrideTypeHandlerResolverFactory(JsonSerializerOptions options)
=> _options = options;
public override TypeHandlerResolver Create(NpgsqlConnector connector)
=> new JsonOverrideTypeHandlerResolver(connector, _options);
public override string? GetDataTypeNameByClrType(Type clrType)
=> null;
public override TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
=> null;
class JsonOverrideTypeHandlerResolver : TypeHandlerResolver
{
readonly JsonHandler _jsonbHandler;
internal JsonOverrideTypeHandlerResolver(NpgsqlConnector connector, JsonSerializerOptions options)
=> _jsonbHandler ??= new JsonHandler(
connector.DatabaseInfo.GetPostgresTypeByName("jsonb"),
connector.TextEncoding,
isJsonb: true,
options);
public override NpgsqlTypeHandler? ResolveByDataTypeName(string typeName)
=> typeName == "jsonb" ? _jsonbHandler : null;
public override NpgsqlTypeHandler? ResolveByClrType(Type type)
// You can add any user-defined CLR types which you want mapped to jsonb
=> type == typeof(JsonDocument) ? _jsonbHandler : null;
public override TypeMappingInfo? GetMappingByDataTypeName(string dataTypeName)
=> null; // Let the built-in resolver do this
}
}
public sealed class DesignTimeContextFactoryPostgres : IDesignTimeDbContextFactory<BenchmarkContext>
{
public BenchmarkContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<BenchmarkContext>();
optionsBuilder.UseNpgsql("Server=localhost");
return new BenchmarkContext(optionsBuilder.Options);
}
}
public class BenchmarkContext : DbContext
{
public DbSet<BenchmarkRun> BenchmarkRuns { get; set; } = default!;
public BenchmarkContext() { }
public BenchmarkContext(DbContextOptions<BenchmarkContext> options) : base(options) { }
}
public class BenchmarkRun
{
public int Id { get; set; }
public string GitHash { get; set; } = string.Empty;
[Column(TypeName = "timestamptz")] public DateTime RunDate { get; set; }
public string Name { get; set; } = string.Empty;
public string? ParameterMapping { get; set; }
[Column(TypeName = "jsonb")]
public BenchmarkRunParameter[]? ParameterMappingJson { get; set; }
[Column(TypeName = "jsonb")]
public Statistics Statistics { get; set; } = default!;
public static IEnumerable<BenchmarkRun> FromSummary(Summary summary, string gitHash)
{
var runDate = DateTime.UtcNow;
foreach (var benchmarkReport in summary.Reports)
{
var paramString = new StringBuilder();
var parametersItems = benchmarkReport.BenchmarkCase.Parameters.Items;
var runParameters = new BenchmarkRunParameter[parametersItems.Count];
for (var i = 0; i < parametersItems.Count; i++)
{
runParameters[i] = new BenchmarkRunParameter(parametersItems[i]);
paramString.Append(runParameters[i].ToString());
if (i < parametersItems.Count - 1) paramString.Append(',');
}
if (benchmarkReport.ResultStatistics == null)
{
Console.WriteLine($"err: No statistics available for {benchmarkReport.BenchmarkCase.Descriptor.DisplayInfo}!");
continue;
}
yield return new BenchmarkRun
{
Name = benchmarkReport.BenchmarkCase.Descriptor.DisplayInfo,
RunDate = runDate,
GitHash = gitHash,
ParameterMapping = runParameters.Length > 0 ? paramString.ToString() : null,
ParameterMappingJson = runParameters.Length > 0 ? runParameters : null,
Statistics = benchmarkReport.ResultStatistics
};
}
}
}
public struct BenchmarkRunParameter
{
public string Name { get; set; } = string.Empty;
public object Value { get; set; } = default!;
public BenchmarkRunParameter(ParameterInstance instance)
{
Name = instance.Name;
Value = instance.Value;
}
public override string ToString()
{
return $"{Name}={Value}";
}
}

View File

@@ -1,55 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Robust.Benchmarks.Exporters;
#nullable disable
namespace Robust.Benchmarks.Migrations
{
[DbContext(typeof(BenchmarkContext))]
[Migration("20220328231938_InitialCreate")]
partial class InitialCreate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Robust.Benchmarks.Exporters.BenchmarkRun", b =>
{
b.Property<decimal>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("numeric(20,0)");
b.Property<string>("GitHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<BenchmarkRunReport[]>("Reports")
.IsRequired()
.HasColumnType("jsonb");
b.Property<DateTime>("RunDate")
.HasColumnType("Date");
b.HasKey("Id");
b.ToTable("BenchmarkRuns");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,35 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Robust.Benchmarks.Exporters;
#nullable disable
namespace Robust.Benchmarks.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "BenchmarkRuns",
columns: table => new
{
Id = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
GitHash = table.Column<string>(type: "text", nullable: false),
RunDate = table.Column<DateTime>(type: "Date", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Reports = table.Column<BenchmarkRunReport[]>(type: "jsonb", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_BenchmarkRuns", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "BenchmarkRuns");
}
}
}

View File

@@ -1,57 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Robust.Benchmarks.Exporters;
#nullable disable
namespace Robust.Benchmarks.Migrations
{
[DbContext(typeof(BenchmarkContext))]
[Migration("20220510131430_fix-pk")]
partial class FixPK
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Robust.Benchmarks.Exporters.BenchmarkRun", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("GitHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<BenchmarkRunReport[]>("Reports")
.IsRequired()
.HasColumnType("jsonb");
b.Property<DateTime>("RunDate")
.HasColumnType("timestamptz");
b.HasKey("Id");
b.ToTable("BenchmarkRuns");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,51 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Robust.Benchmarks.Migrations
{
public partial class FixPK : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "RunDate",
table: "BenchmarkRuns",
type: "timestamptz",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "Date");
migrationBuilder.AlterColumn<int>(
name: "Id",
table: "BenchmarkRuns",
type: "integer",
nullable: false,
oldClrType: typeof(decimal),
oldType: "numeric(20,0)")
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "RunDate",
table: "BenchmarkRuns",
type: "Date",
nullable: false,
oldClrType: typeof(DateTime),
oldType: "timestamptz");
migrationBuilder.AlterColumn<decimal>(
name: "Id",
table: "BenchmarkRuns",
type: "numeric(20,0)",
nullable: false,
oldClrType: typeof(int),
oldType: "integer")
.OldAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
}
}
}

View File

@@ -1,62 +0,0 @@
// <auto-generated />
using System;
using BenchmarkDotNet.Mathematics;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Robust.Benchmarks.Exporters;
#nullable disable
namespace Robust.Benchmarks.Migrations
{
[DbContext(typeof(BenchmarkContext))]
[Migration("20221009235705_db")]
partial class DB
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Robust.Benchmarks.Exporters.BenchmarkRun", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("GitHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ParameterMapping")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("RunDate")
.HasColumnType("timestamptz");
b.Property<Statistics>("Statistics")
.IsRequired()
.HasColumnType("jsonb");
b.HasKey("Id");
b.ToTable("BenchmarkRuns");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,36 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Robust.Benchmarks.Migrations
{
public partial class DB : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "Reports",
table: "BenchmarkRuns",
newName: "Statistics");
migrationBuilder.AddColumn<string>(
name: "ParameterMapping",
table: "BenchmarkRuns",
type: "text",
nullable: false,
defaultValue: "");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ParameterMapping",
table: "BenchmarkRuns");
migrationBuilder.RenameColumn(
name: "Statistics",
table: "BenchmarkRuns",
newName: "Reports");
}
}
}

Some files were not shown because too many files have changed in this diff Show More