Giter VIP home page Giter VIP logo

sidecar's Introduction

Sidecar Analyzer

Enable a more personalized developer experience within the IDE.

A screenshot of a Sidecar lint popup in an IDE

Build Status codecov License: MIT pub package

Visit the official documentation site for work-in-progress tutorials and explanations of core concepts

This is an experimental package which is expected to change slightly until an official 0.1.0 release. However, the core architecture of Sidecar has been designed around the Dart-official package:analyzer APIs, and therefore any rule packages you may want to experiment with will be easy to port over to any future APIs

Overview

Motivation

Dart lints are incredibly useful for keeping a codebase clean and tidy, but code analysis use cases don't need to end at official rules. What if we could use these same tools to enforce highly-opinionated rules for a particular package ecosystem (BloC vs Riverpod) or for a particular app?

The goal of Sidecar is to enable a more personalized developer experience by allowing quick and easy access to the core lint and code assist tools of modern IDEs.

Features

Lint Rules IDE CLI Debug
Lint messages
Define a default severity
Apply Quick Fix suggestions 🚧 🚧
(IDE) URL links to rule documentation 🚫 🚫
(CLI) Alternate output formats 🚫 🚧
Ignore statements
CodeEdit Rules IDE CLI Debug
QuickAssist rules 🚧
Refactorings (rename, extract, etc.)
Code Completion
Rule Configuration (sidecar.yaml) IDE CLI Debug
Explicitly Enable/Disable rules
(Lints) Override default severity
Rule-level include/exclude globs 🚧
Package-level include/exclude globs 🚧
Project-level include/exclude globs 🚧
Customizable rule configurations
Multi-import inheritance
MacOS Linux Windows
Environment Support

Usage

See the below guides for information on how to create and use Sidecar packages.

Example Sidecar Rule Packages

To explore how rule packages are created or to use them to work on your codebase, take a look at the following rule packages:

Installing the CLI tool

Some Sidecar tasks are easier with the CLI tool. To install the CLI, simply run:

dart pub global activate sidecar

Troubleshooting

Contributing

Suggestions or feature requests would be highly appreciated at this point in the development process, so that as many development use cases can be accounted for as possible. It's encouraged to reach out or open a Github issue against the Sidecar repository.

sidecar's People

Contributors

pattobrien avatar

Stargazers

 avatar Luciano Alfredo avatar nelson fernandez avatar Modi avatar Arnold Lumangtad Jr. avatar Matthew Jaoudi avatar  avatar Aljoscha Grebe avatar Massi avatar Jacob Richman avatar

Watchers

 avatar

sidecar's Issues

Create separate sidecar_cli init and watch commands

Below are the definitions for different stages of project setup and configuration:

Project Initialization

New Dart or Flutter project that does not yet have sidecar initialized.

  • create a base plugin for project lints/edits to live in (inside directory)
  • insert base plugin directory into project pubspec.yaml
  • add watcher task (e.g. VSCode tasks)

Rebuild Project Plugin

  • parse sidecar plugin configuration for declared lints/edits
  • add plugin configuration lints/edits into project-plugin pubspec.yaml and run pub get
  • generate bootstrap functions based on lint/fix configurations
  • restart plugin

Watch Project Configuration Changes

e.g. on pubspec.yaml or analysis_options.yaml changes

  • run sidecar rebuild on every config file change

Refactor lint initialization

Related issues:

  • CLI doesn't output correct lint severity
  • remove annotatedNodes from initialize function / SidecarBase

Define a glob filter from within LintRule

A lint rule should default to one of the following:

a) inherit the includes glob of the sidecar config, or
b) inherit the includes globs defined for the lint itself (in the projects yaml file), or
c) have a LintRule-specific default

The order of which the globs should be applied should be dependent on the following definition order:

Lint-Explicit > Lint-Default > Package-Explicit > Package-Default > Sidecar-Explicit > Sidecar-Default

abstract class LintRule {
  const LintRule([this.includesFromConfiguration]);
  final List<Glob>? includesFromConfiguration;
  ...

  List<Glob> get includes(String path) => includesFromConfiguration ?? [Glob('bin/**'), Glob('lib/**')];

}

During plugin initialization phase:

