Giter VIP home page Giter VIP logo

ols's Introduction

ols

Language server for Odin. This project is still in early development.

Note: This project is made to be up to date with the master branch of Odin.

Table Of Contents

Installation

cd ols

# for windows
./build.bat

# for linux and macos
./build.sh

Configuration

In order for the language server to index your files, it must know about your collections.

To do that you can either configure ols via an ols.json file (it should be located at the root of your workspace).

Or you can provide the configuration via your editor of choice.

Example of ols.json:

{
	"$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json",
	"collections": [
		{ "name": "custom_collection", "path": "c:/path/to/collection" }
	],
	"enable_semantic_tokens": false,
	"enable_document_symbols": true,
	"enable_hover": true,
	"enable_snippets": true,
	"profile": "default",
	"profiles": [
		{ "name": "default", "checker_path": ["src"]},
		{ "name": "linux_profile", "os": "linux", "checker_path": ["src/main.odin"]},
		{ "name": "windows_profile", "os": "windows", "checker_path": ["src"]}
	]
}

You can also set ODIN_ROOT environment variable to the path where ols should look for core and vendor libraries.

Options:

enable_format: Turns on formatting with odinfmt. (Enabled by default)

enable_hover: Enables hover feature

enable_snippets: Turns on builtin snippets

enable_semantic_tokens: Turns on syntax highlighting.

enable_document_symbols: Turns on outline of all your global declarations in your document.

enable_fake_methods: Turn on fake methods completion. This is currently highly experimental.

enable_inlay_hints: Turn on inlay hints for editors that support it.

enable_procedure_snippet: Use snippets when completing procedures—adds parenthesis after the name. (Enabled by default)

enable_checker_only_saved: Turns on only calling the checker on the package being saved.

enable_references: Turns on finding references for a symbol. (Experimental)

enable_rename: Turns on renaming a symbol. (Experimental)

odin_command: Allows you to specify your Odin location, instead of just relying on the environment path.

checker_args: Pass custom arguments to odin check.

verbose: Logs warnings instead of just errors.

profile: What profile to currently use.

profiles: List of different profiles that describe the environment ols is running under.

Odinfmt configurations

Odinfmt reads configuration through odinfmt.json.

Example:

{
	"$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/odinfmt.schema.json",
	"character_width": 80,
	"tabs": true,
	"tabs_width": 4
}

Options:

character_width: How many characters it takes before it line breaks it.

spaces: How many spaces is in one indentation.

newline_limit: The limit of newlines between statements and declarations.

tabs: Tabs or spaces.

tabs_width: How many characters one tab represents

sort_imports: A boolean that defaults to true, which can be set to false to disable sorting imports.

Features

Support Language server features:

  • Completion
  • Go to definition
  • Semantic tokens
  • Document symbols
  • Rename
  • References
  • Signature help
  • Hover

Clients

VS Code

Install the extension https://marketplace.visualstudio.com/items?itemName=DanielGavin.ols

Sublime

Install the package https://github.com/sublimelsp/LSP

Configuration of the LSP:

{
	"clients": {
		"odin": {
			"command": [
				"/path/to/ols"
			],
			"enabled": false, // true for globally-enabled, but not required due to 'Enable In Project' command
			"selector": "source.odin",
			"initializationOptions": {
				"collections": [
					{
						"name": "collection_a",
						"path": "/path/to/collection_a"
					}
				],
				"enable_semantic_tokens": true,
				"enable_document_symbols": true,
				"enable_hover": true,
				"enable_snippets": true,
				"enable_format": true,
			}
		}
	}
}

Vim

Install Coc.

Configuration of the LSP:

{
	"languageserver": {
		"odin": {
			"command": "ols",
			"filetypes": ["odin"],
			"rootPatterns": ["ols.json"]
		}
	}
}

Neovim

Neovim has a builtin support for LSP.

There is a plugin that turns easier the setup, called nvim-lspconfig. You can install it with you prefered package manager.

A simple configuration to use with Odin would be like this:

local lspconfig = require('lspconfig')
lspconfig.ols.setup({})

Emacs

