Giter Site home page Giter Site logo

stylecop / stylecop Goto Github PK

View Code? Open in Web Editor NEW
1.2K 73.0 149.0 361.39 MB

Analyzes C# source code to enforce a set of style and consistency rules.

License: Microsoft Public License

JavaScript 0.13% CSS 0.65% C# 79.23% Batchfile 0.01% HTML 19.97% PowerShell 0.01% Smalltalk 0.01%

stylecop's Introduction

StyleCop "Classic"

NOTE: This project is no longer very active. See the "Considerations" section below.

Gitter

StyleCop analyzes C# source code to enforce a set of style and consistency rules. It is available in two primary forms:

  1. The StyleCop Visual Studio extension, which allows StyleCop analysis to be run on any file, project, or solution in Visual Studio without modifying the source code. Visual Studio 2010, 2012, 2013, 2015, 2017, and 2019 are supported by this extension.
  2. The StyleCop.MSBuild NuGet package, which allows StyleCop analysis to be added to any .NET 4.0+ project without installing anything else on the system.

There is also a ReSharper plugin that can be added using ReSharper's Extension Manager.

Considerations

While pull requests will continue to be accepted, it is unlikely that any major development (including support for newer C# syntax) will be done on this project. It is increasingly difficult and inefficient to maintain the custom C# parser used by StyleCop. The primary motivation for recent maintenance work was to allow developers who were already using StyleCop to upgrade to Visual Studio 2015 and C# 6.

The Roslyn-based StyleCopAnalyzers project is strongly recommended for developers who use only Visual Studio 2015 or later.

stylecop's People

Contributors

bexxx avatar citizenmatt avatar csdahlberg avatar darkcloud14 avatar edward-raven avatar emeka-nmc avatar gitter-badger avatar hemnstill avatar jeremyhaubold avatar jodli avatar matkoch avatar mpdeimos avatar peteroupc avatar sanjayguntur avatar stevejost avatar thanaen avatar thieum 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  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

stylecop's Issues

Consider joining StyleCopAnalyzers

Hi @citizenmatt,

I'd like to invite you to join the DotNetAnalyzers/StyleCopAnalyzers project. Over the past 9 months, more than 20 community members have joined together to build a faithful reproduction of StyleCop using the .NET Compiler Platform (Roslyn). The project implements the nearly all of the original StyleCop rules and even includes code fixes for most of them, all without requiring any special tools or Visual Studio extensions. The latest versions of ReSharper already support these code fixes as well, so those users are not left out. We have over 5000 unit tests (including coverage of C# 6 features), a live status page, and an active discussion room on Gitter.

If you don't join us, please consider at least joining our chat room to discuss ways to make sure our diagnostic IDs stay in sync over time. ๐Ÿ˜„

StyleCop for Resharper 2016.1 code cleanup header/doc

I have strange problem with insterting docs and header.
I have StyleCopeAnlayzers added to project.

If there is no summary for constructor, code cleanup removes header and do not insert default summary.
However if there is even empty summary for contructor, code cleanup insert file header. But still not insterts default default constructor documenation.

Overlap with file header settings + ReSharper

How should ReSharper handle the file header? This can be defined in ReSharper settings, or in the settings.stylecop file. It would be nice to use the ReSharper value, but that would mean we can get different results running in ReSharper and running from the command line.

Cannot build the source code

I thought I'd download the source code to my machine to have a go at building it to see what I could do and I've immediately run into an issue - I seem to be missing StyleCop.Build.Targets and StyleCop.Shipping.Targets - do you have copies of these or know where you can get them from?

The future of StyleCop?

So, I've been thinking about the future of StyleCop while updating the ReSharper plugin.

There are two big problems with the project, that I can see. Firstly, it's stagnated, with no new rules, etc. It's ripe for a shakeup. Secondly, and more importantly, the code is based on a custom C# parser that only supports up to C#5, and doesn't know anything about C#6.

The DotNetAnalyzers/StyleCopAnalyzers project is a port of StyleCop to Visual Studio 2015's Roslyn analyzers. This gives it a lot of benefits:

  • C#6 support
  • Let someone else (Microsoft!) worry about maintaining the C# parser
  • Since it reuses the Roslyn syntax tree, there is less overhead from the custom parser
  • Rules run as you type, and as you build (no more need for the msbuild task, or the VS extension)

Furthermore, they've already added a couple of new rules to work with C#6. Whatever happens to StyleCop "Classic", we need to involve and play nice with this project.

The downside is that it's VS2015 only, so that leaves out current users of the msbuild task, VS support + ReSharper for earlier versions. I think we can unify things, to an extent.

Here's my half thought out plan:

  • Deprecate this repo, splitting the projects up into their own repos.
  • Create a new stylecop-msbuild repo that is a task that wraps the Roslyn analysers. You don't need VS2015 installed, you don't need to be using the Roslyn toolchain, you just need .net 4.5 installed. I think this is reasonable. Now the msbuild project would simply rely on the Roslyn analyzers to do the work.
  • Create a new stylecop-visualstudio repo, to create a simple Visual Studio extension to add Tools menu items to run the Roslyn analysers in an external process, and display the results in the Error list window.
  • Create a new stylecop-resharper repo. This would contain the existing ReSharper plugin that I'm working on. It would use the existing C# parser (annoyingly, as ReSharper has already parsed the file, but that would mean a complete rewrite otherwise). This would work for VS2013 and below. VS2015 and above would be encouraged to install the Roslyn analysers, as ReSharper plays nicely there. For VS2015, the extension would automatically configure the users settings + provide code cleanup, etc.

This, to an extent, sunsets StyleCop "Classic" as such. The responsibility for creating new rules, and parsing rules, would move over to DotNetAnalyzers/StyleCopAnalyzers (which you can argue has already happened, thanks to the stagnation of the project), but provides a way for users of the other tools to stay up to date, even if they don't use VS2015.

Thoughts?

Confusion over settings

I'm still a bit confused as to how StyleCop, R# and your plugin co-exist, especially regarding the settings. We have StyleCop 4.7 installed, and up until today have always had a settings.stylecop file in each of our TFS "branch" folders (not the solution folder, but the one above this). I've never been happy with all these settings files, so today I deleted them all, after first copying our custom settings into the "global" settings.stylecop file (in C:\Program Files (x86)\StyleCop 4.7).

Now, if I run StyleCop manually (right-click solution explorer -> "Run StyleCop (Rescan All)") everything is still good, and no violations are reported. However the VS editor is now showing blue squiggles everywhere. Why has this started happening - does your plugin ignore the "global" settings file in the StyleCop install folder and only walk the tree that the solution is in?

Also, looking at my R# layers, all the StyleCop "inspection severity" items are set to "Warning", so I don't understand how things could have ever worked, even before today's changes. Your extension is the lowest layer in the list, so how does it override the StyleCop inspection severity settings in the higher layers?

Thanks in advance.

EDIT: sure enough it works if I put the settings file higher up in the folder hierarchy. I believe your plugin doesn't need StyleCop to be installed, so I guess it is not obliged to look in the StyleCop install folder for a settings file? I'm still curious as regards to my last paragraph...!

Using statements are being relocated even with SA1200 turned off.

I turned off SA1200 in a StyleCop settings file and put it in my solution folder. I then ran code cleanup on a file and the add-in still relocated my using block. I have attached my StyleCop settings file.

Before:

using System;
using System.Collections.Generic;
using Org.Edgerunner.Common.Buffers.Input;

namespace Org.Edgerunner.Common.Parsing.Tokens
{
   /// <summary>
   ///    Class that represents a single parsed language token.
   /// </summary>

After:

using System;

namespace Org.Edgerunner.Common.Parsing.Tokens
{
   using System.Collections.Generic;

   using Org.Edgerunner.Common.Buffers.Input;

   /// <summary>
   ///    Class that represents a single parsed language token.
   /// </summary>

Settings.StyleCop.zip

SA 0102

When using StyleCop as plugin in resharper 10 and using c#6 features like null conditionary expressions I get SA0102: CSharp.CsParser: A syntax error has been discovered in file...

example:

if (bla.Array?.Any() ?? false)

as this is a csparser rule, you can't supress it by settings file, is there a workaround?
I don't want to exclude the files from style cop parsing

StyleCop does fail for files with C# 6 features

I recently disvocered stylecop failing for certain files in VS15. But only some files seemed to be affected. I managed to break it down to files containing C# 6 features, like the conditional access operator (?.) or the new string interpolation ($"String with {variable}").

Repo Steps

Take a new C# class and use any C# 6 feature, like this close does:

using System;

namespace Repo
{
    class Program
    {
        public static void Main(string[] args)
        {
            string asd = $"{args[0]}";
        }
    }
}

StyleCop will not give any warnings about the using directive being out of the namespace or the class not having an access modifyer.
Now delete the '$' from the interpolated string - all warnings appear as expected.

Culture not taken into account R#10.02, VS 2015

Hi,

I've just migrated from VS 2013 to VS 2015.

R#10.02 and "Stylecop By Jetbrains" v4.8.0 are installed into both of them.

The thing is, in VS 2015, the "Culture for Analysis" option does not seem to be taken into account (Stylecop expects the XML doc comments to be redacted in English instead of the selected locale).

I've got the following folder structure :

GitRepo
|- Settings.StyleCop
|- Project1/
|- Project2/
...
|- ProjectX/
|- Solutions/
     |- Solution1.sln
     ...
     |- SolutionX.sln

And there is the relevant sections of my Settings.StyleCop file :

<StyleCopSettings Version="105">
  <GlobalSettings>
    <BooleanProperty Name="WriteCache">False</BooleanProperty>
    <BooleanProperty Name="AutoCheckForUpdate">False</BooleanProperty>
    <StringProperty Name="Culture">fr-FR</StringProperty>
    <StringProperty Name="MergeSettingsFiles">NoMerge</StringProperty>
  </GlobalSettings>
  <Analyzers>
   ...
  </Analyzers>
</StyleCopSettings>

Using StyleCop for ReSharper to provide Company and Copyright Information

How can we configure the company name and copyright text ?

// ---------------------------------------------------- // <copyright file="HomeControllerRoute.cs" company=""> // // </copyright> // <summary> // Defines the HomeControllerRoute type. // </summary> // ---------------------------------------------------------

Create #region directives when SA1124 is disabled (which is the default)

It would be nice to have regions back for those who let SA1124 disabled (it's the default when you use StyleCop from CodePlex and edit the settings with the UI)

I have an "in progress" workaround using the layout capabilities, something like the attached file patches the default StyleCop layout and add region names. Perhaps 2 layouts may be distributed and it would be up to the user to decide what to use.

Sample.DotSettings.zip

Add 'Cleanup only source-control modified' files

Would be nice to add a checkbox 'Cleanup only source-control modified', so we don't have to manually select Cleanup every single files separately.
The problem is that, when doing Cleanup Code on the whole Solution/Project, it cleanup files that are not source-control modified and thus sometimes, modifying them.

TypeLoadException (method not implemented) when starting stylecop

When I have the resharper extension "stylecop by jetbrains" not installed, everything seems to work fine.

When I installed the resharper extension I run the command ClassViewContextMenus ClassViewProject RunStyleCop, it shows me a message box titled StyleCop, with message "An exception occurred while loading one of the styleop addins: System.TypeLoadException, Method 'get_Container' in type 'somegarbledtype' from assembly 'yWorks.yFilesWPF.Viewer, Version=2.4.0.3, Culture=neutral,PublicKeyToke=sometoken'" does not have an implementation.

After uninstalling, the stylecop command runs fine again.

SA0102 : CSharp.CsParser : A syntax error has been discovered in file containing interpolation string with escaped quotes

Warning     SA0102 : CSharp.CsParser :
A syntax error has been discovered in file [path]\ImageOptimizer.cs on line 22

Code to reproduce:

namespace NotImportant
{
    using System;
    using System.Diagnostics;
    using System.IO;

    public class ImageOptimizer : IImageOptimizer
    {
        public byte[] OptimizePng(string optimizerExecutable, byte[] fileContent)
        {
            var fileName = Path.GetTempPath() + Guid.NewGuid() + ".png";
            try
            {
                // PNG file path.
                File.WriteAllBytes(fileName, fileContent);

                // Run OPTIPNG with level 7 compression.
                var info = new ProcessStartInfo
                               {
                                   FileName = optimizerExecutable,
                                   WindowStyle = ProcessWindowStyle.Hidden,
                                   Arguments = $"\"{fileName}\" -o7"
                               };

                // Use Process for the application.
                using (var exe = Process.Start(info))
                {
                    exe.WaitForExit();
                }

                return File.ReadAllBytes(fileName);
            }
            finally
            {
                try
                {
                    File.Delete(fileName);
                }
                catch
                {
                }
            }
        }

        public bool OptimizePng(string optimizerExecutable, string filePath)
        {
            try
            {
                // Run OPTIPNG with level 7 compression.
                var info = new ProcessStartInfo
                               {
                                   FileName = optimizerExecutable,
                                   WindowStyle = ProcessWindowStyle.Hidden,
                                   Arguments = $"\"{filePath}\" -o7"
                               };

                // Use Process for the application.
                using (var exe = Process.Start(info))
                {
                    exe.WaitForExit();
                }

                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}

Line 22 is:

Arguments = $"\"{fileName}\" -o7"

How to change row Highlighting color?

Hi guys!

Help please how to turn off whole-row highlighting(when I press Shift+Left, or Shift with other arrow)

In my dark scheme I don't see anything.. I'm not a cat :)

Image

Best regards,
Gennady

Methods are not sorting by name when running Cleanup Code with custom profile

I have Resharper 9.2 with the extention 4.7.1 (just updated from 4.7.0, but had same issue before) and when I run the cleanup code it does not reorder the methods alphabetically. I have the setting checked in the profile to use StyleCop. I have the setting in File Layout under Public methods and operators to sort by Static then by Name. I have the setting under Other methods to sort by Access then by Static then by Name. No methods get reordered alphabetically.

Exception thrown during R# 10.0.2 update

Hi,

When I update R# 10.0.1 to 10.0.2, this extension throws an error like the screenshot below.

image

Of course there was no issue on 10.0.1. Not sure whether anyone has been aware this of.

Cheers,

Header Creation

CodeCleanup creates empty copyright block while

  • "Update file header" disabled
  • "File Header Text" empty
  • Rules SA16XX disabled via Settings.StyleCop at Solution-Level

Error messages in ReSharper installer

When upgrading ReSharper with ReSharper installed, the installer reports an errors that it can't load the StyleCop.CSharp.Rules assembly from a reference in StyleCop.ReSharper.

This is because the StyleCop.CSharp.Rules assembly lives in a sub-folder of the ReSharper install folder, and can't be loaded by the installer. It lives in a sub-folder because StyleCop will use reflection to load the rules, and scan all files in the rules folder. If it lived in the main install folder, that would meaning using reflection on ALL of ReSharper. Not a good idea, perf-wise.

StyleCop.ReSharper has a reference for some string values used in quick fixes, and to get full type names to use loading the settings for the rules. Both of these uses could be changed to late bound references, and the error wouldn't be shown.

Technically, the installer should also report this as an error when installing the extension in the first place.

Improve support for high resolution screens

At present StyleCop does not display correctly on high resolution screens. This makes it extremely difficult to use.

These screenshots were taken on a Lenovo Yoga 3 pro with a display resolution of 3200 x 1800

stylecop
stylecop2

SA1600 Ignore Privates - option missing?

With StyleCop 4.7 the documentation rules could be set to ignore members based on access modifiers.

Is there a way to do this in StyleCop by JetBrains 2016.1.0? Here is a picture of the option I am referring to.

Thank You

stylecop settings

SA 1512 - Clears blank line after file header.

//
// Copyright (c) comp project. All rights reserved.
// Licensed under the Apache 2.0 license. See LICENSE file in the project root for full license information.
//
!!!!!! this blank line is deleted !!!!
namespace Comp.Code
{

But in this case is not cleared.

//
// Copyright (c) comp project. All rights reserved.
// Licensed under the Apache 2.0 license. See LICENSE file in the project root for full license information.
//
!!!!! this blank line is preserved !!!!
using System.Reflection;
using System.Resources;

image

Support for R# 10

Believe support for R# 10 would be added soon? Would love to have that asap.

R# StyleCop Inspections runs even if StyleCopAnalyzers plugged to project

This problem is not on the top.
It appers only on scenario when single *.ruleset file attached to multiple projects "as link".
I prepared simple solution that can be used to reproduce problem.
Steps to reproduce:

  1. Download and Open solution from this link (https://www.dropbox.com/s/yg3j2ifa3ns6qgk/StyleCopAnalyzersProblem.zip?dl=0)
  2. Wait until solution is fully loaded
  3. Load Missed nuget packages
  4. Open Resharper->Inspect->Code issues in solution (this step is optional but it shows problem clearly)
  5. Add to solution existing project DummyLib
  6. Open Class1.cs in the DummyLib project
  7. On Code issues window push refresh
    StyleCopAnalyzers will not be detected for DummyLib project.
    This is 100% workign way to reproduce the issue.

But when you load solution with multiple projects with ruleset attached as link, problem is appers with probability 1/3. So possibly if project loaded after R# stylecop do some action, StyleCopAnalysers can't be detected on that project.

Problem screenshot:
image

R# File Header Text not being applied

With this plugin installed, and a custom header defined in Options -> Code Editing -> File Header Text, running code cleanup on an individual file results in the wrong header being created. Looks like the default header maybe.? On Options -> Tools -> StyleCop "run StyleCop as you type", "Insert text into documentation and file headers", and "Use ExcludeFromStyleCop setting in csproj files" are checked.

Filtering Inspections Report by StyleCop categories is not working as expected

In R# 10.0.2 / StyleCop 4.8.0, I ran an inspection report for the solution, to pick up any existing StyleCop rule violations as well.

This returned several tens of thousands of items, also expected, including a number of StyleCop rules.

I then went to the Filter function, and included only StyleCop categories, and suddenly I had 0 results, even though in the previous view there were clearly StyleCop rule violations that were listed within the StyleCop categories I was trying to filter by.

Multiple separator lines in code cleanup

From this comment in #9

"I disabled the constructor/destructor documentation setting. We are using a "---------" separator line at the beginning and end of the documentation blocks which works fine for all other code elements, but on the constructors it wants the standard line:

Initializes a new instance of the class.

But when using the separator line it doesn't seem happy and adds another one of those lines every time you clean up the code, I found files that had that line 5 times for each constructor :)"

Finer-grained control of StyleCop-specific code cleanup

I know @citizenmatt mentioned that the StyleCop cleanup actions are now managed using the StyleCop configuration. However, there are cases where I want to enforce a StyleCop rule, but do not want to have ReSharper apply any "cleanup".

For instance, I want to require methods to be documented, but I do not want ReSharper to automatically document them.

Is there any way to achieve this currently?

Load custom StyleCop addins

StyleCop can run custom addins, e.g. StyleCop+, that provide custom rules. These are normally handled by automatically loading the addins from the install folder. The ReSharper extension doesn't have an install location, so there is no way of loading custom addins. Either load addins from known locations, or provide a setting in options to specify one or more addin locations.

(See this comment - #9)

Extracting a method adds this. qualifier even if disabled in R#

I extracted a simple method using R#, and StyleCop added the "this." qualifier to all properties in the new method (e.g. this.Connection instead of just Connection). The "old" StyleCop doesn't do that (just tried it).

In R#, the setting "Use this. qualifier for" is set to "Preference: none" and "Do not show".

Duplicate StyleCop warnings in tooltips.

This is just one example, but every StyleCop warning is displayed three times on tooltips.
Offending code:

private void Main_FormClosing(object sender, FormClosingEventArgs e)

Mouse Over tooltip:
2016-01-04_09-25-17

VS 2013, R# Ultimate 10.0.1
Only two extensions installed:

  • Enhanced Tooltip 2.7.1.17,
  • StyleCop by JetBrains 4.8.0

I've tested the issue with enhanced tooltip installed/uninstalled - same problem.

SA 1202 confclicts with "Static member initializer refers to static member below or in other type part"

The rule SA 1202 All private fields must be placed after all public fields confclicts with Static member initializer refers to static member below or in other type part. This is clrearly a problem when writing readonly dependency properties:

Following code-snippet has SA1202

private static readonly DependencyPropertyKey MyPropertyKey = DependencyProperty.RegisterReadOnly(...);
public static readonly DependencyProperty MyProperty = MyPropertyKey.DependencyProperty;

Following code-snippet Static member initializer refers to static member below or in other type part

public static readonly DependencyProperty MyProperty = MyPropertyKey.DependencyProperty;
private static readonly DependencyPropertyKey MyPropertyKey = DependencyProperty.RegisterReadOnly(...);

The Problem is that stylecop's warning is just a warning. But if following this warning the code gets broken because the DependencyProperty is then null;

Unable to install extension package within R# 10.0.0.2

I'm having a tuff time getting the extension package to install under R# 10.0.0.2.

The installation process chugs away and then prompts a VS restart. After the restart the extension is still not installed. Worked fine under R# 10.0.0.1.

StyleCop is installed within VS2015 and can be run via the solution explorer context menu options. The warnings appear in the build error list as expected.

Incidentally, what's dependencies for the SCbyJB extension? I've tried installing SC from the old CodePlex MSI and using the "Visual StyleCop" VS extension and both! Still no joy.

Any help greatly appreciated!

StyleCop Violation SA1210 not displayed in Visual Studio CodeFiles

Hi,

we use :

  • VS2015, Update 3
  • JetBrains ReSharper Ultimate 2016.1.2 Build 105.0.20160522.80219
  • ReSharper Extension: StyleCop by JetBrains 2016.1.0

The violation SA1210 (Using directives must be sorted alphabetically by the namespaces) not displayed in the visual studio code files.

Only a full cleanup sort the using directives correctly.

How can i reactivate the violation and the resharper quick-fix (Alt+Enter)?

Thank you

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.