Git Product home page Git Product logo

typescript-addin's People

Contributors

chrisber avatar mrward avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

typescript-addin's Issues

fastJSON

Hi Matt,

Take a look at fastJSON as a really fast (2x) and smaller (36kb) replacement for Json.net.
[https://github.com/mgholam/fastJSON]

Cheers,
Mehdi

Installation completed with warnings

When installing from the Alpha channel via Add-in Manager, a warning shows up once the installation is complete.

xamarin-studio-addin-warning

Using Xamarin Studio 5.10.1 (build 6) on OSX.

Parser fileAdd() and fileUpdate calls.

Observer behavior of the parser is that on every character change it
tries to add the current file AddFile() to the host environment also it then tries
to add all files in the project to the host env. AddFiles().
To gain more performance we should move the file add process elsewhere.

Implement V8dotNet to make typescript-addin platform independent

As a Developer
I want to use the typescript-addin on different platforms *nix/Osx/Windows
to write Typescript code with Monodevelop

Done When

  • Implement CsharpTypescriptLanguageService
    • Remove Typescript types from the project
    • Remove Json marshaling of return values
    • Update code base to Typescript 1.5
    • refs #7 Add unit tests

Using v8dotnet with the typescriptbinding
In this issue I will explain the assumptions, changes and thoughts that I made while investigating the support of v8dotnet for the typescript-binding. I will use FMC models to explain my thoughts. Feel free to correct me if I made a wrong assumption about something or share your opinion with me.

TypeScriptBinding FMC modeling

TypescriptBinding
I observed that the TypescriptBinding consists of the following building blocks: V8, Hosting, Provider and Project (MD) related belongings.

Providers

Provider seperate responisbilties of the Typescript language service (ts service api) The Typescript service API can be separated in different responsibilities like parsing, formatting, diagnostics, completion, info, compile. We implemented for each responsibilitiy one provider.

  • Parsing
    • getNavigateToItems()
    • getNavigationBarItems()
    • cleanupSemanticCache()
    • dispose()
  • Diagnostics
    • getSyntacticDiagnostics()
    • getSemanticDiagnostics()
    • getCompilerOptionsDiagnostics()
    • //returns comment, identifier, keyword,number,operator,string ,.. used for hilighting???
    • getSyntacticClassifications()
    • getSemanticClassifications()
  • Completion TypeScriptCompletionItemProvider
    • Provides complition info when a user types a point after an object or uses strg+spacebar. The provider uses the Typescript context to call:
      • getCompletionsAtPosition()
      • getCompletionEntryDetails()
      • getQuickInfoAtPosition()
      • getNameOrDottedNameSpan()
      • getBreakpointStatementAtPosition() //Get the breakpoint span in given sourceFile
      • getSignatureHelpItems()
  • Formatting
    • getFormattingEditsForRange()
    • getFormattingEditsForDocument()
    • getFormattingEditsAfterKeystroke()
  • Info
    • getRenameInfo() //Information about the item to be renamed
    • findRenameLocations()
    • getDefinitionAtPosition()
    • getReferencesAtPosition()
    • getOccurrencesAtPosition()
    • getOutliningSpans()
    • getTodoComments()
    • getBraceMatchingAtPosition()
    • getIndentationAtPosition()
    • getSourceFile()
  • Compile
    When it comes to compiling we have two possibilities. One solution is to use getEmitOutput() function which takes a filename returns the result, or we construct a compiler with getProgram() which takes a file and returns diagnostics. But then we have to implement an additional CompileHostEnvironment(). This is needed because the language service and the compiler using different host environments. The compiler uses:
    Compiler API , Host , EmitHost) , while the service uses TS API and Host.
    - getEmitOutput()
    - getProgram()
  • Debugger
    • The debugger uses websockets to communicate with the chromium dev tools. We use it to obtain values, set and release breakpoints.
    • The debugger provider maybe is also responsible to start the KestrelHttpServer to serve web content.
    • The debugger should be able to use chromium dev tools to live reload on file save.