;; With odin-mode (https://github.com/mattt-b/odin-mode) and lsp-mode already added to your init.el of course!.
(setq-default lsp-auto-guess-root t) ;; if you work with Projectile/project.el this will help find the ols.json file.
(defvar lsp-language-id-configuration '((odin-mode . "odin")))
(lsp-register-client
 (make-lsp-client :new-connection (lsp-stdio-connection "/path/to/ols/executable")
				  :major-modes '(odin-mode)
				  :server-id 'ols
				  :multi-root t)) ;; This is just so lsp-mode sends the "workspaceFolders" param to the server.
(add-hook 'odin-mode-hook #'lsp)

Helix

Guide for installing helix with ols: https://github.com/joaocarvalhoopen/Helix_editor_for_the_Odin_programming_Language

Micro

Install the LSP plugin

Configure the plugin in micro's settings.json:

{
	"lsp.server": "c=clangd,go=gopls,odin=ols"
}

Kate

First, make sure you have the LSP plugin enabled. Then, you can find LSP settings for Kate in Settings -> Configure Kate -> LSP Client -> User Server Settings.

You may have to set the folders for your Odin home path directly, like in the following example:

{
    "servers": {
        "odin": {
            "command": [
                "ols"
            ],
            "filetypes": [
                "odin"
            ],
            "url": "https://github.com/DanielGavin/ols",
            "root": "%{Project:NativePath}",
            "highlightingModeRegex": "^Odin$",
            "initializationOptions": {
                "collections": [
                    {
                        "name": "core",
                        "path": "/path/to/Odin/core"
                    },
                    {
                        "name": "vendor",
                        "path": "/path/to/Odin/vendor"
                    },
                    {
                        "name": "shared",
                        "path": "/path/to/Odin/shared"
                    },
                    {
                        "name": "src", // If your project has src-collection in root folder, 
                        "path": "src"  // this will add it as a collection
                    },
                    {
                        "name": "collection_a",
                        "path": "/path/to/collection_a"
                    }
                ],
                "odin_command": "path/to/Odin",
                "verbose": true,
                "enable_document_symbols": true,
                "enable_hover": true
            }
        }
    }
}

Kate can infer inlay hints on its own when enabled in LSP settings, so enabling it separately in the server config can cause some weird behavior.

ols's People

Contributors

adelarsq avatar akselmo avatar danielgavin avatar deadwanderer avatar dresswithpockets avatar fabiansperber avatar feoramund avatar flga avatar flplv avatar ftphikari avatar harold-b avatar hhhapz avatar hovsater avatar hwchen avatar ianlilleyt avatar il-k avatar isaiahpaget avatar jamesdsource avatar judahcaruso avatar laytan avatar nico-barbas avatar oliverlars avatar oluigipo avatar ryuukk avatar sfluorine avatar tetralux avatar thephtest avatar thetarnav avatar xb-bx avatar yay 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ols's Issues

foreign system code not formatting correctly

This

package test

foreign import test {"system:c", "system:vulkan"}

foreign test {
    my_proc :: proc(argument1: f32,argument2: f32,argument3: f32,argument4: f32,argument5: f32,argument6: f32) ---
}

Formats to

package test

foreign import test "system:c" "system:vulkan"

foreign test {
    my_proc :: proc(
        argument1: f32,
        argument2: f32,
        argument3: f32,
        argument4: f32,
        argument5: f32,
        argument6: f32,
    )
    ---
}

Which won't compile because {} are removed from the list in foreign import and --- is placed on the line after )

Vscode error

I installed ols and vscode addon, added ols to path, but when i trying to type something it gives me this:

[Error - 4:30:56 PM] error in parse file for indexing /home/gohryt/Resources/Odin/Odin/core/builtin/builtin.odin
[Error - 4:30:56 PM] error in parse file for indexing /home/gohryt/Resources/Odin/Odin/core/intrinsics/intrinsics.odin
/home/gohryt/Resources/Odin/ols/src/server/analysis.odin(2373:31) Index -1 is out of bounds range 0:107
[Info - 4:31:03 PM] Connection to server got closed. Server will restart.
[Error - 4:31:03 PM] Request textDocument/completion failed.
Error: Connection got disposed.
at Object.dispose (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/connection.js:1044:27)
at Object.dispose (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-languageclient/lib/common/client.js:74:35)
at LanguageClient.handleConnectionClosed (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-languageclient/lib/common/client.js:2408:42)
at LanguageClient.handleConnectionClosed (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-languageclient/lib/node/main.js:155:15)
at closeHandler (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-languageclient/lib/common/client.js:2395:18)
at CallbackList.invoke (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/events.js:55:39)
at Emitter.fire (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/events.js:117:36)
at closeHandler (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/connection.js:256:26)
at CallbackList.invoke (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/events.js:55:39)
at Emitter.fire (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/events.js:117:36)
at StreamMessageWriter.fireClose (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/messageWriter.js:42:27)
at Socket. (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/messageWriter.js:75:42)
at Socket.emit (events.js:315:20)
at Pipe. (net.js:674:12)
[Error - 4:31:03 PM] error in parse file for indexing /home/gohryt/Resources/Odin/Odin/core/builtin/builtin.odin
[Error - 4:31:04 PM] error in parse file for indexing /home/gohryt/Resources/Odin/Odin/core/intrinsics/intrinsics.odin
/home/gohryt/Resources/Odin/ols/src/server/analysis.odin(2373:31) Index -1 is out of bounds range 0:107
[Info - 4:31:06 PM] Connection to server got closed. Server will restart.
[Error - 4:31:06 PM] Request textDocument/completion failed.
Error: Connection got disposed.
at Object.dispose (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/connection.js:1044:27)
at Object.dispose (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-languageclient/lib/common/client.js:74:35)
at LanguageClient.handleConnectionClosed (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-languageclient/lib/common/client.js:2408:42)
at LanguageClient.handleConnectionClosed (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-languageclient/lib/node/main.js:155:15)
at closeHandler (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-languageclient/lib/common/client.js:2395:18)
at CallbackList.invoke (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/events.js:55:39)
at Emitter.fire (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/events.js:117:36)
at closeHandler (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/connection.js:256:26)
at CallbackList.invoke (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/events.js:55:39)
at Emitter.fire (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/events.js:117:36)
at StreamMessageReader.fireClose (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/messageReader.js:40:27)
at Socket. (/home/gohryt/.vscode/extensions/danielgavin.ols-1.0.0/node_modules/vscode-jsonrpc/lib/common/messageReader.js:125:42)
at Socket.emit (events.js:327:22)
at Pipe. (net.js:674:12)
[Error - 4:31:06 PM] error in parse file for indexing /home/gohryt/Resources/Odin/Odin/core/builtin/builtin.odin
[Error - 4:31:06 PM] error in parse file for indexing /home/gohryt/Resources/Odin/Odin/core/intrinsics/intrinsics.odin

my ols.json wich i placed to project folder is:

{
"collections": [{ "name": "core", "path": "/home/gohryt/Resources/Odin/Odin/core" },
{ "name": "shared", "path": "/home/gohryt/Projects/Bomb" }],
"thread_pool_count": 4,
"enable_document_symbols": true,
"enable_semantic_tokens": false,
"enable_hover": true,
"enable_global_std": true,
"verbose": true
}

Handle procedure overloading correctly

I need to refractor the resolve system away from using SymbolGenericValue to specific types:
SymbolDynamicArrayValue,
SymbolFixedArrayValue,
SymbolMapValue,
SymbolSliceValue,
SymbolBasicValue,
SymbolUntypedValue,

This change should make it possible to support procedure overloading correctly.

typing `import` causes crash

Project with structure

ols.json
src/
	main.odin

ols.json

{
    "collections": [{ "name": "", "path": "." }],
    "thread_pool_count": 4,
    "enable_semantic_tokens": false,
    "enable_document_symbols": true,
    "enable_hover": true
  }

main.odin

package main

typing "import" on line 3 of main.odin causes ols error:

C:/Odin/shared/ols/src/server/analysis.odin(2241:51) Invalid slice indices: 0:23:22

followed by crash.

#13 is likely related?

Add dynamc indexing

Implement dynamic indexer that runs in a background that can index modified files in clients workspace.

Indexing workspace is not implicit

In order for ols to index my project's code, I've had to add this entry into collections in ols.json:

{"name": "", "path": "."}

is this by design? This isn't mentioned in the readme so I'm uncertain if this is a bug or intended.

Ols doesn't build with newest Odin

Just a quick note that ols fails to build with Odin as of April 22, 2021 at 21:31 MST. I reverted back to commit 2db1fe74299766c9a29a33c39299d07e12556bb2 for Odin, rebuilt Odin and then it compiled ols fine.

Just thought I would mention it in case someone else runs into this problem before ols is updated. :)

Adding emacs to clients.

Hello and thanks for your work on ols!
Sorry for adding this as an issue I didn't know where else to put it and is such a small thing that a full pull request seemed like too much.
I've been testing ols on linux with odin-mode (found in the "odin libs" section of the odin wiki) and lsp-mode. Completion and hovering are working great, goto-definition of functions does make the server crash sometimes, (with exit code "1"), but other than that I haven't had any issues.
So I was wondering if you might like to add emacs to the list of clients in the README file.
If you decide to add it, here's the config:

;; With odin-mode (https://github.com/mattt-b/odin-mode) and lsp-mode already added to your init.el of course!.
(setq-default lsp-auto-guess-root t) ;; if you work with Projectile/project.el this will help find the ols.json file.
(defvar lsp-language-id-configuration '((odin-mode . "odin")))
(lsp-register-client
 (make-lsp-client :new-connection (lsp-stdio-connection "/path/to/ols/executable")
                  :major-modes '(odin-mode)
                  :server-id 'ols
                  :multi-root t)) ;; This is just so lsp-mode sends the "workspaceFolders" param to the server.
(add-hook 'odin-mode-hook #'lsp)

Please, let me know if you need any more info.
Cheers!.

Implement delta semantic token feature

The current semantic token has to resolve the entire file per key press, and this does not scale well with larger files. Implement the ability to only send the changes since last semantic request.

Generic handling of `when` boolean expressions

Right now the when conditions are hardcoded for handling ODIN_OS, but at some point it would be nice to support many other variables of the ODIN_* prefixes, and also not have it hardcoded, i.e. right now it only detects when ODIN_OS == "windows", but not when "windows" == ODIN_OS

Attributes can cause incorrect indentation in other blocks

This code gets formatted as follows:

package test

Some_Enum :: enum {
	Field1                       = 0x9,
	Field2                       = 0xA,
}

@(default_calling_convention = "c")
@(link_prefix                = "foobar")
foreign bar {
	Foo :: proc() ---
}

The attributes attached to the foreign block cause the enum values to be indented. Commenting out the foreign block and formatting corrects the enum indentation.

Failing to build on latest dev

Was trying to build on the latest odin release but it comes up with a lot of errors, i've tried to go through and fix it myself to make a PR or something, but I don't know odin well enough.

image

Support global core completion

Allow options to be set that completes all core without requiring it to be imported, and when the user completes a core symbol, it automatically adds an import to the top of the file.

VScode ols crashes with proc keyword and parentheses

Code snippets

Typing a character in two parentheses after proc, I've only tested !, %, & and *:

package main
main :: proc((*)) {}

Error

Only got Connection to server got closed. in the output window

VSCode info:

Version: 1.53.0-insider (system setup)
Commit: 32b28f6f8f9dfe36efad102cc460e14a84ba756a
Date: 2021-01-19T06:09:44.762Z
Electron: 11.2.0
Chrome: 87.0.4280.141
Node.js: 12.18.3
V8: 8.7.220.31-electron.0
OS: Windows_NT x64 10.0.19041

VSCode variable shadowing causes crash

Code Snippet

package main

main :: proc() {
	x : [3]int;
	for i := 0; i < len(x); i += 1 {
		x := x[i] // Crash
	}
}

Output

Connection to server got closed.

Reproduce

Seems to crash as soon as I type the i index.

Versions

OLS: commit 51595ac (newest as of writing this)
Odin: 0.13.1-92431c83
VSCode:

Version: 1.53.1 (system setup)
Commit: 5d424b828ada08e1eb9f95d6cb41120234ef57c7
Date: 2021-02-08T23:29:42.785Z
Electron: 11.2.1
Chrome: 87.0.4280.141
Node.js: 12.18.3
V8: 8.7.220.31-electron.0
OS: Windows_NT x64 10.0.19041

Failing LS request with error "Clone type Unhandled node kind: Type_Cast"

Running the latest commit of ols against one of my projects resulted in LS request failure with error:

Clone type Unhandled node kind: Type_Cast

I made this change

@@ -214,6 +214,10 @@ clone_node :: proc(node: ^ast.Node, allocator: mem.Allocator, unique_strings: ^m
        case Helper_Type:
                r := cast(^Helper_Type)res;
                r.type = clone_type(r.type, allocator, unique_strings);
+       case Type_Cast:
+               r := cast(^Type_Cast)res;
+               r.type = clone_type(r.type, allocator, unique_strings);
+               r.expr = clone_type(r.expr, allocator, unique_strings);
        case:
                panic(fmt.aprintf("Clone type Unhandled node kind: %T", node.derived));
        }

which ultimately allowed the failing LS request to succeed. I'm largely unfamiliar with the purpose of clone_node and the inner workings of this project, so I do not know if this is a correct implementation for Type_Cast here, and do not know if in reality this is just a bandaid over a different bug in OLS which resulted in this faulty call.

Is this a valid fix? If so I'll happily move this into a PR, otherwise I felt this would be better as an issue for discussion's sake.

Crash in VSCode passing proc value to function

Code snippet

package main

import la "core:math/linalg"
import "core:strings"

main :: proc() {
	sb := strings.make_builder_len(la.length);
}

Reproduce

Typing in the name of the length function to the make_builder_len function closes the server.
I know that that shouldn't be the parameter to that function, but I was preemptively putting a length variable as the argument before the variable was declared, so it used the length function instead.

New static indexer

Right now the static indexer uses a naive approach that is fast enough for now, but as projects get bigger, the static indexer needs to get faster.

It could be a file indexer or an in memory indexer(Maybe allow for choosing the indexer).

VSCode OLS crash with euro character

Code snippet

package main
import €
main :: proc() {
    i: int;
}

Output

c:/Odin/Projects/Test/ols.odin(2:4) illegal character '€': 8364
[Error - 20:49:38] Connection to server is erroring. Shutting down server.

Only some types of crash outputs the illegal character line.
Every crash outputs that the server is erroring.

Reproduce (I was experimenting as well)

OLS crashes when a is typed after import
OLS won't crash if already exists when OLS is started.
If OLS is started after is typed, typing another crashes it (also with some but not other characters).
If OLS is started after is typed, typing "i: in" in main crashes OLS, as soon as n is typed.
OLS doesn't crash when only typing in main, only when it's in the import statement.

Maybe this is too specific, but that's the behaviour I saw

Support for multi-pointers

This will fail to format

package test

Test :: struct {
    data: [^]u8,
}

main :: proc() {}

Truncated error message

ols/src/odin/printer/visit.odin(1042:3) panic: Multi_Pointer_Type{node = Expr

VScode ols server crashing when import is missing final quote

Code snippet

Missing the " after the : in an import statement, though only when there is text between the first " and :

package main
import "core:

ols.json:

{
    "collections": [
	{ "name": "core", "path": "C:/Odin/Odin/core/" },
        { "name": "shared", "path": "C:/Odin/Odin/shared/" }
    ],
    "thread_pool_count": 4,
    "enable_document_symbols": true,
    "enable_semantic_tokens": true,
    "enable_hover": true
}

Error

Output window:
C:/Odin/Tools/ols/src/server/documents.odin(415:30) Invalid slice indices: 6:5:6

VSCode info:

Version: 1.53.0-insider (system setup)
Commit: 32b28f6f8f9dfe36efad102cc460e14a84ba756a
Date: 2021-01-19T06:09:44.762Z
Electron: 11.2.0
Chrome: 87.0.4280.141
Node.js: 12.18.3
V8: 8.7.220.31-electron.0
OS: Windows_NT x64 10.0.19041

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.