void init() {
  
  for (final lintBuilder in lintBuilders) {
    final packageConfig; // config comes from either a) project's sidecar.yaml OR b) the lint-package's definitions
    final lint = lintBuilder(packageConfig);
    allLints.add(lint);
  }

}

During handleAnalysis phase:

for (final lint in lints) {
  
  if (lint.includes.any((glob) => glob.matches(analysisFilePath))) {
    // lint is analyzed
  }

}

Evaluate Utility/Lint versioning strategy

for a riverpod package version 2.0.0

utils package: riverpod_analyzer v2.0.0
lints package: riverpod_lints v0.1.0 (i.e. version doesnt need to match 2.0.0, we can version it independently of the actual package version)

  • create a dart-based utility package
  • create a flutter based utility package

Differentiate Analyzed AstNode vs Highlighted AstNode

example: riverpod_prefer_consumer_widget

The Analyzed and Reported AstNode should be the ClassDeclaration, but the highlighted node would be better served as the class name (i.e. Highlighted AstNode = SimpleIdentifier) or the extended superclass (i.e. Highlighted AstNode = Identifier).

We need to expose a separate method for the LintError class that allows subclasses to declare which node should be highlighted.

Proposal PoC Bugs, Tasks, Notes

  • CLI init function should use dart CLI to add plugin to pubspec (adding a string is too fragile, caused a single-event bug)
  • Init function should add a default lint to the analysis_options file for better DX
  • Write up explaining architecture
  • Validate lints and code edits work in all appropriate scenarios to demonstrate functionality

[Performance] Sidecar CLI analysis is slower than Dart CLI

Since the main objective of Sidecar was to have enhanced performance, it makes sense to solve the obvious quality-related performance issues before getting feedback - otherwise, users will be confused by the value proposition.

Runtime Enhancements:

  • All files are attempted to be resolved before we check if the file is included in any globs; when we calculate "analyzedFiles" for a context, we should only look at folders/subfolders that are permitted by the globs (i.e. look at folders, not individual files)

Logging - Replace current print strategy with Zones

We can use zones to control how printing is handled.

see this zone thread: https://twitter.com/rexthecoder/status/1585003704134299649?s=20&t=F33mFgvdpg6WB2K-tKHkZQ

This would be useful for the following reasons:

  • being able to use log() (from developer package) would clean up a lot of the code throughout the project
  • users would be able to use print or log to output to debugger

Log Zones

  • ISOLATE
  • MIDDLEMAN
  • [RULE-ID]

Log Framework

  • DateTime
  • Zone
  • Function
  • Data/Message/etc.
  • [error, stackTrace]

LintRule - Design a debugging and logging workflow

This would probably best be paired with eventual CLI functionality, to run a lint or code edit.

LintRule debugger

  • Basic Lint debugger

Hot Reload

  • Hot reload on LintRule or CodeEdit changes
  • Hot reload on target source code changes

Code Edit feature

  • Create a Code Edit class for declarations to extend
  • Create bootstrapper that builds based off of analysis_options.yaml configuration

Package TypeChecker generator

  • Generate TypeChecker classes
  • Relative file paths of generated package match file paths of package
  • Generate type checkers via sidecar CLI

Consider using namespace prefixes for lint and fix names

it's possible for there to be many varying and conflicting implementations of a certain lint name. For example, avoid_string_literals could be avoiding strings for any reason.

Instead of having lint/fix developers compete for lint names, or in lieu of arguing what the "proper definitions" of each lint could or should be, itd be much more reasonable to give lints and fixes namespace prefixes to avoid conflicts.

For example:

  • riverpod::prefer_consumer_widget
  • dart::prefer_adjacent_string_concatenation
  • flutter::use_full_hex_values_for_flutter_colors

Open Questions:

  • what should be the name of the package (with or without namespace)
  • name of the LintError.code (with or without namespace)
  • name of the lint in analysis file (with or without namespace)
  • name of the defined Lint/Fix class (with or without namespace)

Lint-based pubspec file

Proposed pubspec file format:

name: riverpod_avoid_stateful_widgets
publish_to: cloudsmith.io/riverpod
version: 0.1.0
micropub: sidecar

environment:
  sdk: ">=2.17.5 <3.0.0"