Note: On VS providers are executed on different threads threads

V8dotnet

V8dotnet is a wrapper around the chromium V8 project. Different then other similar projects like Javascript.Net it uses P/Invoke to focus on platform independence. V8dotnet is developed by James Wilkins and he is mostly the only maintainer of v8dotnet. V8dotnet has a similar syntax like the native V8 library. To start with v8donet I used the following resources.

An usage example of the of the v8dotnet library:

function foo() {
return 42;
}

Native v8:

HandleScope scope;
LocalContext context;

Script::Compile(String::New("function foo() { return 42; }"))->Run();

Local fun = Local::Cast(context->Global()->Get(String::New("foo")));

int argc = 0;
Handle argv[] = NULL;

Handle result = fun->Call(fun, argc, argv); // argc and argv are your standard arguments to a function

With V8dotnet:

Handle handle;
V8Engine v8Engine = new V8Engine();
int number = v8Engine.Execute(@"function foo() { return 42; }");

Or an native approach:

string number = v8Engine.Execute(@"function foo() { return 42; }");
InternalHandle handle = v8Engine.GlobalObject.GetProperty("foo");
var temp = handle.Call(null);

Calling an object

v8Engine.Execute(@"fooObj = { foo : function (bar) { return bar + 42; } }");
InternalHandle handle = v8Engine.GlobalObject.GetProperty("fooObj");

Handle varHandle = v8Engine.CreateValue("V8dotnet=");
var temp = handle.Call("foo",null,varHandle);

CsharpTypeScriptLanguageService
The CsharpTypeScriptLanguageService excites of 3 projects. TypeScriptLanguageServiceTranspiler,TypeScriptLanguageService and TypeScriptLanguageServiceTranspilerTest,
We will use the CsharpTypeScriptLanguageService to reflect the TypeScriptLanguageService API on the managed side.
While investigating V8dotnet and TypeScript and Monodevelop addin development. I recognized that the TypeScript API changes frequently. It is hard to observe which Types changed or what functionality was added. I decided to use TypeScript itself to generate classes/interfaces ( services.ts, types.ts ) that have c# syntax. This is done in the TypeScriptLanguageServiceTranspiler which is a rudimentary implementation to transpile typescript interfaces to c# classes. It also generates the TypeScriptLanguageService API from services.ts. The TypeScriptLanguageService uses an utility function to map the v8 context objects to managed objects. This is done with reflection in the TypeMapper() function.

Like Javascript.Net, v8dotnet is also able to use callbacks. We can just use an attribute on a function and v8donet is able to call the managed function. But this has the disadvantage that we need to annotate all classes which are part of the serialize and deserialize process (return and call parameter). One solution to avoid this problem is to use Jason.Stringify(), but serializing/deserializing is time consuming.

We have two possibilities to avoid serializing based on the same approach:

Static approach

public CompletionInfo GetCompletionsAtPosition( string filename, int offset){

//create call parameters
Handle filenameHandle = v8Engine.CreateValue(filename);
Handle positionHandle = v8Engine.CreateValue(offset);

//get language service object
var ls = v8Engine.GlobalObject.GetProperty("ls");
var resultHandle = ls.Call("getCompletionsAtPosition", null,filenameHandle,positionHandle);

bool isMemberCompletion = resultHandle.GetProperty("isMemberCompletion");
ObjectHandle entriesHandle = resultHandle.GetProperty("entries");
int arrayLength = entriesHandle.ArrayLength;
CompletionEntry[] entries = new CompletionEntry[arrayLength];
for (int i = 0; i < arrayLength; i++)
{
entries[i] = new CompletionEntry( 
entriesHandle.GetProperty(i).GetProperty("name"),
entriesHandle.GetProperty(i).GetProperty("kind"),
entriesHandle.GetProperty(i).GetProperty("kindModifiers")
);
}
return new CompletionInfo(isMemberCompletion, entries);
}         

