Skip to content

Commit

Permalink
Move DefTags into a SimpleICache (#7)
Browse files Browse the repository at this point in the history
Move DefTag detection/caching to RimworldXmlCache which extends from SimpleICache
  • Loading branch information
Garethp authored Apr 28, 2023
1 parent 072734b commit 08987a9
Show file tree
Hide file tree
Showing 15 changed files with 200 additions and 72 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 2023.1.1
* Taking some advice from the Jetbrains team, I've pushed the XML Def detection/storage into a `SimpleICache`, massively improving performance

## 2023.1
* The first release of this plugin.
* On top of the features from the Alphas, it also includes automatically detecting and using Rimworlds `Assembly-CSharp.dll` if it's not already part of your project
Expand Down
10 changes: 0 additions & 10 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,6 @@ rdgen {
}
}

patchPluginXml {
// TODO: See also org.jetbrains.changelog: https://github.com/JetBrains/gradle-changelog-plugin
def changelogText = file("${rootDir}/CHANGELOG.md").text
def changelogMatches = changelogText =~ /(?s)(-.+?)(?=##|$)/

changeNotes = changelogMatches.collect {
it[1].replaceAll(/(?s)\r?\n/, "<br />\n")
}.take(1).join('')
}

prepareSandbox {
dependsOn compileDotNet

Expand Down
2 changes: 1 addition & 1 deletion buildPlugin.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Param(
$Version = "2023.1.0"
$Version = "2023.1.1"
)

Set-StrictMode -Version Latest
Expand Down
7 changes: 7 additions & 0 deletions global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"sdk": {
"version": "7.0.202",
"rollForward": "latestMajor",
"allowPrerelease": true
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
DotnetPluginId=ReSharperPlugin.RimworldDev
DotnetSolution=ReSharperPlugin.RimworldDev.sln
RiderPluginId=com.jetbrains.rider.plugins.rimworlddev
PluginVersion=2023.1.0
PluginVersion=2023.1.1

BuildConfiguration=Release

Expand Down
Binary file added gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
6 changes: 6 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://cache-redirector.jetbrains.com/services.gradle.org/distributions/gradle-7.3-all.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JetBrains.ReSharper.SDK" Version="2022.2.4" PrivateAssets="all" />
<PackageReference Include="JetBrains.ReSharper.SDK" Version="2023.1.1" PrivateAssets="all" />
<PackageReference Include="Wave" Version="$(WaveVersion)" />
<!-- TODO: https://github.com/NuGet/Home/issues/7154 -->
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
using System.Linq;
using JetBrains.DataFlow;
using JetBrains.Lifetimes;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Caches;
using JetBrains.ReSharper.Psi.Modules;
using JetBrains.ReSharper.Psi.Resolve;
using JetBrains.ReSharper.Psi.Tree;
using JetBrains.ReSharper.Psi.Util;
using JetBrains.ReSharper.Psi.Xml;
using JetBrains.ReSharper.Psi.Xml.Impl.Tree;
using JetBrains.ReSharper.Psi.Xml.Tree;
using ReSharperPlugin.RimworldDev.SymbolScope;

namespace ReSharperPlugin.RimworldDev.TypeDeclaration;

Expand Down Expand Up @@ -91,12 +92,12 @@ private ReferenceCollection GetReferencesForText(ITreeNode element, ReferenceCol
!classContext.GetAllSuperTypes().Any(superType => superType.GetClrName().FullName == "Verse.Def"))
return new ReferenceCollection();

var tagId = $"{classContext.ShortName}/{element.GetText()}";
if (!RimworldXMLDefUtil.DefTags.ContainsKey(tagId)) return new ReferenceCollection();

var tag = RimworldXMLDefUtil.DefTags[tagId];

var xmlSymbolTable = element.GetSolution().GetComponent<RimworldSymbolScope>();

var tagId = $"{classContext.ShortName}/{element.GetText()}";
if (xmlSymbolTable.GetTagByDef(classContext.ShortName, element.GetText()) is not { } tag)
return new ReferenceCollection();

return new ReferenceCollection(new RimworldXmlDefReference(element,
tag.GetNestedTags<IXmlTag>("defName").FirstOrDefault() ?? tag, tagId));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,6 @@ public override ISpecificCodeCompletionContext GetCompletionContext(CodeCompleti
if (treeNode == null)
return (ISpecificCodeCompletionContext) null;
TreeTextRange treeRange = reference == null ? XmlCodeCompletionContextProvider.GetElementRange(treeNode) : reference.GetTreeTextRange();

if (1 == 1)
{
RimworldXMLDefUtil.UpdateDefs(xmlFile.GetSolution());
}

DocumentRange documentRange = unterminatedContext.ToDocumentRange(treeRange);
if (!documentRange.IsValid())
Expand Down
42 changes: 0 additions & 42 deletions src/dotnet/ReSharperPlugin.RimworldDev/RimworldXMLDefUtil.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using JetBrains.Application.Progress;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure;
using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure.LookupItems;
using JetBrains.ReSharper.Feature.Services.CodeCompletion.Infrastructure.LookupItems.Impl;
using JetBrains.ReSharper.Feature.Services.Navigation.Requests;
using JetBrains.ReSharper.Feature.Services.Occurrences;
using JetBrains.ReSharper.Features.Intellisense.CodeCompletion.CSharp;
Expand All @@ -20,7 +19,7 @@
using JetBrains.ReSharper.Psi.VB.Util;
using JetBrains.ReSharper.Psi.Xml;
using JetBrains.ReSharper.Psi.Xml.Impl.Tree;
using JetBrains.Util;
using ReSharperPlugin.RimworldDev.SymbolScope;
using ReSharperPlugin.RimworldDev.TypeDeclaration;

namespace ReSharperPlugin.RimworldDev;
Expand Down Expand Up @@ -179,13 +178,15 @@ protected void AddTextLookupItems(RimworldXmlCodeCompletionContext context, IIte

var className = classContext.ShortName;

var keys = RimworldXMLDefUtil.DefTags.Keys
var xmlSymbolTable = context.TreeNode!.GetSolution().GetSolution().GetComponent<RimworldSymbolScope>();

var keys = xmlSymbolTable.DefTags.Keys
.Where(key => key.StartsWith($"{className}/"))
.Select(key => key.Substring(className.Length + 1));

foreach (var key in keys)
{
var item = RimworldXMLDefUtil.DefTags[$"{className}/{key}"];
var item = xmlSymbolTable.GetTagByDef(className, key);

var lookup = LookupFactory.CreateDeclaredElementLookupItem(context, key,
new DeclaredElementInstance(new XMLTagDeclaredElement(item, key, false)));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains;
using JetBrains.Annotations;
using JetBrains.Application.Threading;
using JetBrains.Collections;
using JetBrains.Lifetimes;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Caches;
using JetBrains.ReSharper.Psi.Files;
using JetBrains.ReSharper.Psi.Xml.Tree;

namespace ReSharperPlugin.RimworldDev.SymbolScope;

[PsiComponent]
public class RimworldSymbolScope : SimpleICache<List<RimworldXmlDefSymbol>>
{
public Dictionary<string, IXmlTag> DefTags = new();

public RimworldSymbolScope
(Lifetime lifetime, [NotNull] IShellLocks locks, [NotNull] IPersistentIndexManager persistentIndexManager, long? version = null)
: base(lifetime, locks, persistentIndexManager, RimworldXmlDefSymbol.Marshaller, version)
{
}

protected override bool IsApplicable(IPsiSourceFile sourceFile)
{
return base.IsApplicable(sourceFile) && sourceFile.LanguageType.Name == "XML";
}

[CanBeNull]
public IXmlTag GetTagByDef(string defType, string defName)
{
return GetTagByDef($"{defType}/{defName}");
}

[CanBeNull]
public IXmlTag GetTagByDef(string defId)
{
if (!DefTags.ContainsKey(defId))
return null;

return DefTags[defId];
}

public override object Build(IPsiSourceFile sourceFile, bool isStartup)
{
if (!IsApplicable(sourceFile))
return null;

if (sourceFile.GetPrimaryPsiFile() is not IXmlFile xmlFile) return null;

var tags = xmlFile.GetNestedTags<IXmlTag>("Defs/*").Where(tag =>
{
var defNameTag = tag.GetNestedTags<IXmlTag>("defName").FirstOrDefault();
return defNameTag is not null;
});

List<RimworldXmlDefSymbol> defs = new();

foreach (var tag in tags)
{
var defName = tag.GetNestedTags<IXmlTag>("defName").FirstOrDefault()?.InnerText;
if (defName is null) continue;

defs.Add(new RimworldXmlDefSymbol(tag, defName, tag.GetTagName()));
}

return defs;
}

public override void Merge(IPsiSourceFile sourceFile, object builtPart)
{
RemoveFromLocalCache(sourceFile);
AddToLocalCache(sourceFile, builtPart as List<RimworldXmlDefSymbol>);
base.Merge(sourceFile, builtPart);
}

public override void MergeLoaded(object data)
{
PopulateLocalCache();
base.MergeLoaded(data);
}

public override void Drop(IPsiSourceFile sourceFile)
{
RemoveFromLocalCache(sourceFile);
base.Drop(sourceFile);
}

private void AddToLocalCache(IPsiSourceFile sourceFile, [CanBeNull] List<RimworldXmlDefSymbol> cacheItem)
{
if (sourceFile.GetPrimaryPsiFile() is not IXmlFile xmlFile) return;

cacheItem?.ForEach(item =>
{
if (!DefTags.ContainsKey($"{item.DefType}/{item.DefName}"))
DefTags.Add($"{item.DefType}/{item.DefName}", xmlFile.GetNestedTags<IXmlTag>("Defs/*").FirstOrDefault(tag => tag.GetTreeStartOffset().Offset == item.DocumentOffset));
});
}

private void RemoveFromLocalCache(IPsiSourceFile sourceFile)
{
var items = Map!.GetValueSafe(sourceFile);

items?.ForEach(item =>
{
if (!DefTags.ContainsKey($"{item.DefType}/{item.DefName}"))
DefTags.Remove($"{item.DefType}/{item.DefName}");
});
}

private void PopulateLocalCache()
{
foreach (var (sourceFile, cacheItem) in Map)
AddToLocalCache(sourceFile, cacheItem);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Collections.Generic;
using JetBrains.ReSharper.Psi.Xml.Tree;
using JetBrains.Serialization;
using JetBrains.Util.PersistentMap;

namespace ReSharperPlugin.RimworldDev.SymbolScope;

public class RimworldXmlDefSymbol
{
public static readonly IUnsafeMarshaller<List<RimworldXmlDefSymbol>> Marshaller =
UnsafeMarshallers.GetCollectionMarshaller(new UniversalMarshaller<RimworldXmlDefSymbol>(Read, Write), (size) => new List<RimworldXmlDefSymbol>());

public string DefName { get; }
public string DefType { get; }

public int DocumentOffset { get; }

// public IXmlTag Tag { get; }

public RimworldXmlDefSymbol(IXmlTag tag, string defName, string defType)
{
DefName = defName;
DefType = defType;
DocumentOffset = tag.GetTreeStartOffset().Offset;
}

public RimworldXmlDefSymbol(int documentOffset, string defName, string defType)
{
DefName = defName;
DefType = defType;
DocumentOffset = documentOffset;
}

private static RimworldXmlDefSymbol Read(UnsafeReader reader)
{
var defType = reader.ReadString();
var defName = reader.ReadString();
var documentOffset = reader.ReadInt();

return new RimworldXmlDefSymbol(documentOffset, defName, defType);
}

private static void Write(UnsafeWriter writer, RimworldXmlDefSymbol value)
{
writer.Write(value.DefType);
writer.Write(value.DefName);
writer.Write(value.DocumentOffset);
}
}
2 changes: 1 addition & 1 deletion src/rider/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ in your mods!</p>

<change-notes>
<![CDATA[
<p>First release, first set of features</p>
<p>Massive performance update that stems from better caching of XML Defs</p>
]]>
</change-notes>

Expand Down

0 comments on commit 08987a9

Please sign in to comment.