Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Find usages and completion for ShaderLab properties #362

Merged
merged 13 commits into from
Feb 16, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,16 @@
<Range>DocumentRange</Range>
<Behavour attributeID="ERROR" overlapResolvePolicy="ERROR"/>
</Error>


<Error name="NotResolved" staticGroup="ShaderLabErrors">
<Parameter type="IReference" name="reference"/>
<Message value="Cannot resolve symbol '{0}'">
<Argument>Reference.GetName()</Argument>
</Message>
<Range>Reference.GetDocumentRange()</Range>
<Behavour attributeID="UNRESOLVED_ERROR" overlapResolvePolicy="UNRESOLVED_ERROR"/>
</Error>

<Error name="ShaderLabPreprocessorDirective" staticGroup="ShaderLabErrors">
<Parameter type="IPpErrorDirective" name="directiveNode" />
<Parameter type="string" name="text" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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)
{
Expand All @@ -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!)
Expand All @@ -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);
}
}
}
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ protected override Action<ITextControl> 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);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using JetBrains.ReSharper.Psi;

namespace JetBrains.ReSharper.Plugins.Unity.ShaderLab.Psi.DeclaredElements
{
public interface IShaderLabDeclaredElement : IDeclaredElement
{
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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<IDeclaration> GetDeclarations()
{
if (!(mySourceFile.GetPrimaryPsiFile() is IShaderLabFile psi))
return EmptyList<IDeclaration>.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<IDeclaration>.Instance;

return new[] {(IDeclaration) node};
}

public IList<IDeclaration> GetDeclarationsIn(IPsiSourceFile sourceFile)
{
if (mySourceFile == sourceFile)
return GetDeclarations();
return EmptyList<IDeclaration>.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<IPsiSourceFile> GetSourceFiles()
{
return new HybridCollection<IPsiSourceFile>(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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want some unity-specific icon here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. I'll add a request

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<ShaderLabLanguage>();
protected override IDeclaredElementPresenter DefaultPresenter =>
ShaderLabLanguage.Instance.DeclaredElementPresenter();
}
}
Loading