This function constructs native call parameters and calls the getCompletionsAtPosition function of the Typescript language service. The return values are then marshaled into managed types. Here we are saving time because we don't need to serialize objects first.
To speed up development this can be implemented with an T4 template.

Second approach:

public CompletionInfo  GetCompletionsAtPosition (   string fileName,  int position) {

Handle fileNameHandle = v8Engine.CreateValue(fileName);

Handle positionHandle = v8Engine.CreateValue(position);
var resultHandle = languageService.Call("getCompletionsAtPosition", null ,fileNameHandle,positionHandle);
var result = utilities.TypeMapper<CompletionInfo>(resultHandle);
return result;

}

Since we already have classes we can use reflection to construct the object. The object obtains it's own properties and uses the handle to access the corresponding property in the v8 context. I read that reflection is also costly, when we need more performance we can abandon this approach and use the static generated approach, explained before.

There is also an issue with Uninon types, for instance var foo = string | string[ ]. This is easy we can just use string [ ] as property type and checking the length of the type to initializing it. But what can we do with this messageText: string | DiagnosticMessageChain; which comes from interface Diagnostics and DiagnosticMessageChain. Currently only the first type is selected.

Host environment

We have two host environments the managed host and the v8 related host.

The managed host doesn't know anything about v8, while the V8LanguageServiceHost has an instance of the managed LangauageServiceHost
The TypescriptContext updates then the LanguageServiceHost with new files and file infos. Furthermore, the V8LanguageServiceHost calls the LanguageServiceHost to get this information.

IScriptSnapshotAdapter
This interface is used to exchange data between the managed LangauageServiceHost and the V8LanguageServiceHost to compute the get text change rate. Here we need an algorithm to calculate the exact line changes. Currently we search for the first line that changed.

CRLF vs LF
We need to make sure the all files have the same line endings before initializing the native typescript service. This option can not be changed afterwords.

Building the TypescriptBinding with CsharpTypeScriptLanguageService

  • git clone

  • git submodule update --init --recursive

    • if the remote contains changes
      • git submodule update --remote
    • if you want to revert submodule changes
    • git submodule init

    Project
    Monodevelop related stuff like addin-extensions for the project-options and monodevelop events.

    • which extension points do we use ?
    • We generated the CompilerOptions setter/getter for the project options but this needs more work.

    Naming
    There are a lot of service, typescript, shim host, parser names for objects and I introduced even more service, lanugeage ... I think it is good to have a naming convention.
    And Maybe a directory structure.

  • Hosting

  • Provider

    • Parser
    • Formating
    • Diagnostic
    • Complition
    • Debugger
  • Binding // Extension points / gui related assets
    What about namespaces?

Unit testing
For easier unit testing we can use SimpleInjector for IoC which should be fast by design and work on different platforms, but is it usable within Monodevelop?

Switch bettween the config for windows ( x86) , linux and osx (x86)
CsharpTypeScriptLanguageService has currently no .nupkg. To use it, we have included the CsharpTypeScriptLanguageService to the TypescriptBinding project.

Change the current project config to windows:

  • TypescriptBinding
    • use lib/V8dotnet/win.x86_x64/TypeScriptBinding.addin.xml
    • reference src/CSharpTypeScriptLanguageService/V8dotnet/win.x86_x64
      • V8.Net
      • V8.Net.Proxy.Interface
      • V8.Net.SharedTypes
  • TypeScriptLanguageService
    • reference src/CSharpTypeScriptLanguageService/V8dotnet/win.x86_x64
      • V8.Net
      • V8.Net.Proxy.Interface
      • V8.Net.SharedTypes
    • add as content and mark copy to ouput
      • msvcp110.dll
      • msvcr110.dll
      • v8-ia32.dll
      • vccorlib110.dll
      • remove libV8_Net_Proxy.so