sidecar:
  type: lint

dependencies:
  riverpod_lint_utils: 0.1.0
  sidecar: ^0.1.0

Sidecar Lints

Included lints for Sidecar

  • Code Assist to print AstNode info to code comment
  • Highlight Yaml files that dont conform to a certain lints' specifications

Use correct sidecar_analyzer_plugin package version for project

Utilize pub's dependency checking abilities to figure out what version of sidecar_analyzer_plugin should be used as the base plugin. Also use this to determine lint/fix versions.

We should also include a way to override this path with a local path, to help with development.

To do:

  • Break up sidecar_analyzer_plugin into 2 packages: 1 with only bootstrap functions, 1 with the rest of the implementations
  • Read package_config.json file and extract the desired plugin version number

Note: this version may change at any time over the course of the project.

It's probably best that the implementation code of sidecar_analyzer_plugin is separated into another package, so that the copied package does not have to be updated as frequently. This second package can be a simple interface of the plugin package.

Sidecar Configuration - error messages

Some errors are missing, while some other errors may be not descriptive enough.

analysis_options.yaml errors:

  • Lints: invalid 'severity' value (can only be 'warning', 'error', 'info'
  • Lints/Edits includes: invalid glob
  • Lints/Edits includes: invalid type (should be list of strings)
  • 'sidecar' includes: invalid glob

UX:

  • analysis_options.yaml errors should appear while typing (not just after saving file): unsaved file contents cannot be captured using file.readAsString(). Need to rethink how analysis option errors could be made visible.

Wont Do:

  • lint package could not be downloaded (unnecessary now that we use pub)
  • missing "sidecar" top level variable (highlight sidecar_analyzer_plugin under 'analyzer.plugin' section)

Allow Lints/Edits to be defined within Dart project directory

Users may want to create very project-specific lints or edits that wouldn't make sense to bundle up separately from the project itself. Therefore, defining lints/edits within the project directory is necessary to make defining project-specific rules as simple as possible.

Requirements:

  • a way to define from-path plugin dependencies

Lint Configurations and Configuration Errors

lint configurations:

  • allow lints to specify a configuration
  • rethink if lint configurations need to explicitly be under 'configuration' key

lint configuration errors:

  • instead of killing entire plugin, a bad lint/edit configuration should throw an analysis_options error (should these errors be logged or show up visually in IDE?)
  • Lints/Edits: invalid configuration (can we specify what's invalid about it?)

[Refactor] LintError that analyzes non-Dart files

  • Explicitly separate LintRule (configuration) from DetectedLint (instance)
  • Restructure ErrorReporter to generate lints
  • Move parse-based-on-file logic into LintRule class
  • Add Yaml parse utilities for converting to source spans

API Cleanup tasks

LintRule/CodeEdits:

  • Merge LintRule and CodeEdit into one class
  • Merge CodeEdit/LintRule bootstrappers
  • Create new CodeCorrection class for defining source changes
  • Switch includes globs to excludes

Visitor:

  • SidecarVisitor

v0.1.0 Refactor

  • Sidecar runs directly from pub cache (no external package needed)
  • Sidecar entrypoint should be created in .dart_tool directory
  • Sidecar can run directly from a lint package (i.e. sidecar doesnt need to be a direct dev-dependency)
  • Configuration is defined in sidecar.yaml rather than analysis_options.config (due to plugin shutdown when the latter is edited)
  • Move Analysis Error reporting to a separate provider
  • Fix sidecar.yaml generic configuration errors
  • Fix CLI reporting
  • Combine middleman_plugin and server into one entity

Lints/Fixes individual yaml configurations

Lint / fixes should be responsible for declaring their own configurations, by declaring it when extending LintError or QuickFix .

  • optional config parameters
  • required config parameters (causes error to appear in analysis options file)

Run Sequence of CodeEdits from CLI

Similar to CLI scripts, a user could run any sequence of CodeEdits from the CLI (including prompts for missing arguments). This would work similarly to dart fix.

For example, users installing the intl and flutter_localizations packages will need to follow a series of steps in order to use generated translations. Instead of following a guide step-by-step, a user could instead run a command from the CLI that guides them through the install process.

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.