Code Monkey home page Code Monkey logo

Comments (5)

ToddGrun avatar ToddGrun commented on June 16, 2024

Rion, this is Todd from the VS webtools team (I'm not on twitter). Is the exception due to something the VS webtooling code is providing? I took a quick look at the code and it looked like it wasn't.

from glyphfriend.

rionmonster avatar rionmonster commented on June 16, 2024

Hi @ToddGrun,

Thanks for reaching out. So it looks like the issue is stemming from how some of the Glyphs are being served to the CompletionHandler, which is probably a pattern that needs to be addressed (but I'm not entirely sure the best way to do it in the 2019 world).

The flow of the application goes as follows:

  1. Prior to the extension being built, all of the supported glyphs (~6-7k of them) are serialized into a .bin file with all of the libraries they correspond to, image data, and the text that appears during autocompletion.
  2. When the extension starts up, this .bin file is read and deserialized into a collection that the extension uses to determine which glyphs to serve.

I think a big part of this problem is that process in earlier version of the extension used to be synchronous:

public sealed class VSPackage : AsyncPackage
{
        protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
        {
            await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

            await Logger.InitializeAsync(this, "Glyphfriend");
            // This is where the glyphs are being loaded and referenced from
            await GlyphfriendPreferences.InitializeAsync();
            await ToggleLibraryCommand.InitializeAsync(this);
        }
}

The GlyphfriendPreferences class is initialized, during which the .bin file is deserialized into the collection:

public static class GlyphfriendPreferences
    {
        // The primary glyphs collection that gets loaded from the .bin file
        public static List<Glyph> Glyphs { get; private set; }

        public static async System.Threading.Tasks.Task InitializeAsync()
        {
            // Omitted for brevity
            Glyphs = LoadSupportedGlyphs();
            // Omitted for brevity
        }

        private static List<Glyph> LoadSupportedGlyphs()
        {
            var binaryPath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "glyphs.bin");
            using (var fs = File.Open(binaryPath, FileMode.Open))
            {
                var glyphs = Serializer.Deserialize<List<Glyph>>(fs);
                glyphs.ForEach(g => g.GenerateImage());

                Logger.Log($"{glyphs.Count} glyphs found.");
                return glyphs;
            }
        }
}

And finally the Completion Provider will read these (directly from this class, which may be an issue) as the user starts typing:

[HtmlCompletionProvider(CompletionTypes.Values, "*", "class")]
[ContentType("htmlx")]
internal class GlyphCompletionListProvider : BaseHtmlCompletionListProvider
{
        public override string CompletionType { get { return CompletionTypes.Values; } }

        public override IList<HtmlCompletion> GetEntries(HtmlCompletionContext context)
        {
            var glyphCompletionItems = new List<HtmlCompletion>();

            // Get the filtered set of enabled glyphs (directly from the preferences class)
            var enabledGlyphs = Preferences.Glyphs.Where(g => g.Enabled);
            foreach (var glyph in enabledGlyphs)
            {
                glyphCompletionItems.Add(CreateItem(glyph.Name, glyph.Image, context.Session));
            }

            return glyphCompletionItems;
        }
}

It may be possible that this is a threading (UI vs Main) issue or the fact that there's a race-condition type issue where the autocompletion is engaging prior to the .bin file being properly serialized.

Is there a better way to do this? I'm almost certain that it's an issue with the serialization/loading not being done prior to being accessed.

from glyphfriend.

ToddGrun avatar ToddGrun commented on June 16, 2024

Depends on the experience desired, I guess.

If you are content to not show the glyphs if deserialization isn't yet completed, then a simple null check on Preferences.Glyphs is probably sufficient as it's populated via an assignment from a local.

If you wish to have your provider block until deserialization is completed, then JTF.Run is probably appropriate (and you'll probably want to make GlyphfriendPreferences.Glyphs return a Task<List>)

from glyphfriend.

rionmonster avatar rionmonster commented on June 16, 2024

Thanks Todd,

I'll give those a shot. Everything seemed to work as expected on a few versions back but once I updated Visual Studio to the latest version, this started to come up. I do suspect that this is part/all of the issue (as some stack traces that I had seen in the past mentioned access to the glyph from another thread).

from glyphfriend.

rionmonster avatar rionmonster commented on June 16, 2024

It looks like this recent fix addressed the issue that a few users had reported. I was able to reproduce it and confirm that the latest release fixes the problem.

Thanks @ToddGrun for your suggestions and help, I really appreciate it!

from glyphfriend.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.