I’m trying to filter the CodeCompletion results so that only public properties are exposed via auto completion. I found that I can filter properties via the ListMember.Category.Id, but there is no way to determine if a property is static or not.
Could you please provide a bit more details here? What parser are you using and sample of code where you need to filter out static (or non-static properties)?
On our tests (tested with Roslyn C# parser), code completion will not mix static and instance properties:
public class Person
{
public string Name { get; set; }
public static int MyProp { get; set; }
}
public static void Main()
{
Person person = new Person();
person. - will show only Name;
Person. - will show only MyProp
}
I see that you’re correct, in my application those properties that I thought were static were not. It appears I need a way to filter out list members that have the System.ComponentModel.BrowsableAttribute(false). I don’t see anyway to access the attributes associated with the properties of the object exposed as globals in my script environment.
If there is a way to access those attributes or edit the syntax tree to filter them out that would be great.
It does not seem to be possible to get additional attribute information associated with the code completion item - you can read a bit more about it here:
However you can execute additional API to get recommended symbols at the position and use this information to filter out code completion items which have attribute Browsable(false).
Below is sample code showing how to do that:
private bool IsBrowsable(string name, IEnumerable<Microsoft.CodeAnalysis.ISymbol> symbols)
{
foreach (var symbol in symbols) // use dictionary to make it faster
{
if (symbol.Name == name)
{
var attributes = symbol.GetAttributes();
if (attributes != null)
{
foreach (var attribute in attributes)
{
if (attribute.ToString().Contains("Browsable(false)") || attribute.ToString().Contains("BrowsableAttribute(false)"))
return false;
}
}
}
}
return true;
}
private void SyntaxEdit1_NeedCodeCompletion(object sender, Alternet.Syntax.CodeCompletionArgs e)
{
var members = e.Provider as Alternet.Syntax.CodeCompletion.IListMembers;
if (members != null)
{
var repository = csParser1.Repository;
var model = repository.Model;
var text = repository.Text;
var workspace = repository.Solution?.Workspace;
IEnumerable<Microsoft.CodeAnalysis.ISymbol> symbols = null;
if (text != null && model != null && workspace != null)
{
int pos = csParser1.Repository.GetPosFromPosition(text, e.StartPosition);
if (pos >= 0)
symbols = Microsoft.CodeAnalysis.Recommendations.Recommender.GetRecommendedSymbolsAtPosition(model, pos, workspace);
}
if (symbols != null)
{
for (int i = members.Count - 1; i >= 0; i--)
{
var member = members[i];
if (!IsBrowsable(member.Name, symbols))
{
members.RemoveAt(i);
}
}
}
}
}
For anyone that might want to see what my final version looks like:
` var members = e.Provider as IListMembers;
var repository = _parser.Repository;
var model = repository.Model;
var text = repository.Text;
var workspace = repository.Solution?.Workspace;
var symbols = new HashSet<string>();
if (text != null && model != null && workspace != null)
{
int pos = _parser.Repository.GetPosFromPosition(text, e.StartPosition);
if (pos >= 0)
{
symbols = Microsoft.CodeAnalysis.Recommendations.Recommender.GetRecommendedSymbolsAtPosition(model, pos, workspace)
.Where(s=>s.Kind == Microsoft.CodeAnalysis.SymbolKind.Property)
.Where(s => s.ContainingNamespace.ToString() == typeof(LogicalData).Namespace)
.Where(s => !s.GetAttributes()
.Select(a=>a.ToString())
.Any(an =>an.Contains("Browsable(false)") || an.Contains("BrowsableAttribute(false)")))
.Select(s=>s.Name)
.ToHashSet();
}
}
for (int i = members.Count - 1; i >= 0; i--)
{
if (!symbols.Contains(members[i].Name))
{
members.RemoveAt(i);
}
}`