エディタ上でだけ編集可能にする
「エディタ上で編集不可能にする」ではなく、その逆です。
↓こういうこと
ReadonlyInScript
属性が付いたフィールドはインスペクタでは普通に編集できますが、スクリプトで代入しようとするとエラーで怒られます。
ネタバラし
RoslynAnalyzerで書き込みを禁止しているだけです。
以下のような感じで、すごく愚直に。
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
var kinds = new SyntaxKind[]
{
SyntaxKind.SimpleAssignmentExpression,
SyntaxKind.AddAssignmentExpression,
SyntaxKind.SubtractAssignmentExpression,
SyntaxKind.MultiplyAssignmentExpression,
SyntaxKind.DivideAssignmentExpression,
SyntaxKind.ModuloAssignmentExpression,
SyntaxKind.AndAssignmentExpression,
SyntaxKind.ExclusiveOrAssignmentExpression,
SyntaxKind.OrAssignmentExpression,
SyntaxKind.LeftShiftAssignmentExpression,
SyntaxKind.RightShiftAssignmentExpression,
SyntaxKind.CoalesceAssignmentExpression,
SyntaxKind.PreIncrementExpression,
SyntaxKind.PreDecrementExpression,
SyntaxKind.PostIncrementExpression,
SyntaxKind.PostDecrementExpression
};
context.RegisterSyntaxNodeAction(AnalyzeSyntax, kinds);
}
private static void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
{
var syntax = context.Node switch
{
AssignmentExpressionSyntax assignExpression => assignExpression.Left,
PostfixUnaryExpressionSyntax postUnary => postUnary.Operand,
PrefixUnaryExpressionSyntax preUnary => preUnary.Operand,
_ => default
};
if (syntax == default) return;
var symbol = context.SemanticModel
.GetSymbolInfo(syntax, context.CancellationToken)
.Symbol;
var result = symbol switch
{
IFieldSymbol fieldSymbol
=> fieldSymbol.GetAttributes()
.Any(x => x.AttributeClass.Name.Contains("ReadonlyInScriptAttribute")),
IPropertySymbol propertySymbol
=> IsAutoProperty(propertySymbol) && HasReadonlyAttribute(propertySymbol),
_ => false,
};
if (result)
{
var diagnostic = Diagnostic.Create(Rule, context.Node.GetLocation());
context.ReportDiagnostic(diagnostic);
}
bool IsAutoProperty(IPropertySymbol propertySymbol)
{
var node = propertySymbol.DeclaringSyntaxReferences.First().GetSyntax();
if (node is not PropertyDeclarationSyntax propertyDeclarationSyntax) return false;
return propertyDeclarationSyntax.AccessorList.Accessors.All(a => a.Body == null);
}
bool HasReadonlyAttribute(IPropertySymbol propertySymbol)
{
var node = propertySymbol.DeclaringSyntaxReferences.First().GetSyntax();
if (node is not PropertyDeclarationSyntax propertyDeclarationSyntax) return false;
return propertyDeclarationSyntax.DescendantNodes()
.OfType<AttributeSyntax>()
.Any(a => a.Name.ToString().Contains("ReadonlyInScript"));
}
}
飽くまでもコードを分析しているだけなので、エディタからの編集は何も問題無いというわけです。
これの何が嬉しいの?って言われたらわからないですが、
アナライザのコードとdllは以下のリポジトリに公開しています。
github.com
以下のページなどを参考に、dllをポイっとUnityにインポートして、ReadonlyInScriptAtribute
って名前の属性を作ればOKです。
docs.unity3d.com