This libraries are costum builds of v8dotnet. V8dotnet uses an app start event to Load the dlls but this events get never called in mono.

contribution
This are some assumptions and ideas that I made while investigating v8dotnet for mono, if you like it would be nice if I can contribute something of this list to the project. We can start using gitter and hubord to keep track of things that needed to be done.

NullReferenceException when renaming C# file

With the MonoDevelop Main.sln open and a C# file open in the text editor when F2 is pressed to rename a C# method the TypeScript addin is being run and an exception is thrown:

ERROR [2015-01-05 12:17:00Z]: Error while executing command: Rename
System.NullReferenceException: Object reference not set to an instance of an object.
   at ICSharpCode.TypeScriptBinding.TypeScriptCodeCompletionTextEditorExtension.UpdateContext(TypeScriptContext context, TextEditorData editor)
   at ICSharpCode.TypeScriptBinding.TypeScriptCodeCompletionTextEditorExtension.GetReferences(TextEditorData editor)
   at ICSharpCode.TypeScriptBinding.RenameTypeScriptReferenceCommandHandler.Run(Document document)
   at ICSharpCode.TypeScriptBinding.TypeScriptCommandHandler.Run()
   at MonoDevelop.Components.Commands.CommandHandler.Run(Object dataItem)
   at MonoDevelop.Components.Commands.CommandHandler.InternalRun(Object dataItem)
   at MonoDevelop.Components.Commands.CommandManager.DefaultDispatchCommand(ActionCommand cmd, CommandInfo info, Object dataItem, Object target, CommandSource source)
   at MonoDevelop.Components.Commands.CommandManager.DispatchCommand(Object commandId, Object dataItem, Object initialTarget, CommandSource source)

How to build a mono with typescript

Is there a way to build typescript all together while building mono? So that I don't need to install typescript again after building mono?

Compiled JS file not updating if already open

Nice addin and thanks for keeping it up to date 👍

I'm noticing an issue with the generated .js file when compiling on save where if the .js file is open in Xamarin Studio, it doesn't reflect changes from compiling the corresponding .ts file.

Reproduction steps:
1.Create/add to project myclass.ts
2.Create simple class

class MyClass { }

3.Save (with option to compile on save enabled).
4.Add myclass.js to project and open it.
5.Modify myclass.ts and save
6.myclass.js hasn't updated since first opened.

I'm not sure the best way to approach the problem, as when I've done it in the past for an Xamarin Studio addin, the best way I could find was to force the IDE to close and reopen the file, like so. Any ideas?

Using Xamarin Studio 5.10.1 (build 6) and addin version 0.9 on OSX

Style Guide

If you accepted pull request in the future, could you provide a style guide for it ❔
I would like to use spaces for tabs are you OK with that 🙏 ?
What are the monodevelop code format options that you are using?

Duplicate javascript file shown in MonoDevelop's Solution window

To reproduce:

  1. Open an ASP.NET MVC project into MonoDevelop.
  2. Add a TypeScript file to the project.
  3. With Compile on Save enabled, save the file.

Expected result:

JavaScript file added as child of TypeScript file in Solution window.

Actual result:

Two JavaScript files added to the TypeScript file in the Solution window.

Investigation

Debugging the code it looks like the problem is in MonoDevelop. It looks like the Project.OnFileAddedToProject is called twice if an AspNetAppProject is opened. For other types of projects the duplicate file does not get added.

Adding the DependsOn value after the project file is added does not fix the problem either. It also has another side effect that if the javascript file is deleted from the Solution window, the duplicate file node is left. Deleting the second node causes an unhandled exception.

When opening a non-AspNetProject there are still problems. When the JavaScript file is deleted using the Solution window, saving the TypeScript file again then creates two child nodes.

Note that Visual Studio does not add the JavaScript files to the project, which may be the required workaround.

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.