From 6ccbe52e06512d2753c36bdb2de9c0643c5ed984 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Sun, 11 Feb 2018 11:17:06 +0000 Subject: [PATCH 01/13] Introduce ReferenceName for variable refrences --- ...idParametersOnVariableReferenceQuickFix.cs | 2 +- .../ShaderLab/Psi/Parsing/ShaderLab.psi | 8 ++- .../ShaderLab/Psi/Parsing/BlendOp.shader.gold | 50 +++++++++++-------- .../Psi/Parsing/CullDepth01.shader.gold | 5 +- .../Parsing/LegacyAlphaTesting01.shader.gold | 15 +++--- .../Parsing/LegacyAlphaTesting02.shader.gold | 10 ++-- .../Parsing/LegacyAlphaTesting03.shader.gold | 30 ++++++----- .../Parsing/LegacyAlphaTesting04.shader.gold | 5 +- .../Psi/Parsing/LegacyFog.shader.gold | 20 +++++--- .../Psi/Parsing/LegacyLighting03.shader.gold | 10 ++-- .../Psi/Parsing/LegacyLighting04.shader.gold | 30 ++++++----- .../LegacyTextureCombiner01.shader.gold | 15 +++--- .../LegacyTextureCombiner02.shader.gold | 10 ++-- .../LegacyTextureCombiner03.shader.gold | 15 +++--- .../LegacyTextureCombiner04.shader.gold | 50 +++++++++++-------- .../PropertiesTextureValue.shader.gold | 5 +- .../Parsing/VariableReferences.shader.gold | 25 ++++++---- 17 files changed, 184 insertions(+), 121 deletions(-) diff --git a/resharper/src/resharper-unity/ShaderLab/Feature/Services/QuickFixes/InvalidParametersOnVariableReferenceQuickFix.cs b/resharper/src/resharper-unity/ShaderLab/Feature/Services/QuickFixes/InvalidParametersOnVariableReferenceQuickFix.cs index 26d4838834..6b3b05d83b 100644 --- a/resharper/src/resharper-unity/ShaderLab/Feature/Services/QuickFixes/InvalidParametersOnVariableReferenceQuickFix.cs +++ b/resharper/src/resharper-unity/ShaderLab/Feature/Services/QuickFixes/InvalidParametersOnVariableReferenceQuickFix.cs @@ -51,7 +51,7 @@ protected override Action ExecutePsiTransaction(ISolution solution var reference = VariableReferenceNavigator.GetByInvalidParameters(myToken); ModificationUtil.DeleteChild(myToken); // TODO: Remove this when we finally get a formatter - var firstWhitespace = reference?.Identifier?.NextSibling; + var firstWhitespace = reference?.Name?.NextSibling; var lastWhitespace = reference?.RBrack?.PrevSibling; if (firstWhitespace.IsWhitespaceToken() && lastWhitespace.IsWhitespaceToken()) ModificationUtil.DeleteChildRange(firstWhitespace, lastWhitespace); diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi b/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi index eceef3ff5c..a7e2021724 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi @@ -704,6 +704,10 @@ options { ; +referenceName +: + shaderLabIdentifier +; // ************************************************************************** // @@ -739,13 +743,13 @@ colorLiteral // Private and error handling to allow resync on colorLiteralValue::RPAREN private errorhandling colorLiteralValues : - LIST numericValue SEP COMMA + LIST numericValue SEP COMMA ; variableReference : LBRACK - shaderLabIdentifier + referenceName // Technically, Unity parses a variable reference exactly as it does an attribute // The parameters aren't an error, but are silently ignored invalidVariableReferenceParameters? diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/BlendOp.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/BlendOp.shader.gold index 3c54730123..8fb608b12f 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/BlendOp.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/BlendOp.shader.gold @@ -87,8 +87,9 @@ IShaderLabFile IBlendOpValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Op) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Op) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -108,15 +109,17 @@ IShaderLabFile IBlendOpValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_ColorOp) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_ColorOp) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) ShaderLabTokenType+FixedTokenElement(type:COMMA, text:,) Whitespace(type:WHITESPACE, text: ) spaces: " " IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_AlphaOp) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_AlphaOp) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -126,8 +129,9 @@ IShaderLabFile IBlendOpValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_ColorOp) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_ColorOp) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) ShaderLabTokenType+FixedTokenElement(type:COMMA, text:,) Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -145,8 +149,9 @@ IShaderLabFile Whitespace(type:WHITESPACE, text: ) spaces: " " IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_AlphaOp) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_AlphaOp) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -171,15 +176,17 @@ IShaderLabFile Whitespace(type:WHITESPACE, text: ) spaces: " " IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_ColorOp) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_ColorOp) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) ShaderLabTokenType+FixedTokenElement(type:COMMA, text:,) Whitespace(type:WHITESPACE, text: ) spaces: " " IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_AlphaOp) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_AlphaOp) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -191,8 +198,9 @@ IShaderLabFile Whitespace(type:WHITESPACE, text: ) spaces: " " IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_ColorOp) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_ColorOp) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) ShaderLabTokenType+FixedTokenElement(type:COMMA, text:,) Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -212,8 +220,9 @@ IShaderLabFile Whitespace(type:WHITESPACE, text: ) spaces: " " IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_AlphaOp) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_AlphaOp) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -239,8 +248,9 @@ IShaderLabFile Whitespace(type:WHITESPACE, text: ) spaces: " " IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Op) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Op) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/CullDepth01.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/CullDepth01.shader.gold index bfe5dc0fe3..7a31735763 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/CullDepth01.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/CullDepth01.shader.gold @@ -221,8 +221,9 @@ IShaderLabFile ICullOrientation IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_CullValue) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_CullValue) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting01.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting01.shader.gold index e07359c475..1891bd8e33 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting01.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting01.shader.gold @@ -76,8 +76,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) @@ -118,8 +119,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) @@ -166,8 +168,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting02.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting02.shader.gold index a562ab34e3..f64671d4f5 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting02.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting02.shader.gold @@ -96,8 +96,9 @@ IShaderLabFile INumericValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Cutoff) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Cutoff) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -164,8 +165,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting03.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting03.shader.gold index c6a64ff6f7..984ca9dc38 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting03.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting03.shader.gold @@ -123,8 +123,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Color) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Color) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -134,8 +135,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Color) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Color) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -184,8 +186,9 @@ IShaderLabFile INumericValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Cutoff) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Cutoff) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -195,8 +198,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) @@ -278,8 +282,9 @@ IShaderLabFile INumericValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Cutoff) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Cutoff) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" NewLine(type:NEW_LINE, text:\n) spaces: "\n" @@ -307,8 +312,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting04.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting04.shader.gold index 7686dc0dc9..232a98fd09 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting04.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyAlphaTesting04.shader.gold @@ -69,8 +69,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyFog.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyFog.shader.gold index 2beed98c1a..6f146e5781 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyFog.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyFog.shader.gold @@ -263,8 +263,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Color) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Color) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -274,8 +275,9 @@ IShaderLabFile INumericValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Density) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Density) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -286,16 +288,18 @@ IShaderLabFile INumericValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Min) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Min) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) ShaderLabTokenType+FixedTokenElement(type:COMMA, text:,) Whitespace(type:WHITESPACE, text: ) spaces: " " INumericValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Max) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Max) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyLighting03.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyLighting03.shader.gold index d47b89a74e..acb28c97c4 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyLighting03.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyLighting03.shader.gold @@ -96,8 +96,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Color) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Color) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -122,8 +123,9 @@ IShaderLabFile INumericValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_ColorComponent) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_ColorComponent) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) ShaderLabTokenType+FixedTokenElement(type:RPAREN, text:)) NewLine(type:NEW_LINE, text:\n) spaces: "\n" diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyLighting04.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyLighting04.shader.gold index 35b3678584..bddfced624 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyLighting04.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyLighting04.shader.gold @@ -187,8 +187,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Color) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Color) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -198,8 +199,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Color) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Color) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -209,8 +211,9 @@ IShaderLabFile INumericValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Shininess) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Shininess) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -220,8 +223,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_SpecColor) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_SpecColor) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -231,8 +235,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Emission) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Emission) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -259,8 +264,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner01.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner01.shader.gold index 77dfff5f08..a9f6042b02 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner01.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner01.shader.gold @@ -86,8 +86,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) @@ -115,8 +116,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_BlendTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_BlendTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) @@ -151,8 +153,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_BlendTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_BlendTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner02.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner02.shader.gold index 42252290c1..675cee56df 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner02.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner02.shader.gold @@ -126,8 +126,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) @@ -184,8 +185,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner03.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner03.shader.gold index 2f87d56127..3ce93a7cf2 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner03.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner03.shader.gold @@ -157,8 +157,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) @@ -173,8 +174,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_IlluminCol) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_IlluminCol) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -215,8 +217,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner04.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner04.shader.gold index 9561ded81c..15c674b9cb 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner04.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/LegacyTextureCombiner04.shader.gold @@ -222,8 +222,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Color) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Color) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -233,8 +234,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Color) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Color) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -244,8 +246,9 @@ IShaderLabFile INumericValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Shininess) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Shininess) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -255,8 +258,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_SpecColor) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_SpecColor) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -266,8 +270,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Emission) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Emission) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -291,8 +296,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) @@ -304,8 +310,9 @@ IShaderLabFile IColorValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_IlluminCol) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_IlluminCol) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" Whitespace(type:WHITESPACE, text: ) spaces: " " @@ -341,8 +348,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) @@ -421,8 +429,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) @@ -504,8 +513,9 @@ IShaderLabFile ISetTextureValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_MainTex) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_MainTex) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:LBRACE, text:{) diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/PropertiesTextureValue.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/PropertiesTextureValue.shader.gold index 4165256cba..519e4c0bc9 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/PropertiesTextureValue.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/PropertiesTextureValue.shader.gold @@ -255,8 +255,9 @@ IShaderLabFile Whitespace(type:WHITESPACE, text: ) spaces: " " IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Color) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Color) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:RBRACE, text:}) diff --git a/resharper/test/data/ShaderLab/Psi/Parsing/VariableReferences.shader.gold b/resharper/test/data/ShaderLab/Psi/Parsing/VariableReferences.shader.gold index 51a267aa98..43f306290a 100644 --- a/resharper/test/data/ShaderLab/Psi/Parsing/VariableReferences.shader.gold +++ b/resharper/test/data/ShaderLab/Psi/Parsing/VariableReferences.shader.gold @@ -56,8 +56,9 @@ IShaderLabFile IBlendOpValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Op) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Op) ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" NewLine(type:NEW_LINE, text:\n) spaces: "\n" @@ -71,8 +72,9 @@ IShaderLabFile IBlendOpValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Op) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Op) Whitespace(type:WHITESPACE, text: ) spaces: " " ShaderLabTokenType+FixedTokenElement(type:RBRACK, text:]) NewLine(type:NEW_LINE, text:\n) spaces: "\n" @@ -83,8 +85,9 @@ IShaderLabFile IBlendOpValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Op) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Op) IInvalidVariableReferenceParameters ShaderLabTokenType+FixedTokenElement(type:LPAREN, text:() IShaderLabIdentifier @@ -99,8 +102,9 @@ IShaderLabFile IBlendOpValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Op) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Op) IInvalidVariableReferenceParameters ShaderLabTokenType+FixedTokenElement(type:LPAREN, text:() IShaderLabIdentifier @@ -116,8 +120,9 @@ IShaderLabFile IBlendOpValue IVariableReference ShaderLabTokenType+FixedTokenElement(type:LBRACK, text:[) - IShaderLabIdentifier - Identifier(type:IDENTIFIER, text:_Op) + IReferenceName + IShaderLabIdentifier + Identifier(type:IDENTIFIER, text:_Op) IInvalidVariableReferenceParameters ShaderLabTokenType+FixedTokenElement(type:LPAREN, text:() IShaderLabIdentifier From 000a94e78918fbf811471004d17e58c9031ad21b Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Sun, 11 Feb 2018 14:11:22 +0000 Subject: [PATCH 02/13] Add first class references for variables Everything's unresolved for now --- .../Daemon/Errors/ShaderLabErrors.xml | 11 +- .../Stages/IdentifierHighlighterProcess.cs | 19 +- .../Resolve/ResolveProblemHighlighter.cs | 44 +++ .../ShaderLab/Psi/Parsing/ShaderLab.psi | 269 +++++++++--------- .../ShaderLab/Psi/Tree/Impl/Identifier.cs | 7 +- .../ShaderLab/Psi/Tree/Impl/ReferenceName.cs | 92 ++++++ 6 files changed, 299 insertions(+), 143 deletions(-) create mode 100644 resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/ResolveProblemHighlighter.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml b/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml index fe81497b8e..e9c6d5c0eb 100644 --- a/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml @@ -19,7 +19,16 @@ DocumentRange - + + + + + Reference.GetName() + + Reference.GetDocumentRange() + + + diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/IdentifierHighlighterProcess.cs b/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/IdentifierHighlighterProcess.cs index a96ddcbae4..261db5b440 100644 --- a/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/IdentifierHighlighterProcess.cs +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/IdentifierHighlighterProcess.cs @@ -2,8 +2,11 @@ using JetBrains.ReSharper.Daemon.VisualElements; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Errors; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Stages.Resolve; using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi; using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree; +using JetBrains.ReSharper.Psi.ExtensionsAPI.Tree; +using JetBrains.ReSharper.Psi.Resolve; using JetBrains.ReSharper.Psi.Tree; namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Stages @@ -13,6 +16,8 @@ internal class IdentifierHighlighterProcess : ShaderLabDaemonStageProcessBase private readonly DaemonProcessKind myProcessKind; private readonly bool myIdentifierHighlightingEnabled; private readonly VisualElementHighlighter myVisualElementHighlighter; + private readonly ResolveProblemHighlighter myResolveProblemHighlighter; + private readonly IReferenceProvider myReferenceProvider; public IdentifierHighlighterProcess(IDaemonProcess process, ResolveHighlighterRegistrar registrar, IContextBoundSettingsStore settingsStore, DaemonProcessKind processKind, IShaderLabFile file, @@ -22,9 +27,11 @@ public IdentifierHighlighterProcess(IDaemonProcess process, ResolveHighlighterRe myProcessKind = processKind; myIdentifierHighlightingEnabled = identifierHighlightingStageService.ShouldHighlightIdentifiers(settingsStore); myVisualElementHighlighter = new VisualElementHighlighter(ShaderLabLanguage.Instance, settingsStore); + myResolveProblemHighlighter = new ResolveProblemHighlighter(registrar); + myReferenceProvider = ((IFileImpl)file).ReferenceProvider; } - public override void VisitNode(ITreeNode node, IHighlightingConsumer context) + public override void VisitNode(ITreeNode node, IHighlightingConsumer consumer) { if (myProcessKind == DaemonProcessKind.VISIBLE_DOCUMENT) { @@ -33,11 +40,11 @@ public override void VisitNode(ITreeNode node, IHighlightingConsumer context) var info = myVisualElementHighlighter.CreateColorHighlightingInfo(node); if (info != null) - context.AddHighlighting(info.Highlighting, info.Range); + consumer.AddHighlighting(info.Highlighting, info.Range); } - // TODO: Resolve problem highlighter - // That is, highlight problems with resolve + var references = node.GetReferences(myReferenceProvider); + myResolveProblemHighlighter.CheckForResolveProblems(node, consumer, references); // TODO: Move to ShaderLabSyntaxHighlightingStage // (Not Rider's syntax highlighting though!) @@ -57,10 +64,10 @@ public override void VisitNode(ITreeNode node, IHighlightingConsumer context) else if (range.TextRange.StartOffset > 0) range = range.ExtendLeft(1); } - context.AddHighlighting(new ShaderLabSyntaxError(errorElement.ErrorDescription, range)); + consumer.AddHighlighting(new ShaderLabSyntaxError(errorElement.ErrorDescription, range)); } - base.VisitNode(node, context); + base.VisitNode(node, consumer); } } } \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/ResolveProblemHighlighter.cs b/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/ResolveProblemHighlighter.cs new file mode 100644 index 0000000000..5a41aef603 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/ResolveProblemHighlighter.cs @@ -0,0 +1,44 @@ +using System; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Errors; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi; +using JetBrains.ReSharper.Psi.Resolve; +using JetBrains.ReSharper.Psi.Tree; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Stages.Resolve +{ + internal class ResolveProblemHighlighter + { + private readonly ResolveHighlighterRegistrar myResolveHighlighterRegistrar; + + public ResolveProblemHighlighter(ResolveHighlighterRegistrar resolveHighlighterRegistrar) + { + myResolveHighlighterRegistrar = resolveHighlighterRegistrar; + } + + public void CheckForResolveProblems(ITreeNode node, IHighlightingConsumer consumer, ReferenceCollection references) + { + foreach (var reference in references) + CheckForResolveProblems(consumer, reference); + } + + private void CheckForResolveProblems(IHighlightingConsumer consumer, IReference reference) + { + var error = reference.CheckResolveResult(); + if (error == null) + throw new InvalidOperationException("ResolveErrorType is null for reference " + reference.GetType().FullName); + + if (error == ResolveErrorType.OK) + return; + + if (myResolveHighlighterRegistrar.ContainsHandler(ShaderLabLanguage.Instance, error)) + { + var highlighting = myResolveHighlighterRegistrar.GetResolveHighlighting(reference, error); + if (highlighting != null) + consumer.AddHighlighting(highlighting); + } + else + consumer.AddHighlighting(new NotResolvedError(reference)); + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi b/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi index a7e2021724..96942ab58c 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi @@ -563,144 +563,147 @@ options { // Note that C# does context sensitive keywords the other way - all context sensitive keywords are identifiers // and parsed via custom match/expect methods. This has implications on follow tokens (on error, can skip to // any following identifier, rather than expected keyword) +// +// TODO: I can't remember why this is customImpl!? shaderLabIdentifier options { customImpl; } : - IDENTIFIER | UNQUOTED_STRING_LITERAL - - | SHADER_KEYWORD - | PROPERTIES_KEYWORD - | CATEGORY_KEYWORD - | SUB_SHADER_KEYWORD - | FALLBACK_KEYWORD - | CUSTOM_EDITOR_KEYWORD - | DEPENDENCY_KEYWORD - - | COLOR_KEYWORD - | FLOAT_KEYWORD - | INT_KEYWORD - | RANGE_KEYWORD - | VECTOR_KEYWORD - - | ANY_KEYWORD - | CUBE_KEYWORD - | CUBE_ARRAY_KEYWORD - | RECT_KEYWORD - | TEXTURE_2D_KEYWORD - | TEXTURE_2D_ARRAY_KEYWORD - | TEXTURE_3D_KEYWORD - - | TAGS_KEYWORD - | PASS_KEYWORD - | USEPASS_KEYWORD - | GRABPASS_KEYWORD - - | CULL_KEYWORD - | ZCLIP_KEYWORD - | ZTEST_KEYWORD - | ZWRITE_KEYWORD - | OFFSET_KEYWORD - | BLEND_KEYWORD - | BLEND_OP_KEYWORD - | ALPHA_TO_MASK_KEYWORD - | COLOR_MASK_KEYWORD - | STENCIL_KEYWORD - | NAME_KEYWORD - | LOD_KEYWORD - | BIND_CHANNELS_KEYWORD - - | BACK_KEYWORD - | FRONT_KEYWORD - - | LIGHTING_KEYWORD - | MATERIAL_KEYWORD - | SEPARATE_SPECULAR_KEYWORD - | COLOR_MATERIAL_KEYWORD - | FOG_KEYWORD - | ALPHA_TEST_KEYWORD - | SET_TEXTURE_KEYWORD - - | DIFFUSE_KEYWORD - | AMBIENT_KEYWORD - | SPECULAR_KEYWORD - | SHININESS_KEYWORD - - | COMBINE_KEYWORD - | CONSTANT_COLOR_KEYWORD - | MATRIX_KEYWORD - | LIGHTMAP_MODE_KEYWORD - | TEX_GEN_KEYWORD - - | PREVIOUS_KEYWORD - | PRIMARY_KEYWORD - | TEXTURE_KEYWORD - | CONSTANT_KEYWORD - | DOUBLE_KEYWORD - | QUAD_KEYWORD - | LERP_KEYWORD - | ONE_KEYWORD - | ALPHA_KEYWORD - | DOT3_KEYWORD - | DOT3RGBA_KEYWORD - - | SPHERE_MAP_KEYWORD - | EYE_LINEAR_KEYWORD - | CUBE_REFLECT_KEYWORD - | CUBE_NORMAL_KEYWORD - | OBJECT_LINEAR_KEYWORD - - | BIND_KEYWORD - - | AMBIENT_AND_DIFFUSE_KEYWORD - | EMISSION_KEYWORD - - | MODE_KEYWORD - | DENSITY_KEYWORD - - | GLOBAL_KEYWORD - | LINEAR_KEYWORD - | EXP_KEYWORD - | EXP2_KEYWORD - - | REF_KEYWORD - | READ_MASK_KEYWORD - | WRITE_MASK_KEYWORD - | PASS_FRONT_KEYWORD - | PASS_BACK_KEYWORD - | COMP_KEYWORD - | COMP_FRONT_KEYWORD - | COMP_BACK_KEYWORD - | FAIL_KEYWORD - | FAIL_FRONT_KEYWORD - | FAIL_BACK_KEYWORD - | ZFAIL_KEYWORD - | ZFAIL_FRONT_KEYWORD - | ZFAIL_BACK_KEYWORD - - | GREATER_KEYWORD - | GEQUAL_KEYWORD - | LESS_KEYWORD - | LEQUAL_KEYWORD - | EQUAL_KEYWORD - | NOT_EQUAL_KEYWORD - | ALWAYS_KEYWORD - | NEVER_KEYWORD - - | KEEP_KEYWORD - | ZERO_KEYWORD - | REPLACE_KEYWORD - | INCR_SAT_KEYWORD - | DECR_SAT_KEYWORD - | INVERT_KEYWORD - | INCR_WRAP_KEYWORD - | DECR_WRAP_KEYWORD - - | TRUE_KEYWORD - | FALSE_KEYWORD - | ON_KEYWORD - | OFF_KEYWORD + IDENTIFIER + | UNQUOTED_STRING_LITERAL + + | SHADER_KEYWORD + | PROPERTIES_KEYWORD + | CATEGORY_KEYWORD + | SUB_SHADER_KEYWORD + | FALLBACK_KEYWORD + | CUSTOM_EDITOR_KEYWORD + | DEPENDENCY_KEYWORD + + | COLOR_KEYWORD + | FLOAT_KEYWORD + | INT_KEYWORD + | RANGE_KEYWORD + | VECTOR_KEYWORD + + | ANY_KEYWORD + | CUBE_KEYWORD + | CUBE_ARRAY_KEYWORD + | RECT_KEYWORD + | TEXTURE_2D_KEYWORD + | TEXTURE_2D_ARRAY_KEYWORD + | TEXTURE_3D_KEYWORD + + | TAGS_KEYWORD + | PASS_KEYWORD + | USEPASS_KEYWORD + | GRABPASS_KEYWORD + + | CULL_KEYWORD + | ZCLIP_KEYWORD + | ZTEST_KEYWORD + | ZWRITE_KEYWORD + | OFFSET_KEYWORD + | BLEND_KEYWORD + | BLEND_OP_KEYWORD + | ALPHA_TO_MASK_KEYWORD + | COLOR_MASK_KEYWORD + | STENCIL_KEYWORD + | NAME_KEYWORD + | LOD_KEYWORD + | BIND_CHANNELS_KEYWORD + + | BACK_KEYWORD + | FRONT_KEYWORD + + | LIGHTING_KEYWORD + | MATERIAL_KEYWORD + | SEPARATE_SPECULAR_KEYWORD + | COLOR_MATERIAL_KEYWORD + | FOG_KEYWORD + | ALPHA_TEST_KEYWORD + | SET_TEXTURE_KEYWORD + + | DIFFUSE_KEYWORD + | AMBIENT_KEYWORD + | SPECULAR_KEYWORD + | SHININESS_KEYWORD + + | COMBINE_KEYWORD + | CONSTANT_COLOR_KEYWORD + | MATRIX_KEYWORD + | LIGHTMAP_MODE_KEYWORD + | TEX_GEN_KEYWORD + + | PREVIOUS_KEYWORD + | PRIMARY_KEYWORD + | TEXTURE_KEYWORD + | CONSTANT_KEYWORD + | DOUBLE_KEYWORD + | QUAD_KEYWORD + | LERP_KEYWORD + | ONE_KEYWORD + | ALPHA_KEYWORD + | DOT3_KEYWORD + | DOT3RGBA_KEYWORD + + | SPHERE_MAP_KEYWORD + | EYE_LINEAR_KEYWORD + | CUBE_REFLECT_KEYWORD + | CUBE_NORMAL_KEYWORD + | OBJECT_LINEAR_KEYWORD + + | BIND_KEYWORD + + | AMBIENT_AND_DIFFUSE_KEYWORD + | EMISSION_KEYWORD + + | MODE_KEYWORD + | DENSITY_KEYWORD + + | GLOBAL_KEYWORD + | LINEAR_KEYWORD + | EXP_KEYWORD + | EXP2_KEYWORD + + | REF_KEYWORD + | READ_MASK_KEYWORD + | WRITE_MASK_KEYWORD + | PASS_FRONT_KEYWORD + | PASS_BACK_KEYWORD + | COMP_KEYWORD + | COMP_FRONT_KEYWORD + | COMP_BACK_KEYWORD + | FAIL_KEYWORD + | FAIL_FRONT_KEYWORD + | FAIL_BACK_KEYWORD + | ZFAIL_KEYWORD + | ZFAIL_FRONT_KEYWORD + | ZFAIL_BACK_KEYWORD + + | GREATER_KEYWORD + | GEQUAL_KEYWORD + | LESS_KEYWORD + | LEQUAL_KEYWORD + | EQUAL_KEYWORD + | NOT_EQUAL_KEYWORD + | ALWAYS_KEYWORD + | NEVER_KEYWORD + + | KEEP_KEYWORD + | ZERO_KEYWORD + | REPLACE_KEYWORD + | INCR_SAT_KEYWORD + | DECR_SAT_KEYWORD + | INVERT_KEYWORD + | INCR_WRAP_KEYWORD + | DECR_WRAP_KEYWORD + + | TRUE_KEYWORD + | FALSE_KEYWORD + | ON_KEYWORD + | OFF_KEYWORD ; diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/Identifier.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/Identifier.cs index 3a248fe18e..03348eb5e5 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/Identifier.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/Identifier.cs @@ -4,9 +4,8 @@ namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree.Impl { - // A named identifier, so presumably only used when referring to a thing - // e.g. property definition name, property reference name, shader name, etc. - // Except shader name is a string literal... + // A token to represent an identifier name. Note that an identifier can also be another token + // as the tokens for command names and values are not keywords as such internal class Identifier : ShaderLabTokenBase, IIdentifier { private readonly string myText; @@ -24,6 +23,8 @@ public Identifier(string text) public string Name => GetText(); } + // An element to represent an identifier. We need an element instead of just a tree + // node, because the name of the identifier might clash with one of the "keyword" tokens internal abstract partial class ShaderLabIdentifierStub { public abstract string Name { get; } diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs new file mode 100644 index 0000000000..37197c3602 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs @@ -0,0 +1,92 @@ +using JetBrains.Annotations; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.ExtensionsAPI; +using JetBrains.ReSharper.Psi.ExtensionsAPI.Resolve; +using JetBrains.ReSharper.Psi.Resolve; +using JetBrains.ReSharper.Psi.Tree; +using JetBrains.ReSharper.Resources.Shell; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree.Impl +{ + internal partial class ReferenceName + { + private IReference myReference; + + public override ReferenceCollection GetFirstClassReferences() + { + return new ReferenceCollection(Reference); + } + + public IReference Reference + { + get + { + if (myReference == null) + { + lock (this) + { + if (myReference == null) + myReference = new PropertyReference(this); + } + } + + return myReference; + } + } + + private class PropertyReference : TreeReferenceBase + { + public PropertyReference([NotNull] ReferenceName owner) + : base(owner) + { + } + + public override ResolveResultWithInfo ResolveWithoutCache() + { + // Look for the item in the properties + return ResolveResultWithInfo.Unresolved; + } + + public override string GetName() + { + return myOwner.Identifier?.Name ?? SharedImplUtil.MISSING_DECLARATION_NAME; + } + + public override ISymbolTable GetReferenceSymbolTable(bool useReferenceName) + { + return EmptySymbolTable.INSTANCE; + } + + public override TreeTextRange GetTreeTextRange() + { + return myOwner.Identifier?.GetTreeTextRange() ?? TreeTextRange.InvalidRange; + } + + public override IReference BindTo(IDeclaredElement element) + { + using (WriteLockCookie.Create(myOwner.IsPhysical())) + { + var shaderLabIdentifier = new ShaderLabIdentifier(); + shaderLabIdentifier.AddChild(new Identifier(element.ShortName)); + if (myOwner.Identifier != null) + LowLevelModificationUtil.ReplaceChildRange(myOwner.Identifier, myOwner.Identifier, + shaderLabIdentifier); + else + LowLevelModificationUtil.AddChild(myOwner.Identifier, shaderLabIdentifier); + } + + return myOwner.Reference; + } + + public override IReference BindTo(IDeclaredElement element, ISubstitution substitution) + { + return BindTo(element); + } + + public override IAccessContext GetAccessContext() + { + return new DefaultAccessContext(myOwner); + } + } + } +} \ No newline at end of file From 7067193817e7fa92da425824627ca70d3097f92d Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Mon, 12 Feb 2018 17:46:43 +0000 Subject: [PATCH 03/13] Add declarations and declared elements --- .../IShaderLabDeclaredElement.cs | 8 ++ .../PropertyDeclaredElement.cs | 14 ++++ .../ShaderLabDeclaredElementBase.cs | 73 +++++++++++++++++++ .../ShaderLabDeclaredElementPresenter.cs | 25 +++++++ .../ShaderLabDeclaredElementType.cs | 27 +++++++ .../ShaderLab/Psi/Parsing/ShaderLab.psi | 5 +- .../Psi/Tree/Impl/PropertyDeclaration.cs | 49 +++++++++++++ .../Psi/Tree/Impl/ShaderLabDeclarationBase.cs | 20 +++++ 8 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/IShaderLabDeclaredElement.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenter.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/PropertyDeclaration.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ShaderLabDeclarationBase.cs diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/IShaderLabDeclaredElement.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/IShaderLabDeclaredElement.cs new file mode 100644 index 0000000000..d8fb836276 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/IShaderLabDeclaredElement.cs @@ -0,0 +1,8 @@ +using JetBrains.ReSharper.Psi; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements +{ + public interface IShaderLabDeclaredElement : IDeclaredElement + { + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs new file mode 100644 index 0000000000..794ff75ba6 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs @@ -0,0 +1,14 @@ +using JetBrains.ReSharper.Psi; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements +{ + public class PropertyDeclaredElement : ShaderLabDeclaredElementBase + { + public PropertyDeclaredElement(string shortName, IPsiSourceFile sourceFile, int treeOffset) + : base(shortName, sourceFile, treeOffset) + { + } + + public override DeclaredElementType GetElementType() => ShaderLabDeclaredElementType.Property; + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs new file mode 100644 index 0000000000..1ee53b6128 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Xml; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.Files; +using JetBrains.ReSharper.Psi.Tree; +using JetBrains.Util; +using JetBrains.Util.DataStructures; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements +{ + public abstract class ShaderLabDeclaredElementBase : IShaderLabDeclaredElement + { + private readonly IPsiSourceFile mySourceFile; + private readonly int myTreeOffset; + + protected ShaderLabDeclaredElementBase(string shortName, IPsiSourceFile sourceFile, int treeOffset) + { + mySourceFile = sourceFile; + myTreeOffset = treeOffset; + ShortName = shortName; + } + + public IPsiServices GetPsiServices() + { + return mySourceFile.GetPsiServices(); + } + + public IList GetDeclarations() + { + if (!(mySourceFile.GetPrimaryPsiFile() is IShaderLabFile psi)) + return EmptyList.InstanceList; + + var node = psi.FindNodeAt(TreeTextRange.FromLength(new TreeOffset(myTreeOffset), 1)); + while (node != null && !(node is IDeclaration)) + node = node.Parent; + if (node == null) + return EmptyList.Instance; + + return new[] {(IDeclaration) node}; + } + + public IList GetDeclarationsIn(IPsiSourceFile sourceFile) + { + if (mySourceFile == sourceFile) + return GetDeclarations(); + return EmptyList.Instance; + } + + public abstract DeclaredElementType GetElementType(); + + public XmlNode GetXMLDoc(bool inherit) => null; + public XmlNode GetXMLDescriptionSummary(bool inherit) => null; + public bool IsValid() => true; + public bool IsSynthetic() => false; + + public HybridCollection GetSourceFiles() + { + return new HybridCollection(mySourceFile); + } + + public bool HasDeclarationsIn(IPsiSourceFile sourceFile) + { + return mySourceFile == sourceFile; + } + + public string ShortName { get; } + public bool CaseSensitiveName => true; // TODO: Check! + + // ReSharper disable once AssignNullToNotNullAttribute + public PsiLanguageType PresentationLanguage => ShaderLabLanguage.Instance; + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenter.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenter.cs new file mode 100644 index 0000000000..c3573acf75 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenter.cs @@ -0,0 +1,25 @@ +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.Resolve; +using JetBrains.Util; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements +{ + [PsiSharedComponent] + public class ShaderLabDeclaredElementPresenter : IDeclaredElementPresenter + { + public string Format(DeclaredElementPresenterStyle style, IDeclaredElement element, ISubstitution substitution, + out DeclaredElementPresenterMarking marking) + { + marking = new DeclaredElementPresenterMarking(); + if (!(element is IShaderLabDeclaredElement)) + return null; + + // TODO: Type (Float, Color, etc.), display name, etc. + marking.NameRange = new TextRange(0, element.ShortName.Length); + return element.ShortName; + } + + public string Format(ParameterKind parameterKind) => string.Empty; + public string Format(AccessRights accessRights) => string.Empty; + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs new file mode 100644 index 0000000000..63a0fa6c5a --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs @@ -0,0 +1,27 @@ +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.Resources; +using JetBrains.UI.Icons; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements +{ + public class ShaderLabDeclaredElementType : DeclaredElementType + { + // TODO: Proper icon + public static readonly ShaderLabDeclaredElementType Property = new ShaderLabDeclaredElementType("Property", PsiSymbolsThemedIcons.Property.Id); + + private readonly IconId myIconId; + + private ShaderLabDeclaredElementType(string name, IconId iconId) + : base(name) + { + PresentableName = name; + myIconId = iconId; + } + + public override string PresentableName { get; } + protected override IconId GetImage() => myIconId; + public override bool IsPresentable(PsiLanguageType language) => language.Is(); + protected override IDeclaredElementPresenter DefaultPresenter => + ShaderLabLanguage.Instance.DeclaredElementPresenter(); + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi b/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi index 96942ab58c..dab239dda0 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Parsing/ShaderLab.psi @@ -107,7 +107,6 @@ // `interfaceName` // `elementType` // `elementTypeSet` -// `stubBase` // `fakeStub` // `result` // `multilevel` @@ -966,6 +965,10 @@ propertiesValue ; propertyDeclaration +options { + customInterface; + stubBase="ShaderLabDeclarationBase"; +} : propertyHeader EQUALS diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/PropertyDeclaration.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/PropertyDeclaration.cs new file mode 100644 index 0000000000..0574a214f7 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/PropertyDeclaration.cs @@ -0,0 +1,49 @@ +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.ExtensionsAPI; +using JetBrains.ReSharper.Psi.ExtensionsAPI.Tree; +using JetBrains.ReSharper.Psi.Tree; +using JetBrains.ReSharper.Resources.Shell; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree.Impl +{ + internal partial class PropertyDeclaration + { + private readonly CachedPsiValueWithOffsets myCachedDeclaredElement = + new CachedPsiValueWithOffsets(); + + public override IDeclaredElement DeclaredElement + { + get + { + if (Name == null) + return null; + return myCachedDeclaredElement.GetValue(this, + () => CreateDeclaration(DeclaredName)); + } + } + + public override string DeclaredName => Name?.GetText() ?? SharedImplUtil.MISSING_DECLARATION_NAME; + + public override void SetName(string name) + { + using (WriteLockCookie.Create()) + { + // TODO: Perhaps add SetName to ShaderLabIdentifier? + var identifier = new ShaderLabIdentifier(); + identifier.AddChild(new Identifier(name)); + ModificationUtil.ReplaceChild(Name, identifier); + } + } + + public override TreeTextRange GetNameRange() + { + return Name?.GetTreeTextRange() ?? TreeTextRange.InvalidRange; + } + + private IDeclaredElement CreateDeclaration(string declaredName) + { + return new PropertyDeclaredElement(declaredName, GetSourceFile(), GetTreeStartOffset().Offset); + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ShaderLabDeclarationBase.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ShaderLabDeclarationBase.cs new file mode 100644 index 0000000000..a36a4f8669 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ShaderLabDeclarationBase.cs @@ -0,0 +1,20 @@ +using System.Xml; +using JetBrains.Annotations; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.Tree; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree.Impl +{ + public abstract class ShaderLabDeclarationBase : ShaderLabCompositeElement, IDeclaration + { + public abstract IDeclaredElement DeclaredElement { get; } + + public abstract string DeclaredName { get; } + public abstract void SetName([NotNull] string name); + public abstract TreeTextRange GetNameRange(); + + public bool IsSynthetic() => false; + // Can we abuse this to return e.g. tooltips? + public virtual XmlNode GetXMLDoc(bool inherit) => null; + } +} \ No newline at end of file From 894a8bb7bb423107971a754050894c564b08dac5 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Mon, 12 Feb 2018 23:04:42 +0000 Subject: [PATCH 04/13] Resolve references to property declarations --- .../Psi/Tree/IPropertyDeclaration.cs | 8 +++++ .../ShaderLab/Psi/Tree/IShaderLabTreeNode.cs | 2 -- .../ShaderLab/Psi/Tree/Impl/ReferenceName.cs | 33 +++++++++++++++++-- 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/Tree/IPropertyDeclaration.cs diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/IPropertyDeclaration.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/IPropertyDeclaration.cs new file mode 100644 index 0000000000..19c991bafc --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/IPropertyDeclaration.cs @@ -0,0 +1,8 @@ +using JetBrains.ReSharper.Psi.Tree; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree +{ + public partial interface IPropertyDeclaration : IDeclaration + { + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/IShaderLabTreeNode.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/IShaderLabTreeNode.cs index 9e78b117c0..a2ae4f3d2f 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/IShaderLabTreeNode.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/IShaderLabTreeNode.cs @@ -6,9 +6,7 @@ namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree public interface IShaderLabTreeNode : ITreeNode { void Accept([NotNull] TreeNodeVisitor visitor); - void Accept([NotNull] TreeNodeVisitor visitor, TContext context); - TReturn Accept([NotNull] TreeNodeVisitor visitor, TContext context); } } \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs index 37197c3602..20993b9845 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs @@ -1,4 +1,6 @@ -using JetBrains.Annotations; +using System; +using System.Collections.Generic; +using JetBrains.Annotations; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.ExtensionsAPI; using JetBrains.ReSharper.Psi.ExtensionsAPI.Resolve; @@ -43,7 +45,34 @@ public PropertyReference([NotNull] ReferenceName owner) public override ResolveResultWithInfo ResolveWithoutCache() { - // Look for the item in the properties + if (!(myOwner.GetContainingFile() is IShaderLabFile file)) + return ResolveResultWithInfo.Unresolved; + + if (myOwner.Identifier?.Name == null) + return ResolveResultWithInfo.Unresolved; + + if (file.Command.Value is IShaderValue shaderValue) + { + if (shaderValue.PropertiesCommand.Value is IPropertiesValue propertiesValue) + { + var name = myOwner.Identifier.Name; + var declaredElements = new List(); + foreach (var propertyDeclaration in propertiesValue.DeclarationsEnumerable) + { + var declarationName = propertyDeclaration?.Name?.GetText(); + // TODO: Is ShaderLab case sensitive or not? + // I suspect property references aren't, but Cg references are... + if (string.Equals(name, declarationName, StringComparison.InvariantCulture)) + declaredElements.Add(propertyDeclaration.DeclaredElement); + } + + if (declaredElements.Count > 1) + return new ResolveResultWithInfo(ResolveResultFactory.CreateResolveResult(declaredElements), ResolveErrorType.MULTIPLE_CANDIDATES); + if (declaredElements.Count == 1) + return new ResolveResultWithInfo(ResolveResultFactory.CreateResolveResult(declaredElements[0]), ResolveErrorType.OK); + } + } + return ResolveResultWithInfo.Unresolved; } From 4e2fd6079abf74fb19c87fe02d7651d63ad093c9 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Wed, 14 Feb 2018 12:30:03 +0000 Subject: [PATCH 05/13] Add find usages and context highlighting --- .../ShaderLabUsagesContextHighlighter.cs | 114 ++++++++++++++++++ .../Resolve/IVariableReferenceReference.cs | 9 ++ .../Psi/Search/ShaderLabReferenceSearcher.cs | 44 +++++++ .../Search/ShaderLabTextOccurrenceSearcher.cs | 28 +++++ .../Psi/Search/ShaderLabUsageSearchFactory.cs | 103 ++++++++++++++++ .../ShaderLab/Psi/Tree/IReferenceName.cs | 9 ++ .../ShaderLab/Psi/Tree/Impl/ReferenceName.cs | 7 +- 7 files changed, 311 insertions(+), 3 deletions(-) create mode 100644 resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsagesContextHighlighter.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/Resolve/IVariableReferenceReference.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabReferenceSearcher.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabTextOccurrenceSearcher.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabUsageSearchFactory.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/Tree/IReferenceName.cs diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsagesContextHighlighter.cs b/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsagesContextHighlighter.cs new file mode 100644 index 0000000000..6ce5e34358 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsagesContextHighlighter.cs @@ -0,0 +1,114 @@ +using System; +using JetBrains.Annotations; +using JetBrains.Application.Progress; +using JetBrains.DataFlow; +using JetBrains.ReSharper.Daemon.CaretDependentFeatures; +using JetBrains.ReSharper.Daemon.CSharp.ContextHighlighters; +using JetBrains.ReSharper.Feature.Services.Contexts; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Feature.Services.Navigation.Requests; +using JetBrains.ReSharper.Feature.Services.Occurrences; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.DataContext; +using JetBrains.ReSharper.Psi.Files; +using JetBrains.ReSharper.Psi.Resolve; +using JetBrains.ReSharper.Psi.Search; +using JetBrains.ReSharper.Psi.Tree; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.ContextHighlighters +{ + [ContainsContextConsumer] + public class ShaderLabUsagesContextHighlighter : ContextHighlighterBase + { + [NotNull] private readonly IDeclaredElement myDeclaredElement; + [CanBeNull] private readonly IDeclaration myDeclarationUnderCaret; + + private ShaderLabUsagesContextHighlighter([NotNull] IDeclaredElement declaredElement, [CanBeNull] IDeclaration declarationUnderCaret) + { + myDeclaredElement = declaredElement; + myDeclarationUnderCaret = declarationUnderCaret; + } + + private const string HIGHLIGHTING_ID = HighlightingAttributeIds.USAGE_OF_ELEMENT_UNDER_CURSOR; + + [CanBeNull, AsyncContextConsumer] + public static Action ProcessContext( + [NotNull] Lifetime lifetime, [NotNull] HighlightingProlongedLifetime prolongedLifetime, + [NotNull, ContextKey(typeof(ContextHighlighterPsiFileView.ContextKey))] IPsiDocumentRangeView psiDocumentRangeView, + [NotNull] UsagesContextHighlighterAvailabilityComponent contextHighlighterAvailability) + { + var psiView = psiDocumentRangeView.View(); + +// foreach (var file in psiView.SortedSourceFiles) +// { +// if (!contextHighlighterAvailability.IsAvailable(file)) return null; +// } + + var declaredElement = FindDeclaredElement(psiView, out var declarationUnderCaret); + if (declaredElement == null) return null; + + var highlighter = new ShaderLabUsagesContextHighlighter(declaredElement, declarationUnderCaret); + return highlighter.GetDataProcessAction(prolongedLifetime, psiDocumentRangeView); + } + + private static IDeclaredElement FindDeclaredElement(IPsiView psiView, out IDeclaration declarationUnderCaret) + { + declarationUnderCaret = null; + + var referenceName = psiView.GetSelectedTreeNode(); + if (referenceName != null) + return referenceName.Reference.Resolve().DeclaredElement; + + declarationUnderCaret = psiView.GetSelectedTreeNode(); + return declarationUnderCaret?.DeclaredElement; + } + + protected override void CollectHighlightings(IPsiDocumentRangeView psiDocumentRangeView, HighlightingsConsumer consumer) + { + if (myDeclarationUnderCaret != null) + HighlightDeclaration(myDeclarationUnderCaret, consumer); + else + { + var psiView = psiDocumentRangeView.View(PsiLanguageCategories.Dominant); + HighlightDeclarationsInFile(myDeclaredElement, psiView, consumer); + } + HighlightReferencesInFile(myDeclaredElement, psiDocumentRangeView, consumer); + } + + private void HighlightReferencesInFile(IDeclaredElement declaredElement, + IPsiDocumentRangeView psiDocumentRangeView, HighlightingsConsumer consumer) + { + var searchDomain = SearchDomainFactory.Instance.CreateSearchDomain(psiDocumentRangeView.SortedSourceFiles); + var elements = new[] {new DeclaredElementInstance(declaredElement)}; + var searchRequest = new SearchSingleFileDeclaredElementRequest(elements, elements, searchDomain); + + foreach (var occurrence in searchRequest.Search(NullProgressIndicator.Create())) + { + if (!(occurrence is ReferenceOccurrence referenceOccurrence)) continue; + + var primaryReference = referenceOccurrence.PrimaryReference; + if (primaryReference == null) continue; + + var documentRange = primaryReference.GetDocumentRange(); + consumer.ConsumeHighlighting(HIGHLIGHTING_ID, documentRange); + } + } + + private void HighlightDeclaration(IDeclaration declaration, HighlightingsConsumer consumer) + { + var nameDocumentRange = declaration.GetNameDocumentRange(); + if (nameDocumentRange.IsValid()) + consumer.ConsumeHighlighting(HIGHLIGHTING_ID, nameDocumentRange); + } + + private void HighlightDeclarationsInFile(IDeclaredElement declaredElement, IPsiView psiView, + HighlightingsConsumer consumer) + { + foreach (var psiSourceFile in psiView.SortedSourceFiles) + foreach (var declaration in declaredElement.GetDeclarationsIn(psiSourceFile)) + HighlightDeclaration(declaration, consumer); + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Resolve/IVariableReferenceReference.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Resolve/IVariableReferenceReference.cs new file mode 100644 index 0000000000..8b1beb9620 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Resolve/IVariableReferenceReference.cs @@ -0,0 +1,9 @@ +using JetBrains.ReSharper.Psi.Resolve; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Resolve +{ + // TODO: Terrible name... + public interface IVariableReferenceReference : IReference //, ICompletableReference + { + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabReferenceSearcher.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabReferenceSearcher.cs new file mode 100644 index 0000000000..8f6d099dcb --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabReferenceSearcher.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree.Impl; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.ExtensionsAPI; +using JetBrains.ReSharper.Psi.ExtensionsAPI.Finder; +using JetBrains.ReSharper.Psi.Files; +using JetBrains.ReSharper.Psi.Search; +using JetBrains.ReSharper.Psi.Tree; +using JetBrains.Util; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Search +{ + public class ShaderLabReferenceSearcher : IDomainSpecificSearcher + { + private readonly IDeclaredElementsSet myElements; + private readonly bool myFindCandidates; + private readonly List myElementNames; + + public ShaderLabReferenceSearcher(IDeclaredElementsSet elements, bool findCandidates) + { + myElements = elements; + myFindCandidates = findCandidates; + + myElementNames = new List(); + foreach (var element in elements) + myElementNames.Add(element.ShortName); + } + + public bool ProcessProjectItem(IPsiSourceFile sourceFile, IFindResultConsumer consumer) + { + if (!(sourceFile.GetPrimaryPsiFile() is ShaderLabFile shaderLabFile)) + return false; + return ProcessElement(shaderLabFile, consumer); + } + + public bool ProcessElement(ITreeNode element, IFindResultConsumer consumer) + { + Assertion.AssertNotNull(element, "element != null"); + var result = new ReferenceSearchSourceFileProcessor(element, myFindCandidates, consumer, + myElements, myElementNames, myElementNames).Run(); + return result == FindExecution.Stop; + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabTextOccurrenceSearcher.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabTextOccurrenceSearcher.cs new file mode 100644 index 0000000000..6cd7ec2ddf --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabTextOccurrenceSearcher.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.ExtensionsAPI; +using JetBrains.ReSharper.Psi.ExtensionsAPI.Finder; +using JetBrains.ReSharper.Psi.Tree; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Search +{ + // TODO: I don't know when this gets used + public class ShaderLabTextOccurrenceSearcher : TextOccurrenceSearcherBase, IDomainSpecificSearcher + { + public ShaderLabTextOccurrenceSearcher(IEnumerable elements) + : base(elements) + { + } + + public ShaderLabTextOccurrenceSearcher(string subject) + : base(subject) + { + } + + protected override Predicate Predicate + { + get { return node => true; } + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabUsageSearchFactory.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabUsageSearchFactory.cs new file mode 100644 index 0000000000..0387aee5f3 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Search/ShaderLabUsageSearchFactory.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.ExtensionsAPI; +using JetBrains.ReSharper.Psi.Impl.Search.SearchDomain; +using JetBrains.ReSharper.Psi.Search; +using JetBrains.Util; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Search +{ + [PsiSharedComponent] + public class ShaderLabUsageSearchFactory : IDomainSpecificSearcherFactory + { + private readonly SearchDomainFactory mySearchDomainFactory; + + public ShaderLabUsageSearchFactory(SearchDomainFactory searchDomainFactory) + { + mySearchDomainFactory = searchDomainFactory; + } + + public bool IsCompatibleWithLanguage(PsiLanguageType languageType) + { + return languageType.Is(); + } + + public IDomainSpecificSearcher CreateConstructorSpecialReferenceSearcher(ICollection constructors) + { + return null; + } + + public IDomainSpecificSearcher CreateMethodsReferencedByDelegateSearcher(IDelegate @delegate) + { + return null; + } + + public IDomainSpecificSearcher CreateReferenceSearcher(IDeclaredElementsSet elements, bool findCandidates) + { + if (elements.Any(element => !(element is IShaderLabDeclaredElement))) + return null; + return new ShaderLabReferenceSearcher(elements, findCandidates); + } + + public IDomainSpecificSearcher CreateLateBoundReferenceSearcher(IDeclaredElementsSet elements) + { + return null; + } + + public IDomainSpecificSearcher CreateTextOccurrenceSearcher(IDeclaredElementsSet elements) + { + return new ShaderLabTextOccurrenceSearcher(elements); + } + + public IDomainSpecificSearcher CreateTextOccurrenceSearcher(string subject) + { + return new ShaderLabTextOccurrenceSearcher(subject); + } + + public IDomainSpecificSearcher CreateAnonymousTypeSearcher(IList typeDescription, bool caseSensitive) + { + return null; + } + + public IDomainSpecificSearcher CreateConstantExpressionSearcher(ConstantValue constantValue, bool onlyLiteralExpression) + { + return null; + } + + public IEnumerable GetAllPossibleWordsInFile(IDeclaredElement element) + { + yield return element.ShortName; + } + + public IEnumerable GetRelatedDeclaredElements(IDeclaredElement element) + { + return EmptyList.InstanceList; + } + + public Tuple, Predicate, bool> GetDerivedFindRequest(IFindResultReference result) + { + return null; + } + + public Tuple, bool> GetNavigateToTargets(IDeclaredElement element) + { + return null; + } + + public ICollection TransformNavigationTargets(ICollection targets) + { + return targets; + } + + public ISearchDomain GetDeclaredElementSearchDomain(IDeclaredElement declaredElement) + { + if (!(declaredElement is IShaderLabDeclaredElement)) + return EmptySearchDomain.Instance; + + return mySearchDomainFactory.CreateSearchDomain(declaredElement.GetSourceFiles()); + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/IReferenceName.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/IReferenceName.cs new file mode 100644 index 0000000000..5de681dac8 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/IReferenceName.cs @@ -0,0 +1,9 @@ +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Resolve; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree +{ + public partial interface IReferenceName + { + IVariableReferenceReference Reference { get; } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs index 20993b9845..be807624a9 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using JetBrains.Annotations; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Resolve; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.ExtensionsAPI; using JetBrains.ReSharper.Psi.ExtensionsAPI.Resolve; @@ -12,14 +13,14 @@ namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree.Impl { internal partial class ReferenceName { - private IReference myReference; + private IVariableReferenceReference myReference; public override ReferenceCollection GetFirstClassReferences() { return new ReferenceCollection(Reference); } - public IReference Reference + public IVariableReferenceReference Reference { get { @@ -36,7 +37,7 @@ public IReference Reference } } - private class PropertyReference : TreeReferenceBase + private class PropertyReference : TreeReferenceBase, IVariableReferenceReference { public PropertyReference([NotNull] ReferenceName owner) : base(owner) From 07851a204d578cbe9111f33393cabf83e6f0dd82 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Wed, 14 Feb 2018 13:21:48 +0000 Subject: [PATCH 06/13] Disable PSI for duplicate .shader files The files are duplicated by Visual C++ adding them to a hidden project for "single file intellisense" --- .../ShaderLabDeclaredElementBase.cs | 4 +- ...leFileIntellisensePsiPropertiesProvider.cs | 40 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/SingleFileIntellisensePsiPropertiesProvider.cs diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs index 1ee53b6128..d05a8f429d 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs @@ -65,7 +65,9 @@ public bool HasDeclarationsIn(IPsiSourceFile sourceFile) } public string ShortName { get; } - public bool CaseSensitiveName => true; // TODO: Check! + + // Note that ShaderLab variable references and Cg parameters are case sensitive + public bool CaseSensitiveName => true; // ReSharper disable once AssignNullToNotNullAttribute public PsiLanguageType PresentationLanguage => ShaderLabLanguage.Instance; diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/SingleFileIntellisensePsiPropertiesProvider.cs b/resharper/src/resharper-unity/ShaderLab/Psi/SingleFileIntellisensePsiPropertiesProvider.cs new file mode 100644 index 0000000000..5524ab2862 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/SingleFileIntellisensePsiPropertiesProvider.cs @@ -0,0 +1,40 @@ +using JetBrains.ProjectModel; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.ProjectModel; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.Modules.ExternalFileModules; +using JetBrains.ReSharper.Psi.PerformanceThreshold; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi +{ + // Visual C++ creates a hidden project to contain files for "single file intellisense". + // https://blogs.msdn.microsoft.com/vcblog/2015/04/29/single-file-intellisense-and-other-ide-improvements-in-vs2015/ + // For some reason, it will add open .shader files, although we don't get intellisense. + // I presume this is some kind of DirectX format (Cg/HLSL/whatever). ReSharper creates + // a PSI module for this project, complete with PSI source files for the .shader files + // that already exist in the normal C# project. This means we parse them multiple times + // and causes issues with resolve - find usages on a ShaderLab property now has two + // targets, one from the C# project and another from the hidden VC++ project. + // This provider will provide new PSI properties for the hidden .shader files, so that + // we don't add them into the PSI code model. + [PsiSharedComponent] + public class SingleFileIntellisensePsiPropertiesProvider : IPsiSourceFilePropertiesProvider + { + public IPsiSourceFileProperties GetPsiProperties(IPsiSourceFileProperties prevProperties, IProject project, + IProjectFile projectFile, IPsiSourceFile sourceFile) + { + // R# already has a helper method to recognise the SFI project - IsVCXMiscProjectInVs2015 + if (prevProperties != null && prevProperties.ShouldBuildPsi + && prevProperties.ProvidesCodeModel + && !(sourceFile is IExternalPsiSourceFile) + && project.IsVCXMiscProjectInVs2015() + && projectFile.LanguageType.Is()) + { + return ExcludedProjectPsiSourceFilePropertiesProvider.ExcludedProjectPsiSourceFileProperties.Instance; + } + + return prevProperties; + } + + public double Order => int.MaxValue; + } +} \ No newline at end of file From 47b21f7e879d0def3294132b814944c45d805bed Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Thu, 15 Feb 2018 00:09:30 +0000 Subject: [PATCH 07/13] Add resolve error handle for multiple candidates --- .../Daemon/Errors/ShaderLabErrors.xml | 12 ++ ...ltipleCandidatesNotResolvedErrorHandler.cs | 42 +++++++ .../Resolve/ResolveProblemHighlighter.cs | 58 +++++----- .../IPropertyDeclaredElement.cs | 8 ++ .../PropertyDeclaredElement.cs | 21 +++- .../ShaderLabDeclaredElementPresenter.cs | 109 +++++++++++++++++- ...ShaderLabDeclaredElementPresenterStyles.cs | 18 +++ .../ShaderLabDeclaredElementType.cs | 2 +- .../ShaderLab/Psi/ShaderLabLanguageService.cs | 5 + .../ShaderLab/Psi/Tree/Impl/ReferenceName.cs | 9 +- 10 files changed, 243 insertions(+), 41 deletions(-) create mode 100644 resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/MultipleCandidatesNotResolvedErrorHandler.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/IPropertyDeclaredElement.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenterStyles.cs diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml b/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml index e9c6d5c0eb..234881963d 100644 --- a/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml @@ -28,6 +28,18 @@ Reference.GetDocumentRange() + + + + + + + Candidates + Environment.NewLine + + TextRange + + diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/MultipleCandidatesNotResolvedErrorHandler.cs b/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/MultipleCandidatesNotResolvedErrorHandler.cs new file mode 100644 index 0000000000..fe7a1e8dd7 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/MultipleCandidatesNotResolvedErrorHandler.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Errors; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.Resolve; +using JetBrains.Util; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Stages.Resolve +{ + [Language(typeof(ShaderLabLanguage))] + public class MultipleCandidatesNotResolvedErrorHandler : IResolveProblemHighlighter + { + public IHighlighting Run(IReference reference) + { + var resolveResult = reference.Resolve(); + if (resolveResult.Result.Candidates.Count > 1) + { + var candidates = resolveResult.Result.Candidates; + var result = new List(); + foreach (var candidate in candidates) + { + result.Add(Environment.NewLine + " " + DeclaredElementPresenter.Format(ShaderLabLanguage.Instance, + ShaderLabDeclaredElementPresenterStyles.CANDIDATE_PRESENTER, candidate)); + } + result.Sort(); + var message = result.AggregateString(""); + var range = reference.GetDocumentRange(); + return new MultipleResolveCandidatesError(range, message, reference); + } + + return null; + } + + public IEnumerable ErrorTypes => new[] + { + ResolveErrorType.MULTIPLE_CANDIDATES + }; + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/ResolveProblemHighlighter.cs b/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/ResolveProblemHighlighter.cs index 5a41aef603..297f9b72c6 100644 --- a/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/ResolveProblemHighlighter.cs +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Resolve/ResolveProblemHighlighter.cs @@ -7,38 +7,40 @@ namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Stages.Resolve { - internal class ResolveProblemHighlighter - { - private readonly ResolveHighlighterRegistrar myResolveHighlighterRegistrar; - - public ResolveProblemHighlighter(ResolveHighlighterRegistrar resolveHighlighterRegistrar) + internal class ResolveProblemHighlighter { - myResolveHighlighterRegistrar = resolveHighlighterRegistrar; - } + private readonly ResolveHighlighterRegistrar myResolveHighlighterRegistrar; - public void CheckForResolveProblems(ITreeNode node, IHighlightingConsumer consumer, ReferenceCollection references) - { - foreach (var reference in references) - CheckForResolveProblems(consumer, reference); - } + public ResolveProblemHighlighter(ResolveHighlighterRegistrar resolveHighlighterRegistrar) + { + myResolveHighlighterRegistrar = resolveHighlighterRegistrar; + } - private void CheckForResolveProblems(IHighlightingConsumer consumer, IReference reference) - { - var error = reference.CheckResolveResult(); - if (error == null) - throw new InvalidOperationException("ResolveErrorType is null for reference " + reference.GetType().FullName); + public void CheckForResolveProblems(ITreeNode node, IHighlightingConsumer consumer, + ReferenceCollection references) + { + foreach (var reference in references) + CheckForResolveProblems(consumer, reference); + } + + private void CheckForResolveProblems(IHighlightingConsumer consumer, IReference reference) + { + var error = reference.CheckResolveResult(); + if (error == null) + throw new InvalidOperationException("ResolveErrorType is null for reference " + + reference.GetType().FullName); - if (error == ResolveErrorType.OK) - return; + if (error == ResolveErrorType.OK) + return; - if (myResolveHighlighterRegistrar.ContainsHandler(ShaderLabLanguage.Instance, error)) - { - var highlighting = myResolveHighlighterRegistrar.GetResolveHighlighting(reference, error); - if (highlighting != null) - consumer.AddHighlighting(highlighting); - } - else - consumer.AddHighlighting(new NotResolvedError(reference)); + if (myResolveHighlighterRegistrar.ContainsHandler(ShaderLabLanguage.Instance, error)) + { + var highlighting = myResolveHighlighterRegistrar.GetResolveHighlighting(reference, error); + if (highlighting != null) + consumer.AddHighlighting(highlighting); + } + else + consumer.AddHighlighting(new NotResolvedError(reference)); + } } - } } \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/IPropertyDeclaredElement.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/IPropertyDeclaredElement.cs new file mode 100644 index 0000000000..ffea967baf --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/IPropertyDeclaredElement.cs @@ -0,0 +1,8 @@ +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements +{ + public interface IPropertyDeclaredElement : IShaderLabDeclaredElement + { + string GetDisplayName(); + string GetPropertyType(); + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs index 794ff75ba6..9d8f39e2a2 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs @@ -1,8 +1,9 @@ -using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree; +using JetBrains.ReSharper.Psi; namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements { - public class PropertyDeclaredElement : ShaderLabDeclaredElementBase + public class PropertyDeclaredElement : ShaderLabDeclaredElementBase, IPropertyDeclaredElement { public PropertyDeclaredElement(string shortName, IPsiSourceFile sourceFile, int treeOffset) : base(shortName, sourceFile, treeOffset) @@ -10,5 +11,21 @@ public PropertyDeclaredElement(string shortName, IPsiSourceFile sourceFile, int } public override DeclaredElementType GetElementType() => ShaderLabDeclaredElementType.Property; + + public string GetDisplayName() + { + var declarations = GetDeclarations(); + if (declarations.Count > 0 && declarations[0] is IPropertyDeclaration declaration) + return declaration.DisplayName?.GetText() ?? string.Empty; + return string.Empty; + } + + public string GetPropertyType() + { + var declarations = GetDeclarations(); + if (declarations.Count > 0 && declarations[0] is IPropertyDeclaration declaration) + return declaration.PropertyType?.GetText() ?? string.Empty; + return string.Empty; + } } } \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenter.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenter.cs index c3573acf75..29a515cbd3 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenter.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenter.cs @@ -1,4 +1,6 @@ -using JetBrains.ReSharper.Psi; +using System; +using System.Text; +using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.Resolve; using JetBrains.Util; @@ -7,6 +9,8 @@ namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements [PsiSharedComponent] public class ShaderLabDeclaredElementPresenter : IDeclaredElementPresenter { + public static ShaderLabDeclaredElementPresenter Instance => PsiShared.GetComponent(); + public string Format(DeclaredElementPresenterStyle style, IDeclaredElement element, ISubstitution substitution, out DeclaredElementPresenterMarking marking) { @@ -14,12 +18,109 @@ public string Format(DeclaredElementPresenterStyle style, IDeclaredElement eleme if (!(element is IShaderLabDeclaredElement)) return null; - // TODO: Type (Float, Color, etc.), display name, etc. - marking.NameRange = new TextRange(0, element.ShortName.Length); - return element.ShortName; + var result = new StringBuilder(); + + if (style.ShowEntityKind != EntityKindForm.NONE) + { + var entityKind = GetEntityKind(element); + if (entityKind != string.Empty) + { + if (style.ShowEntityKind == EntityKindForm.NORMAL_IN_BRACKETS) + entityKind = "(" + entityKind + ")"; + marking.EntityKindRange = AppendString(result, entityKind); + result.Append(" "); + } + } + + if (style.ShowNameInQuotes) + result.Append("\'"); + + if (style.ShowType == TypeStyle.DEFAULT) + { + var typeName = GetTypeName(element); + if (!string.IsNullOrEmpty(typeName)) + { + marking.TypeRange = marking.ScalarTypeRange = AppendString(result, typeName); + result.Append(" "); + } + } + + if (style.ShowName != NameStyle.NONE) + { + marking.NameRange = AppendString(result, element.ShortName); + result.Append(" "); + } + + if (style.ShowType == TypeStyle.AFTER) + { + var typeName = GetTypeName(element); + if (!string.IsNullOrEmpty(typeName)) + { + result.Append(": "); + marking.TypeRange = marking.ScalarTypeRange = AppendString(result, typeName); + result.Append(" "); + } + } + + if (style.ShowNameInQuotes) + { + TrimString(result); + result.Append("\'"); + } + + if (style.ShowName != NameStyle.NONE && style.ShowName != NameStyle.SHORT && + style.ShowName != NameStyle.SHORT_RAW) + { + AppendDisplayName(result, element); + } + + if (style.ShowConstantValue) + { + } + + TrimString(result); + return result.ToString(); } public string Format(ParameterKind parameterKind) => string.Empty; public string Format(AccessRights accessRights) => string.Empty; + + private static void TrimString(StringBuilder sb) + { + while (sb.Length > 0 && sb[sb.Length - 1] == ' ') + sb.Remove(sb.Length - 1, 1); + } + + private static TextRange AppendString(StringBuilder sb, string substr) + { + var s = sb.Length; + sb.Append(substr); + return substr.Length == 0 ? TextRange.InvalidRange : new TextRange(s, sb.Length); + } + + private static string GetEntityKind(IDeclaredElement element) + { + return element is IPropertyDeclaredElement ? "property" : string.Empty; + } + + private string GetTypeName(IDeclaredElement element) + { + if (element is IPropertyDeclaredElement property) + return property.GetPropertyType(); + return string.Empty; + } + + private void AppendDisplayName(StringBuilder result, IDeclaredElement element) + { + if (element is IPropertyDeclaredElement property) + { + var displayName = property.GetDisplayName(); + if (!string.IsNullOrEmpty(displayName)) + { + result.Append(displayName); + result.Append(" "); + } + } + } } } \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenterStyles.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenterStyles.cs new file mode 100644 index 0000000000..69b58d3683 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementPresenterStyles.cs @@ -0,0 +1,18 @@ +using JetBrains.ReSharper.Psi; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements +{ + public static class ShaderLabDeclaredElementPresenterStyles + { + public static readonly DeclaredElementPresenterStyle CANDIDATE_PRESENTER; + + static ShaderLabDeclaredElementPresenterStyles() + { + CANDIDATE_PRESENTER = new DeclaredElementPresenterStyle + { + ShowName = NameStyle.QUALIFIED, + ShowType = TypeStyle.DEFAULT + }; + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs index 63a0fa6c5a..f27ec1dfa6 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs @@ -22,6 +22,6 @@ private ShaderLabDeclaredElementType(string name, IconId iconId) protected override IconId GetImage() => myIconId; public override bool IsPresentable(PsiLanguageType language) => language.Is(); protected override IDeclaredElementPresenter DefaultPresenter => - ShaderLabLanguage.Instance.DeclaredElementPresenter(); + ShaderLabDeclaredElementPresenter.Instance; } } \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/ShaderLabLanguageService.cs b/resharper/src/resharper-unity/ShaderLab/Psi/ShaderLabLanguageService.cs index e32b19380c..aaaa152542 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/ShaderLabLanguageService.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/ShaderLabLanguageService.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements; using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Parsing; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.ExtensionsAPI.Caches2; @@ -16,6 +17,7 @@ namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi public class ShaderLabLanguageService : LanguageService { private readonly CommonIdentifierIntern myCommonIdentifierIntern; + private IDeclaredElementPresenter myPresenter; public ShaderLabLanguageService(ShaderLabLanguage psiLanguageType, IConstantValueService constantValueService, CommonIdentifierIntern commonIdentifierIntern) : base(psiLanguageType, constantValueService) @@ -50,6 +52,9 @@ public override IEnumerable FindTypeDeclarations(IFile file) public override bool SupportTypeMemberCache => false; public override ITypePresenter TypePresenter => DefaultTypePresenter.Instance; + public override IDeclaredElementPresenter DeclaredElementPresenter => + myPresenter ?? (myPresenter = ShaderLabDeclaredElementPresenter.Instance); + private class ShaderLabLexerFactory : ILexerFactory { public ILexer CreateLexer(IBuffer buffer) diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs index be807624a9..dde5fc45c1 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs @@ -61,16 +61,13 @@ public override ResolveResultWithInfo ResolveWithoutCache() foreach (var propertyDeclaration in propertiesValue.DeclarationsEnumerable) { var declarationName = propertyDeclaration?.Name?.GetText(); - // TODO: Is ShaderLab case sensitive or not? - // I suspect property references aren't, but Cg references are... + + // Note that both ShaderLab and Cg are case sensitive if (string.Equals(name, declarationName, StringComparison.InvariantCulture)) declaredElements.Add(propertyDeclaration.DeclaredElement); } - if (declaredElements.Count > 1) - return new ResolveResultWithInfo(ResolveResultFactory.CreateResolveResult(declaredElements), ResolveErrorType.MULTIPLE_CANDIDATES); - if (declaredElements.Count == 1) - return new ResolveResultWithInfo(ResolveResultFactory.CreateResolveResult(declaredElements[0]), ResolveErrorType.OK); + return ResolveUtil.CreateResolveResult(declaredElements); } } From 48cfa5eacd3596dd7b34cda3a945dd50c502f2b9 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Thu, 15 Feb 2018 10:54:07 +0000 Subject: [PATCH 08/13] Respect Rider's context usage highlight option --- ...rLabUsageContextHighlighterAvailability.cs | 28 +++++++++++++++++++ ...rLabUsageContextHighlighterAvailability.cs | 19 +++++++++++++ .../ShaderLabUsagesContextHighlighter.cs | 10 +++---- .../resharper-unity.rider.csproj.DotSettings | 3 ++ 4 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/Rider/RiderShaderLabUsageContextHighlighterAvailability.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsageContextHighlighterAvailability.cs create mode 100644 resharper/src/resharper-unity/resharper-unity.rider.csproj.DotSettings diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/Rider/RiderShaderLabUsageContextHighlighterAvailability.cs b/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/Rider/RiderShaderLabUsageContextHighlighterAvailability.cs new file mode 100644 index 0000000000..7d21ab7b12 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/Rider/RiderShaderLabUsageContextHighlighterAvailability.cs @@ -0,0 +1,28 @@ +#if RIDER + +using JetBrains.Annotations; +using JetBrains.Application; +using JetBrains.Platform.RdFramework.Util; +using JetBrains.ReSharper.Psi; +using JetBrains.Rider.Model; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.ContextHighlighters +{ + [ShellComponent] + public class RiderShaderLabUsageContextHighlighterAvailability : ShaderLabUsageContextHighlighterAvailability + { + private readonly IRdProperty myIsAvailable; + + public RiderShaderLabUsageContextHighlighterAvailability([NotNull] SettingsModel settingsModel) + { + myIsAvailable = settingsModel.HighlightElementUnderCursor; + } + + public override bool IsAvailable(IPsiSourceFile psiSourceFile) + { + return myIsAvailable.HasValue() && myIsAvailable.Value; + } + } +} + +#endif \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsageContextHighlighterAvailability.cs b/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsageContextHighlighterAvailability.cs new file mode 100644 index 0000000000..2b0eb963e7 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsageContextHighlighterAvailability.cs @@ -0,0 +1,19 @@ +using JetBrains.Annotations; +using JetBrains.Application; +using JetBrains.ReSharper.Psi; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.ContextHighlighters +{ + [ShellComponent] + public class ShaderLabUsageContextHighlighterAvailability + { + public virtual bool IsAvailable([NotNull] IPsiSourceFile psiSourceFile) + { + // Always available in ReSharper - R# doesn't have an option for this, + // and actually lets Visual Studio do it for C#. It only does it for + // C# files that are non user files (e.g. decompiled files). + // Rider has an option, so we have a derived class that checks that. + return true; + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsagesContextHighlighter.cs b/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsagesContextHighlighter.cs index 6ce5e34358..c113384e05 100644 --- a/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsagesContextHighlighter.cs +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/ContextHighlighters/ShaderLabUsagesContextHighlighter.cs @@ -37,14 +37,14 @@ private ShaderLabUsagesContextHighlighter([NotNull] IDeclaredElement declaredEle public static Action ProcessContext( [NotNull] Lifetime lifetime, [NotNull] HighlightingProlongedLifetime prolongedLifetime, [NotNull, ContextKey(typeof(ContextHighlighterPsiFileView.ContextKey))] IPsiDocumentRangeView psiDocumentRangeView, - [NotNull] UsagesContextHighlighterAvailabilityComponent contextHighlighterAvailability) + [NotNull] ShaderLabUsageContextHighlighterAvailability contextHighlighterAvailability) { var psiView = psiDocumentRangeView.View(); -// foreach (var file in psiView.SortedSourceFiles) -// { -// if (!contextHighlighterAvailability.IsAvailable(file)) return null; -// } + foreach (var file in psiView.SortedSourceFiles) + { + if (!contextHighlighterAvailability.IsAvailable(file)) return null; + } var declaredElement = FindDeclaredElement(psiView, out var declarationUnderCaret); if (declaredElement == null) return null; diff --git a/resharper/src/resharper-unity/resharper-unity.rider.csproj.DotSettings b/resharper/src/resharper-unity/resharper-unity.rider.csproj.DotSettings new file mode 100644 index 0000000000..b23f1502f7 --- /dev/null +++ b/resharper/src/resharper-unity/resharper-unity.rider.csproj.DotSettings @@ -0,0 +1,3 @@ + + False + True \ No newline at end of file From 8c5b33949c82252baf8bac0bb6168c3b4a368eeb Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Thu, 15 Feb 2018 22:54:35 +0000 Subject: [PATCH 09/13] Add warnings for multiply declared properties --- .../Daemon/Errors/ShaderLabErrors.xml | 22 ++++++++++ ...icatePropertyDeclarationProblemAnalyzer.cs | 41 +++++++++++++++++++ .../DuplicatePropertyHighlights.shader | 12 ++++++ .../DuplicatePropertyHighlights.shader.gold | 19 +++++++++ ...LabDuplicatePropertiesHighlightingTests.cs | 19 +++++++++ 5 files changed, 113 insertions(+) create mode 100644 resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyDeclarationProblemAnalyzer.cs create mode 100644 resharper/test/data/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyHighlights.shader create mode 100644 resharper/test/data/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyHighlights.shader.gold create mode 100644 resharper/test/src/ShaderLab/Daemon/Stages/Analysis/ShaderLabDuplicatePropertiesHighlightingTests.cs diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml b/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml index 234881963d..85a140c27f 100644 --- a/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/Errors/ShaderLabErrors.xml @@ -76,4 +76,26 @@ RemoveUnusedElementFix + + + + + + + DeclarationName + + DocumentRange + + + + + + + + + DeclarationName + + DocumentRange + + \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyDeclarationProblemAnalyzer.cs b/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyDeclarationProblemAnalyzer.cs new file mode 100644 index 0000000000..d1225b2077 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyDeclarationProblemAnalyzer.cs @@ -0,0 +1,41 @@ +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Errors; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree; +using JetBrains.Util; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Stages.Analysis +{ + [ElementProblemAnalyzer(typeof(IPropertiesValue), HighlightingTypes = new[] { typeof(ShaderLabFirstDuplicatePropertyWarning), typeof(ShaderLabSubsequentDuplicatePropertyWarning)})] + public class DuplicatePropertyDeclarationProblemAnalyzer : ShaderLabElementProblemAnalyzer + { + protected override void Analyze(IPropertiesValue element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) + { + var propertiesByName = new OneToListMap(); + foreach (var propertyDeclaration in element.DeclarationsEnumerable) + { + var propertyName = propertyDeclaration.Name?.GetText(); + if (string.IsNullOrEmpty(propertyName)) + continue; + + propertiesByName.AddValue(propertyName, propertyDeclaration); + } + + foreach (var pair in propertiesByName) + { + if (pair.Value.Count > 1) + { + var propertyDeclaration = pair.Value[0]; + consumer.AddHighlighting(new ShaderLabFirstDuplicatePropertyWarning(propertyDeclaration, pair.Key, + propertyDeclaration.Name.GetHighlightingRange())); + for (var i = 1; i < pair.Value.Count; i++) + { + propertyDeclaration = pair.Value[i]; + consumer.AddHighlighting(new ShaderLabSubsequentDuplicatePropertyWarning(propertyDeclaration, + pair.Key, propertyDeclaration.Name.GetHighlightingRange())); + } + } + } + } + } +} \ No newline at end of file diff --git a/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyHighlights.shader b/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyHighlights.shader new file mode 100644 index 0000000000..db2b03dcbd --- /dev/null +++ b/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyHighlights.shader @@ -0,0 +1,12 @@ +Shader "Unlit/SingleColor" +{ + Properties + { + _Op ("Op value", float) = 1 + _Op ("Another op value", float) = 1 + _Op ("Three ops!", float) = 1 + _Nothing ("Boring", int) = 1 + _Another ("Something else", float) = 1 + _Another ("More", float) = 1 + } +} diff --git a/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyHighlights.shader.gold b/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyHighlights.shader.gold new file mode 100644 index 0000000000..c9e8989d07 --- /dev/null +++ b/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/DuplicatePropertyHighlights.shader.gold @@ -0,0 +1,19 @@ +Shader "Unlit/SingleColor" +{ + Properties + { + |_Op|(0) ("Op value", float) = 1 + |_Op|(1) ("Another op value", float) = 1 + |_Op|(2) ("Three ops!", float) = 1 + _Nothing ("Boring", int) = 1 + |_Another|(3) ("Something else", float) = 1 + |_Another|(4) ("More", float) = 1 + } +} + +--------------------------------------------------------- +(0): ReSharper Warning: Conflicting property '_Op' is defined below +(1): ReSharper Warning: There is already a property named '_Op' declared +(2): ReSharper Warning: There is already a property named '_Op' declared +(3): ReSharper Warning: Conflicting property '_Another' is defined below +(4): ReSharper Warning: There is already a property named '_Another' declared diff --git a/resharper/test/src/ShaderLab/Daemon/Stages/Analysis/ShaderLabDuplicatePropertiesHighlightingTests.cs b/resharper/test/src/ShaderLab/Daemon/Stages/Analysis/ShaderLabDuplicatePropertiesHighlightingTests.cs new file mode 100644 index 0000000000..db89689ca2 --- /dev/null +++ b/resharper/test/src/ShaderLab/Daemon/Stages/Analysis/ShaderLabDuplicatePropertiesHighlightingTests.cs @@ -0,0 +1,19 @@ +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Errors; +using JetBrains.ReSharper.Psi; +using NUnit.Framework; + +namespace JetBrains.ReSharper.Plugins.Unity.Tests.ShaderLab.Daemon.Stages.Analysis +{ + public class ShaderLabDuplicatePropertiesHighlightingTests : ShaderLabHighlightingTestBase + { + protected override string RelativeTestDataPath => @"ShaderLab\Daemon\Stages\Analysis"; + + protected override bool HighlightingPredicate(IHighlighting highlighting, IPsiSourceFile sourceFile) + { + return highlighting is ShaderLabHighlightingBase; + } + + [Test] public void TestDuplicatePropertyHighlights() { DoNamedTest2(); } + } +} \ No newline at end of file From 517605d334e3ea8c170e8367012b48fe0defaed9 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Thu, 15 Feb 2018 23:40:11 +0000 Subject: [PATCH 10/13] Add tests for property usage highlights --- .../PropertyUsage/PropertyUsage01.shader | 29 ++++++++++++++ .../PropertyUsage/PropertyUsage01.shader.gold | 37 ++++++++++++++++++ .../PropertyUsage/PropertyUsage02.shader | 29 ++++++++++++++ .../PropertyUsage/PropertyUsage02.shader.gold | 38 +++++++++++++++++++ ...rLabPropertyUsageContextHighlighterTest.cs | 17 +++++++++ 5 files changed, 150 insertions(+) create mode 100644 resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage01.shader create mode 100644 resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage01.shader.gold create mode 100644 resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage02.shader create mode 100644 resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage02.shader.gold create mode 100644 resharper/test/src/ShaderLab/Daemon/ContextHighlighters/ShaderLabPropertyUsageContextHighlighterTest.cs diff --git a/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage01.shader b/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage01.shader new file mode 100644 index 0000000000..6ad3c22e7d --- /dev/null +++ b/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage01.shader @@ -0,0 +1,29 @@ +Shader "Foo" +{ + Properties + { + _C{caret:Color}olor ("Color", Color) = (1,1,1,1) + _Src{caret:SrcBlend}Blend ("SrcBlend", Int) = 5.0 + _DstBlend ("DstBlend", Int) = 10.0 + _ZWrite ("ZWrite", Int) = 1.0 + _ZTest ("ZTest", Int) = 4.0 + _Cull ("Cull", Int) = 0.0 + _Z{caret:ZBias}Bias ("ZBias", Float) = 0.0 + } + + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Pass + { + Blend [_SrcBlend] [_DstBlend] + ZWrite [_ZWrite] + ZTest [_ZTest] + Cull [_Cull] + Offset [_ZBias], [_ZBias] + + CGPROGRAM + ENDCG + } + } +} diff --git a/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage01.shader.gold b/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage01.shader.gold new file mode 100644 index 0000000000..6b088630fc --- /dev/null +++ b/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage01.shader.gold @@ -0,0 +1,37 @@ +Shader "Foo" +{ + Properties + { + |_Color|(0:Color) ("Color", Color) = (1,1,1,1) + |_SrcBlend|(1:SrcBlend) ("SrcBlend", Int) = 5.0 + _DstBlend ("DstBlend", Int) = 10.0 + _ZWrite ("ZWrite", Int) = 1.0 + _ZTest ("ZTest", Int) = 4.0 + _Cull ("Cull", Int) = 0.0 + |_ZBias|(2:ZBias) ("ZBias", Float) = 0.0 + } + + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Pass + { + Blend [|_SrcBlend|(3:SrcBlend)] [_DstBlend] + ZWrite [_ZWrite] + ZTest [_ZTest] + Cull [_Cull] + Offset [|_ZBias|(4:ZBias)], [|_ZBias|(5:ZBias)] + + CGPROGRAM + ENDCG + } + } +} + +--------------------------------------------------------- +(0:Color): ReSharper Usage of element under cursor +(1:SrcBlend): ReSharper Usage of element under cursor +(2:ZBias): ReSharper Usage of element under cursor +(3:SrcBlend): ReSharper Usage of element under cursor +(4:ZBias): ReSharper Usage of element under cursor +(5:ZBias): ReSharper Usage of element under cursor diff --git a/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage02.shader b/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage02.shader new file mode 100644 index 0000000000..b153393b5d --- /dev/null +++ b/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage02.shader @@ -0,0 +1,29 @@ +Shader "Foo" +{ + Properties + { + _Color ("Color", Color) = (1,1,1,1) + _SrcBlend ("SrcBlend", Int) = 5.0 + _DstBlend ("DstBlend", Int) = 10.0 + _ZWrite ("ZWrite", Int) = 1.0 + _ZTest ("ZTest", Int) = 4.0 + _Cull ("Cull", Int) = 0.0 + _ZBias ("ZBias", Float) = 0.0 + } + + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Pass + { + Blend [_Sr{caret:SrcBlend}cBlend] [_DstBlend] + ZWrite [_ZWrite] + ZTest [_ZTe{caret:ZTest}st] + Cull [_Cull] + Offset [_ZBias], [_ZBi{caret:ZBias}as] + + CGPROGRAM + ENDCG + } + } +} diff --git a/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage02.shader.gold b/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage02.shader.gold new file mode 100644 index 0000000000..984e5bdf43 --- /dev/null +++ b/resharper/test/data/ShaderLab/ContextHighlighters/PropertyUsage/PropertyUsage02.shader.gold @@ -0,0 +1,38 @@ +Shader "Foo" +{ + Properties + { + _Color ("Color", Color) = (1,1,1,1) + |_SrcBlend|(0:SrcBlend) ("SrcBlend", Int) = 5.0 + _DstBlend ("DstBlend", Int) = 10.0 + _ZWrite ("ZWrite", Int) = 1.0 + |_ZTest|(1:ZTest) ("ZTest", Int) = 4.0 + _Cull ("Cull", Int) = 0.0 + |_ZBias|(2:ZBias) ("ZBias", Float) = 0.0 + } + + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Pass + { + Blend [|_SrcBlend|(3:SrcBlend)] [_DstBlend] + ZWrite [_ZWrite] + ZTest [|_ZTest|(4:ZTest)] + Cull [_Cull] + Offset [|_ZBias|(5:ZBias)], [|_ZBias|(6:ZBias)] + + CGPROGRAM + ENDCG + } + } +} + +--------------------------------------------------------- +(0:SrcBlend): ReSharper Usage of element under cursor +(1:ZTest): ReSharper Usage of element under cursor +(2:ZBias): ReSharper Usage of element under cursor +(3:SrcBlend): ReSharper Usage of element under cursor +(4:ZTest): ReSharper Usage of element under cursor +(5:ZBias): ReSharper Usage of element under cursor +(6:ZBias): ReSharper Usage of element under cursor diff --git a/resharper/test/src/ShaderLab/Daemon/ContextHighlighters/ShaderLabPropertyUsageContextHighlighterTest.cs b/resharper/test/src/ShaderLab/Daemon/ContextHighlighters/ShaderLabPropertyUsageContextHighlighterTest.cs new file mode 100644 index 0000000000..301d26eb5a --- /dev/null +++ b/resharper/test/src/ShaderLab/Daemon/ContextHighlighters/ShaderLabPropertyUsageContextHighlighterTest.cs @@ -0,0 +1,17 @@ +using JetBrains.ReSharper.FeaturesTestFramework.ContextHighlighters; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.ProjectModel; +using JetBrains.ReSharper.TestFramework; +using NUnit.Framework; + +namespace JetBrains.ReSharper.Plugins.Unity.Tests.ShaderLab.Daemon.ContextHighlighters +{ + [TestFileExtension(ShaderLabProjectFileType.SHADERLAB_EXTENSION)] + public class ShaderLabPropertyUsageContextHighlighterTest : ContextHighlighterTestBase + { + protected override string RelativeTestDataPath => @"ShaderLab\" + base.RelativeTestDataPath; + protected override string ExtraPath => @"PropertyUsage"; + + [Test] public void TestPropertyUsage01() { DoNamedTest2(); } + [Test] public void TestPropertyUsage02() { DoNamedTest2(); } + } +} \ No newline at end of file From 1ba982c7458f6cdd718cdff30d075e0909d1028d Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 16 Feb 2018 08:51:51 +0000 Subject: [PATCH 11/13] Add tests for ShaderLab property resolve --- .../PropertyDeclaredElement.cs | 21 ++++++++++ .../ShaderLabDeclaredElementBase.cs | 7 ++-- .../Psi/Resolve/VariableReference01.shader | 29 ++++++++++++++ .../Resolve/VariableReference01.shader.gold | 38 +++++++++++++++++++ .../Psi/Resolve/ShaderLabResolveTests.cs | 16 ++++++++ 5 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 resharper/test/data/ShaderLab/Psi/Resolve/VariableReference01.shader create mode 100644 resharper/test/data/ShaderLab/Psi/Resolve/VariableReference01.shader.gold create mode 100644 resharper/test/src/ShaderLab/Psi/Resolve/ShaderLabResolveTests.cs diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs index 9d8f39e2a2..e858ce0ab0 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/PropertyDeclaredElement.cs @@ -27,5 +27,26 @@ public string GetPropertyType() return declaration.PropertyType?.GetText() ?? string.Empty; return string.Empty; } + + protected bool Equals(PropertyDeclaredElement other) + { + return string.Equals(ShortName, other.ShortName) && TreeOffset == other.TreeOffset; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((PropertyDeclaredElement) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (ShortName.GetHashCode() * 397) ^ TreeOffset; + } + } } } \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs index d05a8f429d..e78afbe75f 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementBase.cs @@ -12,15 +12,16 @@ namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements public abstract class ShaderLabDeclaredElementBase : IShaderLabDeclaredElement { private readonly IPsiSourceFile mySourceFile; - private readonly int myTreeOffset; protected ShaderLabDeclaredElementBase(string shortName, IPsiSourceFile sourceFile, int treeOffset) { mySourceFile = sourceFile; - myTreeOffset = treeOffset; + TreeOffset = treeOffset; ShortName = shortName; } + protected int TreeOffset { get; } + public IPsiServices GetPsiServices() { return mySourceFile.GetPsiServices(); @@ -31,7 +32,7 @@ public IList GetDeclarations() if (!(mySourceFile.GetPrimaryPsiFile() is IShaderLabFile psi)) return EmptyList.InstanceList; - var node = psi.FindNodeAt(TreeTextRange.FromLength(new TreeOffset(myTreeOffset), 1)); + var node = psi.FindNodeAt(TreeTextRange.FromLength(new TreeOffset(TreeOffset), 1)); while (node != null && !(node is IDeclaration)) node = node.Parent; if (node == null) diff --git a/resharper/test/data/ShaderLab/Psi/Resolve/VariableReference01.shader b/resharper/test/data/ShaderLab/Psi/Resolve/VariableReference01.shader new file mode 100644 index 0000000000..f7b01ebc11 --- /dev/null +++ b/resharper/test/data/ShaderLab/Psi/Resolve/VariableReference01.shader @@ -0,0 +1,29 @@ +Shader "Foo" +{ + Properties + { + _Color ("Color", Color) = (1,1,1,1) + _SrcBlend ("SrcBlend", Int) = 5.0 + _DstBlend ("DstBlend", Int) = 10.0 + _ZWrite ("ZWrite", Int) = 1.0 + _ZTest ("ZTest", Int) = 4.0 + _Cull ("Cull", Int) = 0.0 + _ZBias ("ZBias", Float) = 0.0 + } + + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Pass + { + Blend [_SrcBlend] [_DstBlend] + ZWrite [_ZWrite] + ZTest [_ZTest] + Cull [_Cull] + Offset [_ZBias], [_ZBias] + + CGPROGRAM + ENDCG + } + } +} diff --git a/resharper/test/data/ShaderLab/Psi/Resolve/VariableReference01.shader.gold b/resharper/test/data/ShaderLab/Psi/Resolve/VariableReference01.shader.gold new file mode 100644 index 0000000000..d7bae417e2 --- /dev/null +++ b/resharper/test/data/ShaderLab/Psi/Resolve/VariableReference01.shader.gold @@ -0,0 +1,38 @@ +Shader "Foo" +{ + Properties + { + _Color ("Color", Color) = (1,1,1,1) + _SrcBlend ("SrcBlend", Int) = 5.0 + _DstBlend ("DstBlend", Int) = 10.0 + _ZWrite ("ZWrite", Int) = 1.0 + _ZTest ("ZTest", Int) = 4.0 + _Cull ("Cull", Int) = 0.0 + _ZBias ("ZBias", Float) = 0.0 + } + + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Pass + { + Blend [|_SrcBlend|(0)] [|_DstBlend|(1)] + ZWrite [|_ZWrite|(2)] + ZTest [|_ZTest|(3)] + Cull [|_Cull|(4)] + Offset [|_ZBias|(5)], [|_ZBias|(6)] + + CGPROGRAM + ENDCG + } + } +} + +------------------------------------------------ +0: result=OK declaredElem=Int _SrcBlend "SrcBlend" +1: result=OK declaredElem=Int _DstBlend "DstBlend" +2: result=OK declaredElem=Int _ZWrite "ZWrite" +3: result=OK declaredElem=Int _ZTest "ZTest" +4: result=OK declaredElem=Int _Cull "Cull" +5: result=OK declaredElem=Float _ZBias "ZBias" +6: result=OK declaredElem=Float _ZBias "ZBias" diff --git a/resharper/test/src/ShaderLab/Psi/Resolve/ShaderLabResolveTests.cs b/resharper/test/src/ShaderLab/Psi/Resolve/ShaderLabResolveTests.cs new file mode 100644 index 0000000000..174cf33f9f --- /dev/null +++ b/resharper/test/src/ShaderLab/Psi/Resolve/ShaderLabResolveTests.cs @@ -0,0 +1,16 @@ +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.ProjectModel; +using JetBrains.ReSharper.Psi.Resolve; +using JetBrains.ReSharper.TestFramework; +using NUnit.Framework; + +namespace JetBrains.ReSharper.Plugins.Unity.Tests.ShaderLab.Psi.Resolve +{ + [TestFileExtension(ShaderLabProjectFileType.SHADERLAB_EXTENSION)] + public class ShaderLabResolveTests : ReferenceTestBase + { + protected override string RelativeTestDataPath => @"ShaderLab\Psi\Resolve"; + protected override bool AcceptReference(IReference reference) => true; + + [Test] public void TestVariableReference01() { DoNamedTest2(); } + } +} From 9488435bc915ce47a06b97c9d473ec0d2095223d Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 16 Feb 2018 10:08:26 +0000 Subject: [PATCH 12/13] Add tests for multiple property candidates --- .../ShaderLab/Psi/Tree/Impl/ReferenceName.cs | 4 +- ...MultipleCandidatePropertyHighlights.shader | 30 +++++++++++++ ...pleCandidatePropertyHighlights.shader.gold | 42 +++++++++++++++++++ ...ipleCandidatesPropertyHighlightingTests.cs | 19 +++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 resharper/test/data/ShaderLab/Daemon/Stages/Analysis/MultipleCandidatePropertyHighlights.shader create mode 100644 resharper/test/data/ShaderLab/Daemon/Stages/Analysis/MultipleCandidatePropertyHighlights.shader.gold create mode 100644 resharper/test/src/ShaderLab/Daemon/Stages/Analysis/ShaderLabMultipleCandidatesPropertyHighlightingTests.cs diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs index dde5fc45c1..13ff61a9b6 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs @@ -52,9 +52,9 @@ public override ResolveResultWithInfo ResolveWithoutCache() if (myOwner.Identifier?.Name == null) return ResolveResultWithInfo.Unresolved; - if (file.Command.Value is IShaderValue shaderValue) + if (file.Command?.Value is IShaderValue shaderValue) { - if (shaderValue.PropertiesCommand.Value is IPropertiesValue propertiesValue) + if (shaderValue.PropertiesCommand?.Value is IPropertiesValue propertiesValue) { var name = myOwner.Identifier.Name; var declaredElements = new List(); diff --git a/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/MultipleCandidatePropertyHighlights.shader b/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/MultipleCandidatePropertyHighlights.shader new file mode 100644 index 0000000000..aa35eecaa4 --- /dev/null +++ b/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/MultipleCandidatePropertyHighlights.shader @@ -0,0 +1,30 @@ +Shader "Foo" +{ + Properties + { + _Color ("Color", Color) = (1,1,1,1) + _SrcBlend ("SrcBlend", Int) = 5.0 + _DstBlend ("DstBlend", Int) = 10.0 + _ZWrite ("ZWrite", Int) = 1.0 + _ZTest ("ZTest", Int) = 4.0 + _Cull ("Cull", Int) = 0.0 + _ZBias ("ZBias", Float) = 0.0 + _ZBias ("Duplicate ZBias property", Float) = 0.0 + } + + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Pass + { + Blend [_SrcBlend] [_DstBlend] + ZWrite [_ZWrite] + ZTest [_ZTest] + Cull [_Cull] + Offset [_ZBias], [_ZBias] + + CGPROGRAM + ENDCG + } + } +} diff --git a/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/MultipleCandidatePropertyHighlights.shader.gold b/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/MultipleCandidatePropertyHighlights.shader.gold new file mode 100644 index 0000000000..5d0077a028 --- /dev/null +++ b/resharper/test/data/ShaderLab/Daemon/Stages/Analysis/MultipleCandidatePropertyHighlights.shader.gold @@ -0,0 +1,42 @@ +Shader "Foo" +{ + Properties + { + _Color ("Color", Color) = (1,1,1,1) + _SrcBlend ("SrcBlend", Int) = 5.0 + _DstBlend ("DstBlend", Int) = 10.0 + _ZWrite ("ZWrite", Int) = 1.0 + _ZTest ("ZTest", Int) = 4.0 + _Cull ("Cull", Int) = 0.0 + |_ZBias|(0) ("ZBias", Float) = 0.0 + |_ZBias|(1) ("Duplicate ZBias property", Float) = 0.0 + } + + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Pass + { + Blend [_SrcBlend] [_DstBlend] + ZWrite [_ZWrite] + ZTest [_ZTest] + Cull [_Cull] + Offset [|_ZBias|(2)], [|_ZBias|(3)] + + CGPROGRAM + ENDCG + } + } +} + +--------------------------------------------------------- +(0): ReSharper Warning: Conflicting property '_ZBias' is defined below +(1): ReSharper Warning: There is already a property named '_ZBias' declared +(2): ReSharper Underlined Error Highlighting: Ambiguous reference: + Float _ZBias "Duplicate ZBias property" + Float _ZBias "ZBias" +match +(3): ReSharper Underlined Error Highlighting: Ambiguous reference: + Float _ZBias "Duplicate ZBias property" + Float _ZBias "ZBias" +match diff --git a/resharper/test/src/ShaderLab/Daemon/Stages/Analysis/ShaderLabMultipleCandidatesPropertyHighlightingTests.cs b/resharper/test/src/ShaderLab/Daemon/Stages/Analysis/ShaderLabMultipleCandidatesPropertyHighlightingTests.cs new file mode 100644 index 0000000000..c854d72dff --- /dev/null +++ b/resharper/test/src/ShaderLab/Daemon/Stages/Analysis/ShaderLabMultipleCandidatesPropertyHighlightingTests.cs @@ -0,0 +1,19 @@ +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Daemon.Errors; +using JetBrains.ReSharper.Psi; +using NUnit.Framework; + +namespace JetBrains.ReSharper.Plugins.Unity.Tests.ShaderLab.Daemon.Stages.Analysis +{ + public class ShaderLabMultipleCandidatesPropertyHighlightingTests : ShaderLabHighlightingTestBase + { + protected override string RelativeTestDataPath => @"ShaderLab\Daemon\Stages\Analysis"; + + protected override bool HighlightingPredicate(IHighlighting highlighting, IPsiSourceFile sourceFile) + { + return highlighting is ShaderLabHighlightingBase; + } + + [Test] public void TestMultipleCandidatePropertyHighlights() { DoNamedTest2(); } + } +} \ No newline at end of file From 8a91bfc7e43cdebaea394f5227053f5532df3bee Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 16 Feb 2018 15:53:41 +0000 Subject: [PATCH 13/13] Add code completion for variable references --- .../IntellisenseEnabledSettingShaderLab.cs | 12 ++++ .../ShaderLabAutopopupEnabledSettingsKey.cs | 12 ++++ .../Settings/ShaderLabIntellisenseManager.cs | 26 +++++++ .../ShaderLabCodeCompletionContext.cs | 22 ++++++ .../ShaderLabCodeCompletionContextProvider.cs | 71 +++++++++++++++++++ .../ShaderLabCompletionRangesProvider.cs | 16 +++++ .../ShaderLabReparsedCompletionContext.cs | 22 ++++++ ...bleReferenceAutomaticCompletionStrategy.cs | 54 ++++++++++++++ ...ShaderLabVariableReferenceItemsProvider.cs | 30 ++++++++ .../ShaderLabDeclaredElementType.cs | 1 - .../Resolve/IVariableReferenceReference.cs | 2 +- .../ShaderLab/Psi/Tree/Impl/ReferenceName.cs | 70 +++++++++++------- .../VariableReference/TestAction01.shader | 30 ++++++++ .../TestAction01.shader.gold | 30 ++++++++ .../VariableReference/TestList01.shader | 29 ++++++++ .../VariableReference/TestList01.shader.gold | 9 +++ ...aderLabVariableReferenceCompletionTests.cs | 28 ++++++++ 17 files changed, 437 insertions(+), 27 deletions(-) create mode 100644 resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/IntellisenseEnabledSettingShaderLab.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/ShaderLabAutopopupEnabledSettingsKey.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/ShaderLabIntellisenseManager.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCodeCompletionContext.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCodeCompletionContextProvider.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCompletionRangesProvider.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabReparsedCompletionContext.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceAutomaticCompletionStrategy.cs create mode 100644 resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceItemsProvider.cs create mode 100644 resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestAction01.shader create mode 100644 resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestAction01.shader.gold create mode 100644 resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestList01.shader create mode 100644 resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestList01.shader.gold create mode 100644 resharper/test/src/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceCompletionTests.cs diff --git a/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/IntellisenseEnabledSettingShaderLab.cs b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/IntellisenseEnabledSettingShaderLab.cs new file mode 100644 index 0000000000..ee9d4d7e89 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/IntellisenseEnabledSettingShaderLab.cs @@ -0,0 +1,12 @@ +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Settings; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Feature.Services.CodeCompletion.Settings +{ + [SettingsKey(typeof(IntellisenseEnabledSettingsKey), "Override VS IntelliSense for ShaderLab")] + public class IntellisenseEnabledSettingShaderLab + { + [SettingsEntry(false, "ShaderLab (Unity .shader files)")] + public bool IntellisenseEnabled; + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/ShaderLabAutopopupEnabledSettingsKey.cs b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/ShaderLabAutopopupEnabledSettingsKey.cs new file mode 100644 index 0000000000..988829e7eb --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/ShaderLabAutopopupEnabledSettingsKey.cs @@ -0,0 +1,12 @@ +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Settings; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Feature.Services.CodeCompletion.Settings +{ + [SettingsKey(typeof(AutopopupEnabledSettingsKey), "ShaderLab")] + public class ShaderLabAutopopupEnabledSettingsKey + { + [SettingsEntry(AutopopupType.HardAutopopup, "In variable references")] + public AutopopupType InVariableReferences; + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/ShaderLabIntellisenseManager.cs b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/ShaderLabIntellisenseManager.cs new file mode 100644 index 0000000000..51bdbea545 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/Settings/ShaderLabIntellisenseManager.cs @@ -0,0 +1,26 @@ +using JetBrains.Annotations; +using JetBrains.Application; +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Settings; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi; +using JetBrains.ReSharper.Psi; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Feature.Services.CodeCompletion.Settings +{ + [ShellComponent] + public class ShaderLabIntellisenseManager : LanguageSpecificIntellisenseManager + { + public ShaderLabIntellisenseManager([NotNull] ISettingsStore settingsStore) + : base(settingsStore) + { + } + + public override SettingsScalarEntry GetSettingsEntry() + { + return SettingsStore.Schema.GetScalarEntry((IntellisenseEnabledSettingShaderLab setting) => + setting.IntellisenseEnabled); + } + + public override PsiLanguageType PsiLanguage => ShaderLabLanguage.Instance; + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCodeCompletionContext.cs b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCodeCompletionContext.cs new file mode 100644 index 0000000000..0db32bc759 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCodeCompletionContext.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Feature.Services.CodeCompletion +{ + public class ShaderLabCodeCompletionContext : SpecificCodeCompletionContext + { + public ShaderLabCodeCompletionContext([NotNull] CodeCompletionContext context, + ShaderLabReparsedCompletionContext unterminatedContext, + TextLookupRanges ranges) + : base(context) + { + UnterminatedContext = unterminatedContext; + Ranges = ranges; + } + + public override string ContextId => "ShaderLabCodeCompletionContext"; + + public ShaderLabReparsedCompletionContext UnterminatedContext { get; } + public TextLookupRanges Ranges { get; } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCodeCompletionContextProvider.cs b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCodeCompletionContextProvider.cs new file mode 100644 index 0000000000..047883a214 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCodeCompletionContextProvider.cs @@ -0,0 +1,71 @@ +using JetBrains.ReSharper.Feature.Services.CodeCompletion; +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Impl; +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Feature.Services.CodeCompletion.Settings; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.Tree; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Feature.Services.CodeCompletion +{ + [IntellisensePart] + public class ShaderLabCodeCompletionContextProvider : CodeCompletionContextProviderBase + { + private readonly ShaderLabIntellisenseManager myShaderLabIntellisenseManager; + + public ShaderLabCodeCompletionContextProvider(ShaderLabIntellisenseManager shaderLabIntellisenseManager) + { + myShaderLabIntellisenseManager = shaderLabIntellisenseManager; + } + + public override bool IsApplicable(CodeCompletionContext context) => context.File is IShaderLabFile; + + public override ISpecificCodeCompletionContext GetCompletionContext(CodeCompletionContext context) + { + if (!(context.File is IShaderLabFile file)) return null; + + if (context.CodeCompletionType == CodeCompletionType.BasicCompletion + && !IsIntellisenseEnabled(context)) + { + return null; + } + + var unterminatedContext = new ShaderLabReparsedCompletionContext(file, context.SelectedTreeRange, "aa"); + unterminatedContext.Init(); + + var referenceToComplete = unterminatedContext.Reference; + var elementToComplete = unterminatedContext.TreeNode; + + if (elementToComplete == null) + return null; + + var referenceRange = referenceToComplete?.GetTreeTextRange() ?? GetElementRange(elementToComplete); + var referenceDocumentRange = unterminatedContext.ToDocumentRange(referenceRange); + + if (!referenceDocumentRange.IsValid()) + return null; + + if (!referenceDocumentRange.Contains(context.EffectiveCaretDocumentOffset)) + return null; + + var ranges = GetTextLookupRanges(context, referenceDocumentRange); + return new ShaderLabCodeCompletionContext(context, unterminatedContext, ranges); + } + + private bool IsIntellisenseEnabled(CodeCompletionContext context) + { + return myShaderLabIntellisenseManager.GetIntellisenseEnabled(context.ContextBoundSettingsStore); + } + + private TreeTextRange GetElementRange(ITreeNode element) + { + if (element is ITokenNode tokenNode) + { + var tokenNodeType = tokenNode.GetTokenType(); + if (tokenNodeType.IsIdentifier || tokenNodeType.IsKeyword) + return tokenNode.GetTreeTextRange(); + } + return new TreeTextRange(element.GetTreeTextRange().EndOffset); + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCompletionRangesProvider.cs b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCompletionRangesProvider.cs new file mode 100644 index 0000000000..5b62e36dc4 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabCompletionRangesProvider.cs @@ -0,0 +1,16 @@ +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi; +using JetBrains.ReSharper.Psi; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Feature.Services.CodeCompletion +{ + [Language(typeof(ShaderLabLanguage))] + public class ShaderLabCompletionRangesProvider : ItemsProviderOfSpecificContext, + ICompletionRangesProvider + { + protected override TextLookupRanges GetDefaultRanges(ShaderLabCodeCompletionContext context) + { + return context.Ranges; + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabReparsedCompletionContext.cs b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabReparsedCompletionContext.cs new file mode 100644 index 0000000000..042fb1ab0b --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabReparsedCompletionContext.cs @@ -0,0 +1,22 @@ +using JetBrains.ReSharper.Feature.Services.CodeCompletion; +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure; +using JetBrains.ReSharper.Feature.Services.Util; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.Tree; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Feature.Services.CodeCompletion +{ + public class ShaderLabReparsedCompletionContext : ReparsedCodeCompletionContext + { + public ShaderLabReparsedCompletionContext(IShaderLabFile file, TreeTextRange selectedTreeRange, string newText) + : base(file, selectedTreeRange, newText) + { + } + + protected override IReparseContext GetReparseContext(IFile file, TreeTextRange range) + { + return new TrivialReparseContext(file, range); + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceAutomaticCompletionStrategy.cs b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceAutomaticCompletionStrategy.cs new file mode 100644 index 0000000000..fc80c6b9eb --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceAutomaticCompletionStrategy.cs @@ -0,0 +1,54 @@ +using JetBrains.Application.Settings; +using JetBrains.ProjectModel; +using JetBrains.ReSharper.Feature.Services.CodeCompletion; +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Settings; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Feature.Services.CodeCompletion.Settings; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.Tree; +using JetBrains.TextControl; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Feature.Services.CodeCompletion +{ + [SolutionComponent] + public class ShaderLabVariableReferenceAutomaticCompletionStrategy : IAutomaticCodeCompletionStrategy + { + private readonly ShaderLabIntellisenseManager myShaderLabIntellisenseManager; + private readonly SettingsScalarEntry myScalarEntry; + + public ShaderLabVariableReferenceAutomaticCompletionStrategy(ShaderLabIntellisenseManager shaderLabIntellisenseManager, ISettingsStore settingsStore) + { + myShaderLabIntellisenseManager = shaderLabIntellisenseManager; + myScalarEntry = + settingsStore.Schema.GetScalarEntry((ShaderLabAutopopupEnabledSettingsKey key) => + key.InVariableReferences); + } + + public AutopopupType IsEnabledInSettings(IContextBoundSettingsStore settingsStore, ITextControl textControl) + { + return (AutopopupType) settingsStore.GetValue(myScalarEntry, null); + } + + public bool AcceptTyping(char c, ITextControl textControl, IContextBoundSettingsStore boundSettingsStore) + { + if (!myShaderLabIntellisenseManager.GetAutoppopupEnabled(boundSettingsStore)) + return false; + return c == '['; + } + + public bool ProcessSubsequentTyping(char c, ITextControl textControl) + { + // What does this mean? + return true; + } + + public bool AcceptsFile(IFile file, ITextControl textControl) + { + return file is IShaderLabFile; + } + + public PsiLanguageType Language => ShaderLabLanguage.Instance; + public bool ForceHideCompletion => false; + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceItemsProvider.cs b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceItemsProvider.cs new file mode 100644 index 0000000000..e10f1f4db4 --- /dev/null +++ b/resharper/src/resharper-unity/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceItemsProvider.cs @@ -0,0 +1,30 @@ +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Impl; +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Resolve; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.Resolve; + +namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Feature.Services.CodeCompletion +{ + [Language(typeof(ShaderLabLanguage))] + public class ShaderLabVariableReferenceItemsProvider : ItemsProviderWithSymbolTable + { + protected override TextLookupRanges EvaluateRanges(ShaderLabCodeCompletionContext context) + { + return context.Ranges; + } + + protected override IVariableReferenceReference GetReference(ShaderLabCodeCompletionContext context) + { + return context.UnterminatedContext.Reference as IVariableReferenceReference; + } + + protected override ISymbolTable GetCompletionSymbolTable(IVariableReferenceReference reference, ShaderLabCodeCompletionContext context) + { + return reference.GetCompletionSymbolTable(); + } + } +} \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs index f27ec1dfa6..6cf641f5b3 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/DeclaredElements/ShaderLabDeclaredElementType.cs @@ -6,7 +6,6 @@ namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements { public class ShaderLabDeclaredElementType : DeclaredElementType { - // TODO: Proper icon public static readonly ShaderLabDeclaredElementType Property = new ShaderLabDeclaredElementType("Property", PsiSymbolsThemedIcons.Property.Id); private readonly IconId myIconId; diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Resolve/IVariableReferenceReference.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Resolve/IVariableReferenceReference.cs index 8b1beb9620..3e9ac04673 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/Resolve/IVariableReferenceReference.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Resolve/IVariableReferenceReference.cs @@ -3,7 +3,7 @@ namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Resolve { // TODO: Terrible name... - public interface IVariableReferenceReference : IReference //, ICompletableReference + public interface IVariableReferenceReference : ICompletableReference { } } \ No newline at end of file diff --git a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs index 13ff61a9b6..9606728254 100644 --- a/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs +++ b/resharper/src/resharper-unity/ShaderLab/Psi/Tree/Impl/ReferenceName.cs @@ -8,6 +8,7 @@ using JetBrains.ReSharper.Psi.Resolve; using JetBrains.ReSharper.Psi.Tree; using JetBrains.ReSharper.Resources.Shell; +using JetBrains.Util; namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.Tree.Impl { @@ -46,32 +47,11 @@ public PropertyReference([NotNull] ReferenceName owner) public override ResolveResultWithInfo ResolveWithoutCache() { - if (!(myOwner.GetContainingFile() is IShaderLabFile file)) - return ResolveResultWithInfo.Unresolved; - - if (myOwner.Identifier?.Name == null) + var declaredElements = GetPropertyDeclaredElements(true); + if (declaredElements.Count == 0) return ResolveResultWithInfo.Unresolved; - if (file.Command?.Value is IShaderValue shaderValue) - { - if (shaderValue.PropertiesCommand?.Value is IPropertiesValue propertiesValue) - { - var name = myOwner.Identifier.Name; - var declaredElements = new List(); - foreach (var propertyDeclaration in propertiesValue.DeclarationsEnumerable) - { - var declarationName = propertyDeclaration?.Name?.GetText(); - - // Note that both ShaderLab and Cg are case sensitive - if (string.Equals(name, declarationName, StringComparison.InvariantCulture)) - declaredElements.Add(propertyDeclaration.DeclaredElement); - } - - return ResolveUtil.CreateResolveResult(declaredElements); - } - } - - return ResolveResultWithInfo.Unresolved; + return ResolveUtil.CreateResolveResult(declaredElements); } public override string GetName() @@ -81,7 +61,11 @@ public override string GetName() public override ISymbolTable GetReferenceSymbolTable(bool useReferenceName) { - return EmptySymbolTable.INSTANCE; + var declaredElements = GetPropertyDeclaredElements(useReferenceName); + if (declaredElements.Count == 0) + return EmptySymbolTable.INSTANCE; + + return ResolveUtil.CreateSymbolTable(declaredElements, 0); } public override TreeTextRange GetTreeTextRange() @@ -114,6 +98,42 @@ public override IAccessContext GetAccessContext() { return new DefaultAccessContext(myOwner); } + + public ISymbolTable GetCompletionSymbolTable() + { + return GetReferenceSymbolTable(false); + } + + private IList GetPropertyDeclaredElements(bool useReferenceName) + { + if (!(myOwner.GetContainingFile() is IShaderLabFile file)) + return EmptyList.InstanceList; + + var referenceName = myOwner.Identifier?.Name; + if (string.IsNullOrEmpty(referenceName)) + return EmptyList.InstanceList; + + var declaredElements = new List(); + if (file.Command?.Value is IShaderValue shaderValue) + { + if (shaderValue.PropertiesCommand?.Value is IPropertiesValue propertiesValue) + { + foreach (var propertyDeclaration in propertiesValue.DeclarationsEnumerable) + { + if (useReferenceName) + { + // Note that both ShaderLab and Cg are case sensitive + var declarationName = propertyDeclaration?.Name?.GetText(); + if (!string.Equals(referenceName, declarationName, StringComparison.InvariantCulture)) + continue; + } + declaredElements.Add(propertyDeclaration.DeclaredElement); + } + } + } + + return declaredElements; + } } } } \ No newline at end of file diff --git a/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestAction01.shader b/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestAction01.shader new file mode 100644 index 0000000000..85c1c7bd7a --- /dev/null +++ b/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestAction01.shader @@ -0,0 +1,30 @@ +// ${COMPLETE_ITEM:_SrcBlend} +Shader "Foo" +{ + Properties + { + _Color ("Color", Color) = (1,1,1,1) + _SrcBlend ("SrcBlend", Int) = 5.0 + _DstBlend ("DstBlend", Int) = 10.0 + _ZWrite ("ZWrite", Int) = 1.0 + _ZTest ("ZTest", Int) = 4.0 + _Cull ("Cull", Int) = 0.0 + _ZBias ("ZBias", Float) = 0.0 + } + + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Pass + { + Blend [{caret}] + ZWrite [_ZWrite] + ZTest [_ZTest] + Cull [_Cull] + Offset [_ZBias], [_ZBias] + + CGPROGRAM + ENDCG + } + } +} diff --git a/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestAction01.shader.gold b/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestAction01.shader.gold new file mode 100644 index 0000000000..54621bb994 --- /dev/null +++ b/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestAction01.shader.gold @@ -0,0 +1,30 @@ +// ${COMPLETE_ITEM:_SrcBlend} +Shader "Foo" +{ + Properties + { + _Color ("Color", Color) = (1,1,1,1) + _SrcBlend ("SrcBlend", Int) = 5.0 + _DstBlend ("DstBlend", Int) = 10.0 + _ZWrite ("ZWrite", Int) = 1.0 + _ZTest ("ZTest", Int) = 4.0 + _Cull ("Cull", Int) = 0.0 + _ZBias ("ZBias", Float) = 0.0 + } + + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Pass + { + Blend [_SrcBlend{caret}] + ZWrite [_ZWrite] + ZTest [_ZTest] + Cull [_Cull] + Offset [_ZBias], [_ZBias] + + CGPROGRAM + ENDCG + } + } +} diff --git a/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestList01.shader b/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestList01.shader new file mode 100644 index 0000000000..f2c51f9785 --- /dev/null +++ b/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestList01.shader @@ -0,0 +1,29 @@ +Shader "Foo" +{ + Properties + { + _Color ("Color", Color) = (1,1,1,1) + _SrcBlend ("SrcBlend", Int) = 5.0 + _DstBlend ("DstBlend", Int) = 10.0 + _ZWrite ("ZWrite", Int) = 1.0 + _ZTest ("ZTest", Int) = 4.0 + _Cull ("Cull", Int) = 0.0 + _ZBias ("ZBias", Float) = 0.0 + } + + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Pass + { + Blend [{caret}] + ZWrite [_ZWrite] + ZTest [_ZTest] + Cull [_Cull] + Offset [_ZBias], [_ZBias] + + CGPROGRAM + ENDCG + } + } +} diff --git a/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestList01.shader.gold b/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestList01.shader.gold new file mode 100644 index 0000000000..53a450dd34 --- /dev/null +++ b/resharper/test/data/ShaderLab/CodeCompletion/VariableReference/TestList01.shader.gold @@ -0,0 +1,9 @@ +# 7 ITEMS # + ++ _Color ++ _Cull ++ _DstBlend ++ _SrcBlend ++ _ZBias ++ _ZTest ++ _ZWrite diff --git a/resharper/test/src/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceCompletionTests.cs b/resharper/test/src/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceCompletionTests.cs new file mode 100644 index 0000000000..fbbab90764 --- /dev/null +++ b/resharper/test/src/ShaderLab/Feature/Services/CodeCompletion/ShaderLabVariableReferenceCompletionTests.cs @@ -0,0 +1,28 @@ +using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure.LookupItems; +using JetBrains.ReSharper.FeaturesTestFramework.Completion; +using JetBrains.ReSharper.Plugins.Unity.ShaderLab.ProjectModel; +using JetBrains.ReSharper.TestFramework; +using NUnit.Framework; + +namespace JetBrains.ReSharper.Plugins.Unity.Tests.ShaderLab.Feature.Services.CodeCompletion +{ + [TestFileExtension(ShaderLabProjectFileType.SHADERLAB_EXTENSION)] + public class ShaderLabVariableReferenceCompletionListTests : CodeCompletionTestBase + { + protected override CodeCompletionTestType TestType => CodeCompletionTestType.List; + protected override string RelativeTestDataPath => @"ShaderLab\CodeCompletion\VariableReference"; + + [Test] public void TestList01() { DoNamedTest(); } + } + + [TestFileExtension(ShaderLabProjectFileType.SHADERLAB_EXTENSION)] + public class ShaderLabVariableReferenceCompletionActionTests : CodeCompletionTestBase + { + protected override CodeCompletionTestType TestType => CodeCompletionTestType.Action; + protected override string RelativeTestDataPath => @"ShaderLab\CodeCompletion\VariableReference"; + protected override bool CheckAutomaticCompletionDefault() => true; + protected override LookupListSorting Sorting => LookupListSorting.ByRelevance; + + [Test] public void TestAction01() { DoNamedTest(); } + } +} \ No newline at end of file