<commit_before>use num::Integer;
use std::marker::PhantomData;
use std::mem;

pub trait Topological: Sized {
    type Vertex: Clone;
}

pub trait Polygonal: Topological {}

pub trait MapGeometry<T, U>: Topological<Vertex = T>
where
    T: Clone,
    U: Clone,
{
    type Output: Topological<Vertex = U>;

    fn map_geometry<F>(self, f: F) -> Self::Output
    where
        F: FnMut(T) -> U;
}

pub trait MapVertices<T, U>: Sized
where
    T: Clone,
    U: Clone,
{
    fn map_vertices<F>(self, f: F) -> Map<Self, T, U, F>
    where
        F: FnMut(T) -> U;
}

pub trait Rotate {
    fn rotate(&mut self, n: isize);
}

impl<I, T, U, P, Q> MapVertices<T, U> for I
where
    I: Iterator<Item = P>,
    P: MapGeometry<T, U, Output = Q>,
    Q: Topological<Vertex = U>,
    T: Clone,
    U: Clone,
{
    fn map_vertices<F>(self, f: F) -> Map<Self, T, U, F>
    where
        F: FnMut(T) -> U,
    {
        Map::new(self, f)
    }
}

pub struct Map<I, T, U, F> {
    topologies: I,
    f: F,
    phantom: PhantomData<(T, U)>,
}

impl<I, T, U, F> Map<I, T, U, F> {
    fn new(topologies: I, f: F) -> Self {
        Map {
            topologies: topologies,
            f: f,
            phantom: PhantomData,
        }
    }
}

impl<I, T, U, F, P, Q> Iterator for Map<I, T, U, F>
where
    I: Iterator<Item = P>,
    F: FnMut(T) -> U,
    P: MapGeometry<T, U, Output = Q>,
    Q: Topological<Vertex = U>,
    T: Clone,
    U: Clone,
{
    type Item = Q;

    fn next(&mut self) -> Option<Self::Item> {
        self.topologies
            .next()
            .map(|topology| topology.map_geometry(&mut self.f))
    }
}

pub struct Line<T> {
    pub a: T,
    pub b: T,
}

impl<T> Line<T> {
    pub fn new(a: T, b: T) -> Self {
        Line { a: a, b: b }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Line::new(value.clone(), value)
    }
}

impl<T, U> MapGeometry<T, U> for Line<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Line<U>;

    fn map_geometry<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Line { a, b } = self;
        Line::new(f(a), f(b))
    }
}

impl<T> Topological for Line<T>
where
    T: Clone,
{
    type Vertex = T;
}

impl<T> Rotate for Line<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        if n % 2 != 0 {
            mem::swap(&mut self.a, &mut self.b);
        }
    }
}

pub struct Triangle<T> {
    pub a: T,
    pub b: T,
    pub c: T,
}

impl<T> Triangle<T> {
    pub fn new(a: T, b: T, c: T) -> Self {
        Triangle { a: a, b: b, c: c }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Triangle::new(value.clone(), value.clone(), value)
    }
}

impl<T, U> MapGeometry<T, U> for Triangle<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Triangle<U>;

    fn map_geometry<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Triangle { a, b, c } = self;
        Triangle::new(f(a), f(b), f(c))
    }
}

impl<T> Topological for Triangle<T>
where
    T: Clone,
{
    type Vertex = T;
}

impl<T> Polygonal for Triangle<T>
where
    T: Clone,
{
}

impl<T> Rotate for Triangle<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        let n = umod(n, 3);
        if n == 1 {
            mem::swap(&mut self.a, &mut self.b);
            mem::swap(&mut self.b, &mut self.c);
        }
        else if n == 2 {
            mem::swap(&mut self.c, &mut self.b);
            mem::swap(&mut self.b, &mut self.a);
        }
    }
}

pub struct Quad<T> {
    pub a: T,
    pub b: T,
    pub c: T,
    pub d: T,
}

impl<T> Quad<T> {
    pub fn new(a: T, b: T, c: T, d: T) -> Self {
        Quad {
            a: a,
            b: b,
            c: c,
            d: d,
        }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Quad::new(value.clone(), value.clone(), value.clone(), value)
    }
}

impl<T, U> MapGeometry<T, U> for Quad<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Quad<U>;

    fn map_geometry<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Quad { a, b, c, d } = self;
        Quad::new(f(a), f(b), f(c), f(d))
    }
}

impl<T> Topological for Quad<T>
where
    T: Clone,
{
    type Vertex = T;
}

impl<T> Polygonal for Quad<T>
where
    T: Clone,
{
}

impl<T> Rotate for Quad<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        let n = umod(n, 4);
        if n == 1 {
            mem::swap(&mut self.a, &mut self.b);
            mem::swap(&mut self.b, &mut self.c);
            mem::swap(&mut self.c, &mut self.d);
        }
        else if n == 2 {
            mem::swap(&mut self.a, &mut self.c);
            mem::swap(&mut self.b, &mut self.d);
        }
        else if n == 3 {
            mem::swap(&mut self.d, &mut self.c);
            mem::swap(&mut self.c, &mut self.b);
            mem::swap(&mut self.b, &mut self.a);
        }
    }
}

pub enum Polygon<T> {
    Triangle(Triangle<T>),
    Quad(Quad<T>),
}

impl<T> From<Triangle<T>> for Polygon<T> {
    fn from(triangle: Triangle<T>) -> Self {
        Polygon::Triangle(triangle)
    }
}

impl<T> From<Quad<T>> for Polygon<T> {
    fn from(quad: Quad<T>) -> Self {
        Polygon::Quad(quad)
    }
}

impl<T, U> MapGeometry<T, U> for Polygon<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Polygon<U>;

    fn map_geometry<F>(self, f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        match self {
            Polygon::Triangle(triangle) => Polygon::Triangle(triangle.map_geometry(f)),
            Polygon::Quad(quad) => Polygon::Quad(quad.map_geometry(f)),
        }
    }
}

impl<T> Topological for Polygon<T>
where
    T: Clone,
{
    type Vertex = T;
}

impl<T> Polygonal for Polygon<T>
where
    T: Clone,
{
}

impl<T> Rotate for Polygon<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        match *self {
            Polygon::Triangle(ref mut triangle) => triangle.rotate(n),
            Polygon::Quad(ref mut quad) => quad.rotate(n),
        }
    }
}

fn umod<T>(n: T, m: T) -> T
where
    T: Copy + Integer,
{
    ((n % m) + m) % m
}
<commit_msg>Rename `topologies` to `input` to match other iterators.<commit_after>use num::Integer;
use std::marker::PhantomData;
use std::mem;

pub trait Topological: Sized {
    type Vertex: Clone;
}

pub trait Polygonal: Topological {}

pub trait MapGeometry<T, U>: Topological<Vertex = T>
where
    T: Clone,
    U: Clone,
{
    type Output: Topological<Vertex = U>;

    fn map_geometry<F>(self, f: F) -> Self::Output
    where
        F: FnMut(T) -> U;
}

pub trait MapVertices<T, U>: Sized
where
    T: Clone,
    U: Clone,
{
    fn map_vertices<F>(self, f: F) -> Map<Self, T, U, F>
    where
        F: FnMut(T) -> U;
}

pub trait Rotate {
    fn rotate(&mut self, n: isize);
}

impl<I, T, U, P, Q> MapVertices<T, U> for I
where
    I: Iterator<Item = P>,
    P: MapGeometry<T, U, Output = Q>,
    Q: Topological<Vertex = U>,
    T: Clone,
    U: Clone,
{
    fn map_vertices<F>(self, f: F) -> Map<Self, T, U, F>
    where
        F: FnMut(T) -> U,
    {
        Map::new(self, f)
    }
}

pub struct Map<I, T, U, F> {
    input: I,
    f: F,
    phantom: PhantomData<(T, U)>,
}

impl<I, T, U, F> Map<I, T, U, F> {
    fn new(input: I, f: F) -> Self {
        Map {
            input: input,
            f: f,
            phantom: PhantomData,
        }
    }
}

impl<I, T, U, F, P, Q> Iterator for Map<I, T, U, F>
where
    I: Iterator<Item = P>,
    F: FnMut(T) -> U,
    P: MapGeometry<T, U, Output = Q>,
    Q: Topological<Vertex = U>,
    T: Clone,
    U: Clone,
{
    type Item = Q;

    fn next(&mut self) -> Option<Self::Item> {
        self.input
            .next()
            .map(|topology| topology.map_geometry(&mut self.f))
    }
}

pub struct Line<T> {
    pub a: T,
    pub b: T,
}

impl<T> Line<T> {
    pub fn new(a: T, b: T) -> Self {
        Line { a: a, b: b }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Line::new(value.clone(), value)
    }
}

impl<T, U> MapGeometry<T, U> for Line<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Line<U>;

    fn map_geometry<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Line { a, b } = self;
        Line::new(f(a), f(b))
    }
}

impl<T> Topological for Line<T>
where
    T: Clone,
{
    type Vertex = T;
}

impl<T> Rotate for Line<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        if n % 2 != 0 {
            mem::swap(&mut self.a, &mut self.b);
        }
    }
}

pub struct Triangle<T> {
    pub a: T,
    pub b: T,
    pub c: T,
}

impl<T> Triangle<T> {
    pub fn new(a: T, b: T, c: T) -> Self {
        Triangle { a: a, b: b, c: c }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Triangle::new(value.clone(), value.clone(), value)
    }
}

impl<T, U> MapGeometry<T, U> for Triangle<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Triangle<U>;

    fn map_geometry<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Triangle { a, b, c } = self;
        Triangle::new(f(a), f(b), f(c))
    }
}

impl<T> Topological for Triangle<T>
where
    T: Clone,
{
    type Vertex = T;
}

impl<T> Polygonal for Triangle<T>
where
    T: Clone,
{
}

impl<T> Rotate for Triangle<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        let n = umod(n, 3);
        if n == 1 {
            mem::swap(&mut self.a, &mut self.b);
            mem::swap(&mut self.b, &mut self.c);
        }
        else if n == 2 {
            mem::swap(&mut self.c, &mut self.b);
            mem::swap(&mut self.b, &mut self.a);
        }
    }
}

pub struct Quad<T> {
    pub a: T,
    pub b: T,
    pub c: T,
    pub d: T,
}

impl<T> Quad<T> {
    pub fn new(a: T, b: T, c: T, d: T) -> Self {
        Quad {
            a: a,
            b: b,
            c: c,
            d: d,
        }
    }

    pub fn converged(value: T) -> Self
    where
        T: Clone,
    {
        Quad::new(value.clone(), value.clone(), value.clone(), value)
    }
}

impl<T, U> MapGeometry<T, U> for Quad<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Quad<U>;

    fn map_geometry<F>(self, mut f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        let Quad { a, b, c, d } = self;
        Quad::new(f(a), f(b), f(c), f(d))
    }
}

impl<T> Topological for Quad<T>
where
    T: Clone,
{
    type Vertex = T;
}

impl<T> Polygonal for Quad<T>
where
    T: Clone,
{
}

impl<T> Rotate for Quad<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        let n = umod(n, 4);
        if n == 1 {
            mem::swap(&mut self.a, &mut self.b);
            mem::swap(&mut self.b, &mut self.c);
            mem::swap(&mut self.c, &mut self.d);
        }
        else if n == 2 {
            mem::swap(&mut self.a, &mut self.c);
            mem::swap(&mut self.b, &mut self.d);
        }
        else if n == 3 {
            mem::swap(&mut self.d, &mut self.c);
            mem::swap(&mut self.c, &mut self.b);
            mem::swap(&mut self.b, &mut self.a);
        }
    }
}

pub enum Polygon<T> {
    Triangle(Triangle<T>),
    Quad(Quad<T>),
}

impl<T> From<Triangle<T>> for Polygon<T> {
    fn from(triangle: Triangle<T>) -> Self {
        Polygon::Triangle(triangle)
    }
}

impl<T> From<Quad<T>> for Polygon<T> {
    fn from(quad: Quad<T>) -> Self {
        Polygon::Quad(quad)
    }
}

impl<T, U> MapGeometry<T, U> for Polygon<T>
where
    T: Clone,
    U: Clone,
{
    type Output = Polygon<U>;

    fn map_geometry<F>(self, f: F) -> Self::Output
    where
        F: FnMut(T) -> U,
    {
        match self {
            Polygon::Triangle(triangle) => Polygon::Triangle(triangle.map_geometry(f)),
            Polygon::Quad(quad) => Polygon::Quad(quad.map_geometry(f)),
        }
    }
}

impl<T> Topological for Polygon<T>
where
    T: Clone,
{
    type Vertex = T;
}

impl<T> Polygonal for Polygon<T>
where
    T: Clone,
{
}

impl<T> Rotate for Polygon<T>
where
    T: Clone,
{
    fn rotate(&mut self, n: isize) {
        match *self {
            Polygon::Triangle(ref mut triangle) => triangle.rotate(n),
            Polygon::Quad(ref mut quad) => quad.rotate(n),
        }
    }
}

fn umod<T>(n: T, m: T) -> T
where
    T: Copy + Integer,
{
    ((n % m) + m) % m
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use lsp_types::request::Request;
use lsp_types::Position;
use lsp_types::TextDocumentIdentifier;
use lsp_types::TextDocumentPositionParams;
use lsp_types::Url;
use schema::Schema;
use serde::Deserialize;
use serde::Serialize;

use crate::lsp_runtime_error::LSPRuntimeError;
use crate::lsp_runtime_error::LSPRuntimeResult;
use crate::server::GlobalState;
use crate::FeatureResolutionInfo;

pub(crate) enum ResolvedTypesAtLocation {}

#[derive(Deserialize, Serialize)]
pub(crate) struct ResolvedTypesAtLocationParams {
    file_name: String,
    line: u32,
    character: u32,
}

impl ResolvedTypesAtLocationParams {
    fn to_text_document_position_params(&self) -> LSPRuntimeResult<TextDocumentPositionParams> {
        Ok(TextDocumentPositionParams {
            text_document: TextDocumentIdentifier {
                uri: Url::parse(&self.file_name).map_err(|_| LSPRuntimeError::ExpectedError)?,
            },
            position: Position {
                character: self.character,
                line: self.line,
            },
        })
    }
}

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct ResolvedTypesAtLocationResponse {
    pub path_and_schema_name: Option<PathAndSchemaName>,
}

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct PathAndSchemaName {
    pub path: Vec<String>,
    pub schema_name: String,
}

impl Request for ResolvedTypesAtLocation {
    type Params = ResolvedTypesAtLocationParams;
    type Result = ResolvedTypesAtLocationResponse;
    const METHOD: &'static str = "relay/getResolvedTypesAtLocation";
}

pub(crate) fn on_get_resolved_types_at_location(
    state: &impl GlobalState,
    params: <ResolvedTypesAtLocation as Request>::Params,
) -> LSPRuntimeResult<<ResolvedTypesAtLocation as Request>::Result> {
    let params = params.to_text_document_position_params()?;
    if let Ok(feature_resolution_info) = state.resolve_node(&params) {
        let project_name = state.extract_project_name_from_url(&params.text_document.uri)?;
        let schema = state.get_schema(&project_name)?;

        match feature_resolution_info {
            FeatureResolutionInfo::GraphqlNode(node_resolution_info) => {
                // If type_path is empty, type_path.resolve_current_field() will panic.
                if !node_resolution_info.type_path.0.is_empty() {
                    let type_and_field = node_resolution_info
                        .type_path
                        .resolve_current_field(&schema);
                    if let Some((_parent_type, field)) = type_and_field {
                        let type_name = schema.get_type_name(field.type_.inner()).to_string();
                        // TODO resolve enclosing types, not just types immediately under the cursor
                        return Ok(ResolvedTypesAtLocationResponse {
                            path_and_schema_name: Some(PathAndSchemaName {
                                path: vec![type_name],
                                schema_name: project_name.to_string(),
                            }),
                        });
                    }
                }
            }
            FeatureResolutionInfo::DocblockNode(_) => {
                // Get types at location not implemented for docblocks yet.
                return Ok(ResolvedTypesAtLocationResponse {
                    path_and_schema_name: None,
                });
            }
        }
    }

    Ok(ResolvedTypesAtLocationResponse {
        path_and_schema_name: None,
    })
}
<commit_msg>Fix schema name resolution<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use lsp_types::request::Request;
use lsp_types::Position;
use lsp_types::TextDocumentIdentifier;
use lsp_types::TextDocumentPositionParams;
use lsp_types::Url;
use schema::Schema;
use serde::Deserialize;
use serde::Serialize;

use crate::lsp_runtime_error::LSPRuntimeError;
use crate::lsp_runtime_error::LSPRuntimeResult;
use crate::server::GlobalState;
use crate::FeatureResolutionInfo;

pub(crate) enum ResolvedTypesAtLocation {}

#[derive(Deserialize, Serialize)]
pub(crate) struct ResolvedTypesAtLocationParams {
    file_name: String,
    line: u32,
    character: u32,
}

impl ResolvedTypesAtLocationParams {
    fn to_text_document_position_params(&self) -> LSPRuntimeResult<TextDocumentPositionParams> {
        Ok(TextDocumentPositionParams {
            text_document: TextDocumentIdentifier {
                uri: Url::parse(&self.file_name).map_err(|_| LSPRuntimeError::ExpectedError)?,
            },
            position: Position {
                character: self.character,
                line: self.line,
            },
        })
    }
}

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct ResolvedTypesAtLocationResponse {
    pub path_and_schema_name: PathAndSchemaName,
}

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct PathAndSchemaName {
    pub path: Vec<String>,
    pub schema_name: String,
}

impl Request for ResolvedTypesAtLocation {
    type Params = ResolvedTypesAtLocationParams;
    type Result = ResolvedTypesAtLocationResponse;
    const METHOD: &'static str = "relay/getResolvedTypesAtLocation";
}

pub(crate) fn on_get_resolved_types_at_location(
    state: &impl GlobalState,
    params: <ResolvedTypesAtLocation as Request>::Params,
) -> LSPRuntimeResult<<ResolvedTypesAtLocation as Request>::Result> {
    let params = params.to_text_document_position_params()?;
    let project_name = state.extract_project_name_from_url(&params.text_document.uri)?;
    let schema = state.get_schema(&project_name)?;
    let schema_name = project_name.to_string();

    if let Ok(feature_resolution_info) = state.resolve_node(&params) {
        match feature_resolution_info {
            FeatureResolutionInfo::GraphqlNode(node_resolution_info) => {
                // If type_path is empty, type_path.resolve_current_field() will panic.
                if !node_resolution_info.type_path.0.is_empty() {
                    let type_and_field = node_resolution_info
                        .type_path
                        .resolve_current_field(&schema);
                    if let Some((_parent_type, field)) = type_and_field {
                        let type_name = schema.get_type_name(field.type_.inner()).to_string();
                        // TODO resolve enclosing types, not just types immediately under the cursor
                        return Ok(ResolvedTypesAtLocationResponse {
                            path_and_schema_name: PathAndSchemaName {
                                path: vec![type_name],
                                schema_name,
                            },
                        });
                    }
                }
            }
            FeatureResolutionInfo::DocblockNode(_) => {
                // Get types at location not implemented for docblocks yet.
                return Ok(ResolvedTypesAtLocationResponse {
                    path_and_schema_name: PathAndSchemaName {
                        path: Vec::default(),
                        schema_name,
                    },
                });
            }
        }
    }

    Ok(ResolvedTypesAtLocationResponse {
        path_and_schema_name: PathAndSchemaName {
            path: Vec::default(),
            schema_name,
        },
    })
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Architecture-specific memory management.
use ::{Addr, Page};

use core::{fmt, ops, mem};

pub const PAGE_SHIFT: u8 = 12;
/// The size of a page (4KiB), in bytes
pub const PAGE_SIZE: u64 = 1 << PAGE_SHIFT; // 4k
/// The size of a large page (2MiB) in bytes
pub const LARGE_PAGE_SIZE: u64 = 1024 * 1024 * 2;
/// The size of a huge page (2GiB) in bytes
pub const HUGE_PAGE_SIZE: u64 = 1024 * 1024 * 1024;

macro_attr! {
    /// A physical (linear) memory address is a 64-bit unsigned integer
    #[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Addr!(u64))]
    #[repr(C)]
    pub struct PAddr(u64);
}

macro_attr! {
    /// A frame (physical page)
    //  TODO: consider renaming this to `Frame` (less typing)?
    //      - eliza, 2/28/2017
    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Page!(PAddr) )]
    pub struct PhysicalPage { pub number: u64 }
}
impl fmt::Debug for PhysicalPage {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "frame #{}", self.number)
    }
}

impl ops::Add<usize> for PhysicalPage {
    type Output = Self;

    #[inline] fn add(self, rhs: usize) -> Self {
        PhysicalPage { number: self.number +  rhs as u64 }
    }
}

impl ops::Sub<usize> for PhysicalPage {
    type Output = Self;

    #[inline] fn sub(self, rhs: usize) -> Self {
        PhysicalPage { number: self.number -  rhs as u64 }
    }
}

impl ops::AddAssign<usize> for PhysicalPage {
    #[inline] fn add_assign(&mut self, rhs: usize) {
        self.number += rhs as u64;
    }
}

impl ops::SubAssign<usize> for PhysicalPage {
    #[inline] fn sub_assign(&mut self, rhs: usize) {
        self.number -= rhs as u64;
    }
}

impl PhysicalPage {

    /// Returns the physical address where this frame starts.
    #[inline]
    pub const fn base_addr(&self) -> PAddr {
        PAddr(self.number << PAGE_SHIFT)
    }

    /// Returns a new frame containing `addr`
    #[inline]
    pub const fn containing_addr(addr: PAddr) -> PhysicalPage {
        PhysicalPage { number: addr.0 >> PAGE_SHIFT }
    }

    /// Convert the frame into a raw pointer to the frame's base address
    #[inline]
    pub unsafe fn as_ptr<T>(&self) -> *const T {
        mem::transmute(self.base_addr())
    }

    /// Convert the frame into a raw mutable pointer to the frame's base address
    #[inline]
    pub unsafe fn as_mut_ptr<T>(&self) -> *mut T {
        *self.base_addr() as *mut u8 as *mut T
    }

}
<commit_msg>feat(memory::x86_64::PhysicalPage): nicer frame debug messages<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Architecture-specific memory management.
use ::{Addr, Page};

use core::{fmt, ops, mem};

pub const PAGE_SHIFT: u8 = 12;
/// The size of a page (4KiB), in bytes
pub const PAGE_SIZE: u64 = 1 << PAGE_SHIFT; // 4k
/// The size of a large page (2MiB) in bytes
pub const LARGE_PAGE_SIZE: u64 = 1024 * 1024 * 2;
/// The size of a huge page (2GiB) in bytes
pub const HUGE_PAGE_SIZE: u64 = 1024 * 1024 * 1024;

macro_attr! {
    /// A physical (linear) memory address is a 64-bit unsigned integer
    #[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Addr!(u64))]
    #[repr(C)]
    pub struct PAddr(u64);
}

macro_attr! {
    /// A frame (physical page)
    //  TODO: consider renaming this to `Frame` (less typing)?
    //      - eliza, 2/28/2017
    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Page!(PAddr) )]
    pub struct PhysicalPage { pub number: u64 }
}
impl fmt::Debug for PhysicalPage {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "frame #{} at {:#p}", self.number, self.base_addr())
    }
}

impl ops::Add<usize> for PhysicalPage {
    type Output = Self;

    #[inline] fn add(self, rhs: usize) -> Self {
        PhysicalPage { number: self.number +  rhs as u64 }
    }
}

impl ops::Sub<usize> for PhysicalPage {
    type Output = Self;

    #[inline] fn sub(self, rhs: usize) -> Self {
        PhysicalPage { number: self.number -  rhs as u64 }
    }
}

impl ops::AddAssign<usize> for PhysicalPage {
    #[inline] fn add_assign(&mut self, rhs: usize) {
        self.number += rhs as u64;
    }
}

impl ops::SubAssign<usize> for PhysicalPage {
    #[inline] fn sub_assign(&mut self, rhs: usize) {
        self.number -= rhs as u64;
    }
}

impl PhysicalPage {

    /// Returns the physical address where this frame starts.
    #[inline]
    pub const fn base_addr(&self) -> PAddr {
        PAddr(self.number << PAGE_SHIFT)
    }

    /// Returns a new frame containing `addr`
    #[inline]
    pub const fn containing_addr(addr: PAddr) -> PhysicalPage {
        PhysicalPage { number: addr.0 >> PAGE_SHIFT }
    }

    /// Convert the frame into a raw pointer to the frame's base address
    #[inline]
    pub unsafe fn as_ptr<T>(&self) -> *const T {
        mem::transmute(self.base_addr())
    }

    /// Convert the frame into a raw mutable pointer to the frame's base address
    #[inline]
    pub unsafe fn as_mut_ptr<T>(&self) -> *mut T {
        *self.base_addr() as *mut u8 as *mut T
    }

}
<|endoftext|>


<commit_before>// "Tifflin" Kernel
// - By John Hodge (thePowersGang)
//
// Modules/video_vgs/mod.rs
// - VGA (and derivative) device driver
//
#![feature(no_std,core)]
#![feature(box_syntax)]
#![no_std]
use kernel::prelude::*;
#[macro_use] extern crate kernel;
#[macro_use] extern crate core;
mod std {
	pub use core::fmt;	// write!
	pub use core::option;	// for loops
	pub use core::iter;	// for loops
}

use kernel::metadevs::video::{Framebuffer,Rect,Dims};
use kernel::device_manager;
use kernel::metadevs::video;

module_define!{VGA, [DeviceManager, Video], init}

mod crtc;

/// Driver object for the PCI
struct VgaPciDriver;

struct VgaDevice
{
	/// Handle to video metadev registration
	_video_handle: video::FramebufferRegistration,
}
/**
 * Real device instance (registered with the video manager)
 */
struct VgaFramebuffer
{
	io_base: u16,
	window: ::kernel::memory::virt::AllocHandle,
	crtc: crtc::CrtcRegs,
	w: u16,
	h: u16,
}
/// CRT Controller attributes (signal format)
struct CrtcAttrs
{
	frequency: u16,
	h_front_porch: u16,
	h_active: u16,
	h_back_porch: u16,
	h_sync_len: u16,

	v_front_porch: u16,
	v_active: u16,
	v_back_porch: u16,
	v_sync_len: u16,
}

#[allow(non_upper_case_globals)]
static s_vga_pci_driver: VgaPciDriver = VgaPciDriver;
#[allow(non_upper_case_globals)]
static s_legacy_bound: ::core::atomic::AtomicBool = ::core::atomic::ATOMIC_BOOL_INIT;

fn init()
{
	// 1. Register Driver
	//device_manager::register_driver(&s_vga_pci_driver);
}

impl device_manager::Driver for VgaPciDriver
{
	fn name(&self) -> &str {
		"vga"
	}
	fn bus_type(&self) -> &str {
		"pci"
	}
	fn handles(&self, bus_dev: &device_manager::BusDevice) -> u32
	{
		let classcode = bus_dev.get_attr("class");
		// [class] [subclass] [IF] [ver]
		if classcode & 0xFFFFFF00 == 0x03000000 {
			1	// Handle as weakly as possible (vendor-provided drivers bind higher)
		}
		else {
			0
		}
	}
	fn bind(&self, _bus_dev: &mut device_manager::BusDevice) -> Box<device_manager::DriverInstance+'static>
	{
		if s_legacy_bound.swap(true, ::core::atomic::Ordering::AcqRel)
		{
			panic!("Duplicate binding of legacy VGA");
		}
		box VgaDevice::new(0x3B0)
	}

}

impl VgaDevice
{
	fn new(iobase: u16) -> VgaDevice
	{
		VgaDevice {
			_video_handle: video::add_output(box VgaFramebuffer::new(iobase) ),
		}
	}
}

impl device_manager::DriverInstance for VgaDevice
{
}

impl VgaFramebuffer
{
	fn new(base: u16) -> VgaFramebuffer
	{
		log_debug!("Creating VGA driver at base {:#3x}", base);
		let mut rv = VgaFramebuffer {
			io_base: base,
			window: ::kernel::memory::virt::map_hw_rw(0xA0000, (0xC0-0xA0), module_path!()).unwrap(),
			crtc: crtc::CrtcRegs::load(base + 0x24),	// Colour CRTC regs
			w: 320,
			h: 240,
			};

		rv
	}

	fn set_crtc(&mut self, attrs: CrtcAttrs)
	{
		use self::crtc::PIX_PER_CHAR;
		self.crtc.set_line_compare(0);	// Entire screen is Screen B
		self.crtc.set_screen_start(0);	// Screen A starts at offset 0 (making A and B functionally equal)
		self.crtc.set_byte_pan(0);	// Byte pan = 0, no horizontal offset

		self.crtc.set_offset(attrs.h_active * 1);	// Aka pitch (TODO: Need the BPP setting)

		// Horizontal
		let h_total = (attrs.h_front_porch + attrs.h_active + attrs.h_back_porch) / PIX_PER_CHAR as u16;
		self.crtc.set_h_total(h_total);
		let h_disp_end = attrs.h_active / PIX_PER_CHAR as u16;
		self.crtc.set_h_disp_end(h_disp_end);
		self.crtc.set_h_blank_start(h_disp_end+1);	// Must be larger than h_disp_end
		let h_blank_len = (attrs.h_front_porch + attrs.h_back_porch) / PIX_PER_CHAR as u16;
		self.crtc.set_h_blank_len( h_blank_len );
		let h_sync_start = (attrs.h_active + attrs.h_front_porch) / PIX_PER_CHAR as u16;
		self.crtc.set_h_sync_start(h_sync_start);
		let h_sync_end = ((h_sync_start + attrs.h_sync_len) / PIX_PER_CHAR as u16) & 31;
		self.crtc.set_h_sync_end(h_sync_end);

		// Vertical
		let v_total = attrs.v_front_porch + attrs.v_active + attrs.v_back_porch;
		self.crtc.set_v_total(v_total);
		let v_disp_end = attrs.v_active;
		self.crtc.set_v_disp_end(v_disp_end);
		self.crtc.set_v_blank_start(v_disp_end+1);
		let v_blank_end = attrs.v_front_porch + attrs.v_back_porch;
		self.crtc.set_v_blank_end(v_blank_end);
		let v_sync_start = attrs.v_active + attrs.v_back_porch;
		self.crtc.set_v_sync_start(v_sync_start);
		let v_sync_end = (v_sync_start + attrs.v_sync_len) & 31;
		self.crtc.set_v_sync_end(v_sync_end);

		// Frequency
		// - Just leave as 25MHz (Clock Select = 0)

		self.crtc.commit(self.io_base + 0x24);

		panic!("TODO: Set/check firequency {}Hz", attrs.frequency);
	}

	fn col32_to_u8(&self, colour: u32) -> u8
	{
		// 8:8:8 RGB -> 2:3:3 RGB
		let r8 = (colour >> 16) as u8;
		let g8 = (colour >>  8) as u8;
		let b8 = (colour >>  0) as u8;

		let r2 = (r8 + 0x3F) >> (8-2);
		let g3 = (g8 + 0x1F) >> (8-3);
		let b3 = (b8 + 0x1F) >> (8-3);
		return (r2 << 6) | (g3 << 3) | (b3 << 0);
	}
}

impl CrtcAttrs
{
	pub fn from_res(w: u16, h: u16, freq: u16) -> CrtcAttrs
	{
		match (w,h,freq)
		{
		(640,480,60) => CrtcAttrs {
			frequency: 60,
			h_active: 640,
			h_front_porch: 16+96,	// sync overlaps with front porch
			h_sync_len: 96,
			h_back_porch: 48,
			v_active: 480,
			v_front_porch: 10+2,
			v_sync_len: 2,
			v_back_porch: 33,
			},
		_ => {
			panic!("TODO: Obtain CRTC attributes from resolution {}x{} at {}Hz", w, h, freq);
			}
		}
	}
}

impl video::Framebuffer for VgaFramebuffer
{
	fn as_any(&self) -> &Any {
		self as &Any
	}
	fn activate(&mut self) {
		// Don't modeset yet, wait until video manager tells us to initialise
		// 320x240 @ 60Hz
		self.set_crtc(CrtcAttrs::from_res(320, 240, 60));
	}

	fn get_size(&self) -> Dims {
		// 320x200x 8bpp
		Dims::new( self.w as u32, self.h as u32 )
	}
	fn set_size(&mut self, _newsize: Dims) -> bool {
		// Can't change
		false
	}

	fn blit_inner(&mut self, dst: Rect, src: Rect) {
		panic!("TODO: VGA blit_inner {} to {}", src, dst);
	}
	fn blit_ext(&mut self, dst: Rect, src: Rect, srf: &Framebuffer) -> bool {
		match srf.as_any().downcast_ref::<VgaFramebuffer>()
		{
		Some(_) => panic!("TODO: VGA blit_ext {} to  {}", src, dst),
		None => false,
		}
	}
	fn blit_buf(&mut self, dst: Rect, buf: &[u32]) {
		panic!("TODO: VGA blit_buf {} pixels to {}", buf.len(), dst);
	}
	fn fill(&mut self, dst: Rect, colour: u32) {
		assert!( dst.within(self.w as u32, self.h as u32) );
		let colour_val = self.col32_to_u8(colour);
		for row in dst.top() .. dst.bottom()
		{
			let scanline = self.window.as_mut_slice::<u8>( (row * self.w as u32) as usize, dst.w() as usize);
			for col in dst.left() .. dst.right()
			{
				scanline[col as usize] = colour_val;
			}
		}
	}
}

// vim: ft=rust

<commit_msg>Modules/VGA - (minor) Replace some explicit panics with todo!<commit_after>// "Tifflin" Kernel
// - By John Hodge (thePowersGang)
//
// Modules/video_vgs/mod.rs
// - VGA (and derivative) device driver
//
#![feature(no_std,core)]
#![feature(box_syntax)]
#![no_std]
use kernel::prelude::*;
#[macro_use] extern crate kernel;
#[macro_use] extern crate core;
mod std {
	pub use core::fmt;	// write!
	pub use core::option;	// for loops
	pub use core::iter;	// for loops
}

use kernel::metadevs::video::{Framebuffer,Rect,Dims};
use kernel::device_manager;
use kernel::metadevs::video;

module_define!{VGA, [DeviceManager, Video], init}

mod crtc;

/// Driver object for the PCI
struct VgaPciDriver;

struct VgaDevice
{
	/// Handle to video metadev registration
	_video_handle: video::FramebufferRegistration,
}
/**
 * Real device instance (registered with the video manager)
 */
struct VgaFramebuffer
{
	io_base: u16,
	window: ::kernel::memory::virt::AllocHandle,
	crtc: crtc::CrtcRegs,
	w: u16,
	h: u16,
}
/// CRT Controller attributes (signal format)
struct CrtcAttrs
{
	frequency: u16,
	h_front_porch: u16,
	h_active: u16,
	h_back_porch: u16,
	h_sync_len: u16,

	v_front_porch: u16,
	v_active: u16,
	v_back_porch: u16,
	v_sync_len: u16,
}

#[allow(non_upper_case_globals)]
static s_vga_pci_driver: VgaPciDriver = VgaPciDriver;
#[allow(non_upper_case_globals)]
static s_legacy_bound: ::core::atomic::AtomicBool = ::core::atomic::ATOMIC_BOOL_INIT;

fn init()
{
	// 1. Register Driver
	//device_manager::register_driver(&s_vga_pci_driver);
}

impl device_manager::Driver for VgaPciDriver
{
	fn name(&self) -> &str {
		"vga"
	}
	fn bus_type(&self) -> &str {
		"pci"
	}
	fn handles(&self, bus_dev: &device_manager::BusDevice) -> u32
	{
		let classcode = bus_dev.get_attr("class");
		// [class] [subclass] [IF] [ver]
		if classcode & 0xFFFFFF00 == 0x03000000 {
			1	// Handle as weakly as possible (vendor-provided drivers bind higher)
		}
		else {
			0
		}
	}
	fn bind(&self, _bus_dev: &mut device_manager::BusDevice) -> Box<device_manager::DriverInstance+'static>
	{
		if s_legacy_bound.swap(true, ::core::atomic::Ordering::AcqRel)
		{
			panic!("Duplicate binding of legacy VGA");
		}
		box VgaDevice::new(0x3B0)
	}

}

impl VgaDevice
{
	fn new(iobase: u16) -> VgaDevice
	{
		VgaDevice {
			_video_handle: video::add_output(box VgaFramebuffer::new(iobase) ),
		}
	}
}

impl device_manager::DriverInstance for VgaDevice
{
}

impl VgaFramebuffer
{
	fn new(base: u16) -> VgaFramebuffer
	{
		log_debug!("Creating VGA driver at base {:#3x}", base);
		let mut rv = VgaFramebuffer {
			io_base: base,
			window: ::kernel::memory::virt::map_hw_rw(0xA0000, (0xC0-0xA0), module_path!()).unwrap(),
			crtc: crtc::CrtcRegs::load(base + 0x24),	// Colour CRTC regs
			w: 320,
			h: 240,
			};

		rv
	}

	fn set_crtc(&mut self, attrs: CrtcAttrs)
	{
		use self::crtc::PIX_PER_CHAR;
		self.crtc.set_line_compare(0);	// Entire screen is Screen B
		self.crtc.set_screen_start(0);	// Screen A starts at offset 0 (making A and B functionally equal)
		self.crtc.set_byte_pan(0);	// Byte pan = 0, no horizontal offset

		self.crtc.set_offset(attrs.h_active * 1);	// Aka pitch (TODO: Need the BPP setting)

		// Horizontal
		let h_total = (attrs.h_front_porch + attrs.h_active + attrs.h_back_porch) / PIX_PER_CHAR as u16;
		self.crtc.set_h_total(h_total);
		let h_disp_end = attrs.h_active / PIX_PER_CHAR as u16;
		self.crtc.set_h_disp_end(h_disp_end);
		self.crtc.set_h_blank_start(h_disp_end+1);	// Must be larger than h_disp_end
		let h_blank_len = (attrs.h_front_porch + attrs.h_back_porch) / PIX_PER_CHAR as u16;
		self.crtc.set_h_blank_len( h_blank_len );
		let h_sync_start = (attrs.h_active + attrs.h_front_porch) / PIX_PER_CHAR as u16;
		self.crtc.set_h_sync_start(h_sync_start);
		let h_sync_end = ((h_sync_start + attrs.h_sync_len) / PIX_PER_CHAR as u16) & 31;
		self.crtc.set_h_sync_end(h_sync_end);

		// Vertical
		let v_total = attrs.v_front_porch + attrs.v_active + attrs.v_back_porch;
		self.crtc.set_v_total(v_total);
		let v_disp_end = attrs.v_active;
		self.crtc.set_v_disp_end(v_disp_end);
		self.crtc.set_v_blank_start(v_disp_end+1);
		let v_blank_end = attrs.v_front_porch + attrs.v_back_porch;
		self.crtc.set_v_blank_end(v_blank_end);
		let v_sync_start = attrs.v_active + attrs.v_back_porch;
		self.crtc.set_v_sync_start(v_sync_start);
		let v_sync_end = (v_sync_start + attrs.v_sync_len) & 31;
		self.crtc.set_v_sync_end(v_sync_end);

		// Frequency
		// - Just leave as 25MHz (Clock Select = 0)

		self.crtc.commit(self.io_base + 0x24);

		todo!("Set/check firequency {}Hz", attrs.frequency);
	}

	fn col32_to_u8(&self, colour: u32) -> u8
	{
		// 8:8:8 RGB -> 2:3:3 RGB
		let r8 = (colour >> 16) as u8;
		let g8 = (colour >>  8) as u8;
		let b8 = (colour >>  0) as u8;

		let r2 = (r8 + 0x3F) >> (8-2);
		let g3 = (g8 + 0x1F) >> (8-3);
		let b3 = (b8 + 0x1F) >> (8-3);
		return (r2 << 6) | (g3 << 3) | (b3 << 0);
	}
}

impl CrtcAttrs
{
	pub fn from_res(w: u16, h: u16, freq: u16) -> CrtcAttrs
	{
		match (w,h,freq)
		{
		(640,480,60) => CrtcAttrs {
			frequency: 60,
			h_active: 640,
			h_front_porch: 16+96,	// sync overlaps with front porch
			h_sync_len: 96,
			h_back_porch: 48,
			v_active: 480,
			v_front_porch: 10+2,
			v_sync_len: 2,
			v_back_porch: 33,
			},
		_ => {
			todo!("Obtain CRTC attributes from resolution {}x{} at {}Hz", w, h, freq);
			}
		}
	}
}

impl video::Framebuffer for VgaFramebuffer
{
	fn as_any(&self) -> &Any {
		self as &Any
	}
	fn activate(&mut self) {
		// Don't modeset yet, wait until video manager tells us to initialise
		// 320x240 @ 60Hz
		self.set_crtc(CrtcAttrs::from_res(320, 240, 60));
	}

	fn get_size(&self) -> Dims {
		// 320x200x 8bpp
		Dims::new( self.w as u32, self.h as u32 )
	}
	fn set_size(&mut self, _newsize: Dims) -> bool {
		// Can't change
		false
	}

	fn blit_inner(&mut self, dst: Rect, src: Rect) {
		todo!("VGA blit_inner {} to {}", src, dst);
	}
	fn blit_ext(&mut self, dst: Rect, src: Rect, srf: &Framebuffer) -> bool {
		match srf.as_any().downcast_ref::<VgaFramebuffer>()
		{
		Some(_) => todo!("VGA blit_ext {} to  {}", src, dst),
		None => false,
		}
	}
	fn blit_buf(&mut self, dst: Rect, buf: &[u32]) {
		todo!("VGA blit_buf {} pixels to {}", buf.len(), dst);
	}
	fn fill(&mut self, dst: Rect, colour: u32) {
		assert!( dst.within(self.w as u32, self.h as u32) );
		let colour_val = self.col32_to_u8(colour);
		for row in dst.top() .. dst.bottom()
		{
			let scanline = self.window.as_mut_slice::<u8>( (row * self.w as u32) as usize, dst.w() as usize);
			for col in dst.left() .. dst.right()
			{
				scanline[col as usize] = colour_val;
			}
		}
	}
}

// vim: ft=rust

<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) getpriority execvp setpriority nstr PRIO cstrs ENOENT

#[macro_use]
extern crate uucore;

use libc::{c_char, c_int, execvp};
use std::ffi::CString;
use std::io::Error;
use std::ptr;

use clap::{crate_version, App, AppSettings, Arg};

// XXX: PRIO_PROCESS is 0 on at least FreeBSD and Linux.  Don't know about Mac OS X.
const PRIO_PROCESS: c_int = 0;

extern "C" {
    fn getpriority(which: c_int, who: c_int) -> c_int;
    fn setpriority(which: c_int, who: c_int, prio: c_int) -> c_int;
}

pub mod options {
    pub static ADJUSTMENT: &str = "adjustment";
    pub static COMMAND: &str = "COMMAND";
}

fn get_usage() -> String {
    format!(
        "
  {0} [OPTIONS] [COMMAND [ARGS]]

Run COMMAND with an adjusted niceness, which affects process scheduling.
With no COMMAND, print the current niceness.  Niceness values range from at
least -20 (most favorable to the process) to 19 (least favorable to the
process).",
        executable!()
    )
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    let mut niceness = unsafe {
        nix::errno::Errno::clear();
        getpriority(PRIO_PROCESS, 0)
    };
    if Error::last_os_error().raw_os_error().unwrap() != 0 {
        show_error!("getpriority: {}", Error::last_os_error());
        return 125;
    }

    let adjustment = match matches.value_of(options::ADJUSTMENT) {
        Some(nstr) => {
            if !matches.is_present(options::COMMAND) {
                show_error!(
                    "A command must be given with an adjustment.\nTry \"{} --help\" for more information.",
                    executable!()
                );
                return 125;
            }
            match nstr.parse() {
                Ok(num) => num,
                Err(e) => {
                    show_error!("\"{}\" is not a valid number: {}", nstr, e);
                    return 125;
                }
            }
        }
        None => {
            if !matches.is_present(options::COMMAND) {
                println!("{}", niceness);
                return 0;
            }
            10_i32
        }
    };

    niceness += adjustment;
    if unsafe { setpriority(PRIO_PROCESS, 0, niceness) } == -1 {
        show_warning!("setpriority: {}", Error::last_os_error());
    }

    let cstrs: Vec<CString> = matches
        .values_of(options::COMMAND)
        .unwrap()
        .map(|x| CString::new(x.as_bytes()).unwrap())
        .collect();

    let mut args: Vec<*const c_char> = cstrs.iter().map(|s| s.as_ptr()).collect();
    args.push(ptr::null::<c_char>());
    unsafe {
        execvp(args[0], args.as_mut_ptr());
    }

    show_error!("execvp: {}", Error::last_os_error());
    if Error::last_os_error().raw_os_error().unwrap() as c_int == libc::ENOENT {
        127
    } else {
        126
    }
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(executable!())
        .setting(AppSettings::TrailingVarArg)
        .version(crate_version!())
        .arg(
            Arg::with_name(options::ADJUSTMENT)
                .short("n")
                .long(options::ADJUSTMENT)
                .help("add N to the niceness (default is 10)")
                .takes_value(true)
                .allow_hyphen_values(true),
        )
        .arg(Arg::with_name(options::COMMAND).multiple(true))
}
<commit_msg>nice little code simplification, included already in the libc for all unixes<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) getpriority execvp setpriority nstr PRIO cstrs ENOENT

#[macro_use]
extern crate uucore;

use libc::{c_char, c_int, execvp, PRIO_PROCESS};
use std::ffi::CString;
use std::io::Error;
use std::ptr;

use clap::{crate_version, App, AppSettings, Arg};

pub mod options {
    pub static ADJUSTMENT: &str = "adjustment";
    pub static COMMAND: &str = "COMMAND";
}

fn get_usage() -> String {
    format!(
        "
  {0} [OPTIONS] [COMMAND [ARGS]]

Run COMMAND with an adjusted niceness, which affects process scheduling.
With no COMMAND, print the current niceness.  Niceness values range from at
least -20 (most favorable to the process) to 19 (least favorable to the
process).",
        executable!()
    )
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    let matches = uu_app().usage(&usage[..]).get_matches_from(args);

    let mut niceness = unsafe {
        nix::errno::Errno::clear();
        libc::getpriority(PRIO_PROCESS, 0)
    };
    if Error::last_os_error().raw_os_error().unwrap() != 0 {
        show_error!("getpriority: {}", Error::last_os_error());
        return 125;
    }

    let adjustment = match matches.value_of(options::ADJUSTMENT) {
        Some(nstr) => {
            if !matches.is_present(options::COMMAND) {
                show_error!(
                    "A command must be given with an adjustment.\nTry \"{} --help\" for more information.",
                    executable!()
                );
                return 125;
            }
            match nstr.parse() {
                Ok(num) => num,
                Err(e) => {
                    show_error!("\"{}\" is not a valid number: {}", nstr, e);
                    return 125;
                }
            }
        }
        None => {
            if !matches.is_present(options::COMMAND) {
                println!("{}", niceness);
                return 0;
            }
            10_i32
        }
    };

    niceness += adjustment;
    if unsafe { libc::setpriority(PRIO_PROCESS, 0, niceness) } == -1 {
        show_warning!("setpriority: {}", Error::last_os_error());
    }

    let cstrs: Vec<CString> = matches
        .values_of(options::COMMAND)
        .unwrap()
        .map(|x| CString::new(x.as_bytes()).unwrap())
        .collect();

    let mut args: Vec<*const c_char> = cstrs.iter().map(|s| s.as_ptr()).collect();
    args.push(ptr::null::<c_char>());
    unsafe {
        execvp(args[0], args.as_mut_ptr());
    }

    show_error!("execvp: {}", Error::last_os_error());
    if Error::last_os_error().raw_os_error().unwrap() as c_int == libc::ENOENT {
        127
    } else {
        126
    }
}

pub fn uu_app() -> App<'static, 'static> {
    App::new(executable!())
        .setting(AppSettings::TrailingVarArg)
        .version(crate_version!())
        .arg(
            Arg::with_name(options::ADJUSTMENT)
                .short("n")
                .long(options::ADJUSTMENT)
                .help("add N to the niceness (default is 10)")
                .takes_value(true)
                .allow_hyphen_values(true),
        )
        .arg(Arg::with_name(options::COMMAND).multiple(true))
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

//! Utilities for providing the completion language feature
use crate::lsp::{
    CompletionItem, CompletionParams, CompletionResponse, Message, ServerRequestId, ServerResponse,
    Url,
};
use crate::type_path::{TypePath, TypePathItem};
use crate::utils::extract_executable_document_from_text;
use common::Span;
use crossbeam::Sender;
use graphql_ir::Program;
use graphql_syntax::{
    Directive, DirectiveLocation, ExecutableDefinition, FragmentSpread, InlineFragment,
    LinkedField, List, OperationDefinition, OperationKind, ScalarField, Selection,
};
use graphql_syntax::{ExecutableDocument, GraphQLSource};
use interner::StringKey;
use log::info;
use relay_compiler::FileCategorizer;
use schema::{Directive as SchemaDirective, Schema, Type, TypeReference, TypeWithFields};
use std::{
    collections::HashMap,
    path::PathBuf,
    sync::{Arc, RwLock},
};

#[derive(Debug, Copy, Clone)]
pub enum CompletionKind {
    FieldName,
    FragmentSpread,
    DirectiveName { location: DirectiveLocation },
}
#[derive(Debug)]
pub struct CompletionRequest {
    /// The type of the completion request we're responding to
    kind: CompletionKind,
    /// A list of type metadata that we can use to resolve the leaf
    /// type the request is being made against
    type_path: TypePath,
    /// The project the request belongs to
    pub project_name: StringKey,
}

impl CompletionRequest {
    fn new(project_name: StringKey) -> Self {
        Self {
            kind: CompletionKind::FieldName,
            type_path: Default::default(),
            project_name,
        }
    }
}

pub fn create_completion_request(
    document: ExecutableDocument,
    position_span: Span,
    project_name: StringKey,
) -> Option<CompletionRequest> {
    info!("Building completion path for {:#?}", document);
    let mut completion_request = CompletionRequest::new(project_name);

    for definition in document.definitions {
        match &definition {
            ExecutableDefinition::Operation(operation) => {
                if operation.location.contains(position_span) {
                    let (_, kind) = operation.operation.clone()?;
                    completion_request
                        .type_path
                        .add_type(TypePathItem::Operation(kind));

                    info!(
                        "Completion request is within operation: {:?}",
                        operation.name
                    );
                    let OperationDefinition {
                        selections,
                        directives,
                        ..
                    } = operation;

                    let directive_location = match kind {
                        OperationKind::Query => DirectiveLocation::Query,
                        OperationKind::Mutation => DirectiveLocation::Mutation,
                        OperationKind::Subscription => DirectiveLocation::Subscription,
                    };

                    build_request_from_selection_or_directives(
                        selections,
                        directives,
                        directive_location,
                        position_span,
                        &mut completion_request,
                    );
                }
                // Check if the position span is within this operation's span
            }
            ExecutableDefinition::Fragment(fragment) => {
                if fragment.location.contains(position_span) {
                    let type_name = fragment.type_condition.type_.value;
                    completion_request
                        .type_path
                        .add_type(TypePathItem::FragmentDefinition { type_name });
                    build_request_from_selection_or_directives(
                        &fragment.selections,
                        &fragment.directives,
                        DirectiveLocation::FragmentDefinition,
                        position_span,
                        &mut completion_request,
                    );
                }
            }
        }
    }
    Some(completion_request)
}

fn resolve_completion_items_from_fields<T: TypeWithFields>(
    type_: &T,
    schema: &Schema,
) -> Vec<CompletionItem> {
    type_
        .fields()
        .iter()
        .map(|field_id| {
            let field = schema.field(*field_id);
            let name = field.name.to_string();
            if field.type_.inner().is_scalar() {
                CompletionItem::new_simple(name, "".into())
            } else {
                let insert_text = format!("{} {{\n\t$1\n}}", name);
                CompletionItem {
                    label: name,
                    kind: None,
                    detail: None,
                    documentation: None,
                    deprecated: None,
                    preselect: None,
                    sort_text: None,
                    filter_text: None,
                    insert_text: Some(insert_text),
                    insert_text_format: Some(lsp_types::InsertTextFormat::Snippet),
                    text_edit: None,
                    additional_text_edits: None,
                    command: None,
                    data: None,
                    tags: None,
                }
            }
        })
        .collect()
}

fn resolve_completion_items_for_fragment_spread(
    type_: Type,
    source_program: &Program,
    schema: &Schema,
) -> Vec<CompletionItem> {
    let mut valid_fragments = vec![];
    for fragment in source_program.fragments() {
        if fragment.type_condition == type_ && !fragment.variable_definitions.is_empty() {
            // Create a snippet if the fragment has required arugmentDefinition with no default values
            let mut cursor_location = 1;
            let mut args = vec![];
            for arg in fragment.variable_definitions.iter() {
                if arg.default_value.is_none() {
                    if let TypeReference::NonNull(type_) = &arg.type_ {
                        let value_snippet = match type_ {
                            t if t.is_list() => format!("[${}]", cursor_location),
                            t if schema.is_string(t.inner()) => format!("\"${}\"", cursor_location),
                            _ => format!("${}", cursor_location),
                        };
                        let str = format!("{}: {}", arg.name.item, value_snippet);
                        args.push(str);
                        cursor_location += 1;
                    }
                }
            }

            valid_fragments.push(if args.is_empty() {
                CompletionItem::new_simple(fragment.name.item.to_string(), "".into())
            } else {
                let label = fragment.name.item.to_string();
                let insert_text = format!("{} @arguments({})", label, args.join(", "));
                CompletionItem {
                    label,
                    kind: None,
                    detail: None,
                    documentation: None,
                    deprecated: None,
                    preselect: None,
                    sort_text: None,
                    filter_text: None,
                    insert_text: Some(insert_text),
                    insert_text_format: Some(lsp_types::InsertTextFormat::Snippet),
                    text_edit: None,
                    additional_text_edits: None,
                    command: None,
                    data: None,
                    tags: None,
                }
            });
        }
    }
    info!("get_valid_fragments_for_type {:#?}", valid_fragments);
    valid_fragments
}

pub fn completion_items_for_request(
    request: CompletionRequest,
    schema: &Schema,
    source_programs: &Arc<RwLock<HashMap<StringKey, Program>>>,
) -> Option<Vec<CompletionItem>> {
    let kind = request.kind;
    let project_name = request.project_name;
    let leaf_type = request.type_path.resolve_leaf_type(schema)?;
    info!("completion_items_for_request: {:?} - {:?}", leaf_type, kind);
    match kind {
        CompletionKind::FragmentSpread => {
            if let Some(source_program) = source_programs.read().unwrap().get(&project_name) {
                info!("has source program");
                let items =
                    resolve_completion_items_for_fragment_spread(leaf_type, source_program, schema);
                Some(items)
            } else {
                None
            }
        }
        CompletionKind::FieldName => match leaf_type {
            Type::Interface(interface_id) => {
                let interface = schema.interface(interface_id);
                let items = resolve_completion_items_from_fields(interface, schema);
                Some(items)
            }
            Type::Object(object_id) => {
                let object = schema.object(object_id);
                let items = resolve_completion_items_from_fields(object, schema);
                Some(items)
            }
            Type::Enum(_) | Type::InputObject(_) | Type::Scalar(_) | Type::Union(_) => None,
        },
        CompletionKind::DirectiveName { location } => {
            let directives = schema.directives_for_location(location);
            let items = directives
                .iter()
                .map(|directive| completion_item_from_directive(directive, schema))
                .collect();
            Some(items)
        }
    }
}

fn build_request_from_selections(
    selections: &List<Selection>,
    position_span: Span,
    completion_request: &mut CompletionRequest,
) {
    for item in &selections.items {
        if item.span().contains(position_span) {
            match item {
                Selection::LinkedField(node) => {
                    completion_request.kind = CompletionKind::FieldName;
                    let LinkedField {
                        name,
                        selections,
                        directives,
                        ..
                    } = node;
                    completion_request
                        .type_path
                        .add_type(TypePathItem::LinkedField { name: name.value });
                    build_request_from_selection_or_directives(
                        selections,
                        directives,
                        DirectiveLocation::Field,
                        position_span,
                        completion_request,
                    );
                }
                Selection::FragmentSpread(spread) => {
                    let FragmentSpread {
                        name, directives, ..
                    } = spread;
                    if name.span.contains(position_span) {
                        completion_request.kind = CompletionKind::FragmentSpread;
                    } else {
                        build_request_from_directives(
                            directives,
                            DirectiveLocation::FragmentSpread,
                            position_span,
                            completion_request,
                        );
                    }
                }
                Selection::InlineFragment(node) => {
                    let InlineFragment {
                        selections,
                        directives,
                        type_condition,
                        ..
                    } = node;
                    if let Some(type_condition) = type_condition {
                        let type_name = type_condition.type_.value;
                        completion_request
                            .type_path
                            .add_type(TypePathItem::InlineFragment { type_name });
                        build_request_from_selection_or_directives(
                            selections,
                            directives,
                            DirectiveLocation::InlineFragment,
                            position_span,
                            completion_request,
                        )
                    }
                }
                Selection::ScalarField(node) => {
                    let ScalarField {
                        directives, name, ..
                    } = node;
                    completion_request
                        .type_path
                        .add_type(TypePathItem::ScalarField { name: name.value });
                    build_request_from_directives(
                        directives,
                        DirectiveLocation::Scalar,
                        position_span,
                        completion_request,
                    );
                }
            }
        }
    }
}

fn build_request_from_directives(
    directives: &[Directive],
    location: DirectiveLocation,
    position_span: Span,
    completion_request: &mut CompletionRequest,
) {
    for Directive { span, .. } in directives {
        if span.contains(position_span) {
            completion_request.kind = CompletionKind::DirectiveName { location };
            break;
        }
    }
}

fn build_request_from_selection_or_directives(
    selections: &List<Selection>,
    directives: &[Directive],
    directive_location: DirectiveLocation,
    position_span: Span,
    completion_request: &mut CompletionRequest,
) {
    if selections.span.contains(position_span) {
        // TODO(brandondail) handle when the completion occurs at/within the start token
        build_request_from_selections(selections, position_span, completion_request);
    } else {
        build_request_from_directives(
            directives,
            directive_location,
            position_span,
            completion_request,
        )
    }
}

fn completion_item_from_directive(directive: &SchemaDirective, schema: &Schema) -> CompletionItem {
    let SchemaDirective {
        name, arguments, ..
    } = directive;

    use crate::lsp::InsertTextFormat;

    // Always use the name of the directive as the label
    let label = name.to_string();

    // We can return a snippet with the expected arguments of the directive
    let (insert_text, insert_text_format) = if arguments.is_empty() {
        (label.clone(), InsertTextFormat::PlainText)
    } else {
        let mut cursor_location = 1;
        let mut args = vec![];

        for arg in arguments.iter() {
            if let TypeReference::NonNull(type_) = &arg.type_ {
                let value_snippet = match type_ {
                    t if t.is_list() => format!("[${}]", cursor_location),
                    t if schema.is_string(t.inner()) => format!("\"${}\"", cursor_location),
                    _ => format!("${}", cursor_location),
                };
                let str = format!("{} : {}", arg.name, value_snippet);
                args.push(str);
                cursor_location += 1;
            }
        }

        if args.is_empty() {
            (label.clone(), InsertTextFormat::PlainText)
        } else {
            let insert_text = format!("{}({})", label, args.join(", "));
            (insert_text, InsertTextFormat::Snippet)
        }
    };

    CompletionItem {
        label,
        kind: None,
        detail: None,
        documentation: None,
        deprecated: None,
        preselect: None,
        sort_text: None,
        filter_text: None,
        insert_text: Some(insert_text),
        insert_text_format: Some(insert_text_format),
        text_edit: None,
        additional_text_edits: None,
        command: None,
        data: None,
        tags: None,
    }
}

pub fn send_completion_response(
    items: Vec<CompletionItem>,
    request_id: ServerRequestId,
    sender: &Sender<Message>,
) {
    // If there are no items, don't send any response
    if items.is_empty() {
        return;
    }
    let completion_response = CompletionResponse::Array(items);
    let result = serde_json::to_value(&completion_response).ok();
    let response = ServerResponse {
        id: request_id,
        error: None,
        result,
    };
    sender.send(Message::Response(response)).ok();
}

/// Return a `CompletionPath` for this request, only if the completion request occurs
/// within a GraphQL document. Otherwise return `None`
pub fn get_completion_request(
    params: CompletionParams,
    graphql_source_cache: &HashMap<Url, Vec<GraphQLSource>>,
    file_categorizer: &FileCategorizer,
    root_dir: &PathBuf,
) -> Option<CompletionRequest> {
    let CompletionParams {
        text_document_position,
        ..
    } = params;

    let (document, position_span, project_name) = extract_executable_document_from_text(
        text_document_position,
        graphql_source_cache,
        file_categorizer,
        root_dir,
    )
    .ok()?;

    let completion_request = create_completion_request(document, position_span, project_name);
    info!("Completion request: {:#?}", completion_request);
    completion_request
}
<commit_msg>Insert required arguements code snippets when auto completing fields<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

//! Utilities for providing the completion language feature
use crate::lsp::{
    CompletionItem, CompletionParams, CompletionResponse, Message, ServerRequestId, ServerResponse,
    Url,
};
use crate::type_path::{TypePath, TypePathItem};
use crate::utils::extract_executable_document_from_text;
use common::Span;
use crossbeam::Sender;
use graphql_ir::Program;
use graphql_syntax::{
    Directive, DirectiveLocation, ExecutableDefinition, FragmentSpread, InlineFragment,
    LinkedField, List, OperationDefinition, OperationKind, ScalarField, Selection,
};
use graphql_syntax::{ExecutableDocument, GraphQLSource};
use interner::StringKey;
use log::info;
use relay_compiler::FileCategorizer;
use schema::{
    ArgumentDefinitions, Directive as SchemaDirective, Schema, Type, TypeReference, TypeWithFields,
};
use std::{
    collections::HashMap,
    path::PathBuf,
    sync::{Arc, RwLock},
};

#[derive(Debug, Copy, Clone)]
pub enum CompletionKind {
    FieldName,
    FragmentSpread,
    DirectiveName { location: DirectiveLocation },
}
#[derive(Debug)]
pub struct CompletionRequest {
    /// The type of the completion request we're responding to
    kind: CompletionKind,
    /// A list of type metadata that we can use to resolve the leaf
    /// type the request is being made against
    type_path: TypePath,
    /// The project the request belongs to
    pub project_name: StringKey,
}

impl CompletionRequest {
    fn new(project_name: StringKey) -> Self {
        Self {
            kind: CompletionKind::FieldName,
            type_path: Default::default(),
            project_name,
        }
    }
}

pub fn create_completion_request(
    document: ExecutableDocument,
    position_span: Span,
    project_name: StringKey,
) -> Option<CompletionRequest> {
    info!("Building completion path for {:#?}", document);
    let mut completion_request = CompletionRequest::new(project_name);

    for definition in document.definitions {
        match &definition {
            ExecutableDefinition::Operation(operation) => {
                if operation.location.contains(position_span) {
                    let (_, kind) = operation.operation.clone()?;
                    completion_request
                        .type_path
                        .add_type(TypePathItem::Operation(kind));

                    info!(
                        "Completion request is within operation: {:?}",
                        operation.name
                    );
                    let OperationDefinition {
                        selections,
                        directives,
                        ..
                    } = operation;

                    let directive_location = match kind {
                        OperationKind::Query => DirectiveLocation::Query,
                        OperationKind::Mutation => DirectiveLocation::Mutation,
                        OperationKind::Subscription => DirectiveLocation::Subscription,
                    };

                    build_request_from_selection_or_directives(
                        selections,
                        directives,
                        directive_location,
                        position_span,
                        &mut completion_request,
                    );
                }
                // Check if the position span is within this operation's span
            }
            ExecutableDefinition::Fragment(fragment) => {
                if fragment.location.contains(position_span) {
                    let type_name = fragment.type_condition.type_.value;
                    completion_request
                        .type_path
                        .add_type(TypePathItem::FragmentDefinition { type_name });
                    build_request_from_selection_or_directives(
                        &fragment.selections,
                        &fragment.directives,
                        DirectiveLocation::FragmentDefinition,
                        position_span,
                        &mut completion_request,
                    );
                }
            }
        }
    }
    Some(completion_request)
}

fn resolve_completion_items_from_fields<T: TypeWithFields>(
    type_: &T,
    schema: &Schema,
) -> Vec<CompletionItem> {
    type_
        .fields()
        .iter()
        .map(|field_id| {
            let field = schema.field(*field_id);
            let name = field.name.to_string();
            let args = create_arguments_snippets(&field.arguments, schema);
            let insert_text = match (field.type_.inner().is_scalar(), args.is_empty()) {
                (true, true) => None,
                (true, false) => Some(format!("{}({})", name, args.join(", "))),
                (false, true) => Some(format!("{} {{\n\t$1\n}}", name)),
                (false, false) => Some(format!(
                    "{}({}) {{\n\t${}\n}}",
                    name,
                    args.join(", "),
                    args.len() + 1
                )),
            };
            let insert_text_format = if insert_text.is_some() {
                Some(lsp_types::InsertTextFormat::Snippet)
            } else {
                None
            };
            CompletionItem {
                label: name,
                kind: None,
                detail: None,
                documentation: None,
                deprecated: None,
                preselect: None,
                sort_text: None,
                filter_text: None,
                insert_text,
                insert_text_format,
                text_edit: None,
                additional_text_edits: None,
                command: None,
                data: None,
                tags: None,
            }
        })
        .collect()
}

fn resolve_completion_items_for_fragment_spread(
    type_: Type,
    source_program: &Program,
    schema: &Schema,
) -> Vec<CompletionItem> {
    let mut valid_fragments = vec![];
    for fragment in source_program.fragments() {
        if fragment.type_condition == type_ && !fragment.variable_definitions.is_empty() {
            // Create a snippet if the fragment has required arugmentDefinition with no default values
            let mut cursor_location = 1;
            let mut args = vec![];
            for arg in fragment.variable_definitions.iter() {
                if arg.default_value.is_none() {
                    if let TypeReference::NonNull(type_) = &arg.type_ {
                        let value_snippet = match type_ {
                            t if t.is_list() => format!("[${}]", cursor_location),
                            t if schema.is_string(t.inner()) => format!("\"${}\"", cursor_location),
                            _ => format!("${}", cursor_location),
                        };
                        let str = format!("{}: {}", arg.name.item, value_snippet);
                        args.push(str);
                        cursor_location += 1;
                    }
                }
            }

            valid_fragments.push(if args.is_empty() {
                CompletionItem::new_simple(fragment.name.item.to_string(), "".into())
            } else {
                let label = fragment.name.item.to_string();
                let insert_text = format!("{} @arguments({})", label, args.join(", "));
                CompletionItem {
                    label,
                    kind: None,
                    detail: None,
                    documentation: None,
                    deprecated: None,
                    preselect: None,
                    sort_text: None,
                    filter_text: None,
                    insert_text: Some(insert_text),
                    insert_text_format: Some(lsp_types::InsertTextFormat::Snippet),
                    text_edit: None,
                    additional_text_edits: None,
                    command: None,
                    data: None,
                    tags: None,
                }
            });
        }
    }
    info!("get_valid_fragments_for_type {:#?}", valid_fragments);
    valid_fragments
}

pub fn completion_items_for_request(
    request: CompletionRequest,
    schema: &Schema,
    source_programs: &Arc<RwLock<HashMap<StringKey, Program>>>,
) -> Option<Vec<CompletionItem>> {
    let kind = request.kind;
    let project_name = request.project_name;
    let leaf_type = request.type_path.resolve_leaf_type(schema)?;
    info!("completion_items_for_request: {:?} - {:?}", leaf_type, kind);
    match kind {
        CompletionKind::FragmentSpread => {
            if let Some(source_program) = source_programs.read().unwrap().get(&project_name) {
                info!("has source program");
                let items =
                    resolve_completion_items_for_fragment_spread(leaf_type, source_program, schema);
                Some(items)
            } else {
                None
            }
        }
        CompletionKind::FieldName => match leaf_type {
            Type::Interface(interface_id) => {
                let interface = schema.interface(interface_id);
                let items = resolve_completion_items_from_fields(interface, schema);
                Some(items)
            }
            Type::Object(object_id) => {
                let object = schema.object(object_id);
                let items = resolve_completion_items_from_fields(object, schema);
                Some(items)
            }
            Type::Enum(_) | Type::InputObject(_) | Type::Scalar(_) | Type::Union(_) => None,
        },
        CompletionKind::DirectiveName { location } => {
            let directives = schema.directives_for_location(location);
            let items = directives
                .iter()
                .map(|directive| completion_item_from_directive(directive, schema))
                .collect();
            Some(items)
        }
    }
}

fn build_request_from_selections(
    selections: &List<Selection>,
    position_span: Span,
    completion_request: &mut CompletionRequest,
) {
    for item in &selections.items {
        if item.span().contains(position_span) {
            match item {
                Selection::LinkedField(node) => {
                    completion_request.kind = CompletionKind::FieldName;
                    let LinkedField {
                        name,
                        selections,
                        directives,
                        ..
                    } = node;
                    completion_request
                        .type_path
                        .add_type(TypePathItem::LinkedField { name: name.value });
                    build_request_from_selection_or_directives(
                        selections,
                        directives,
                        DirectiveLocation::Field,
                        position_span,
                        completion_request,
                    );
                }
                Selection::FragmentSpread(spread) => {
                    let FragmentSpread {
                        name, directives, ..
                    } = spread;
                    if name.span.contains(position_span) {
                        completion_request.kind = CompletionKind::FragmentSpread;
                    } else {
                        build_request_from_directives(
                            directives,
                            DirectiveLocation::FragmentSpread,
                            position_span,
                            completion_request,
                        );
                    }
                }
                Selection::InlineFragment(node) => {
                    let InlineFragment {
                        selections,
                        directives,
                        type_condition,
                        ..
                    } = node;
                    if let Some(type_condition) = type_condition {
                        let type_name = type_condition.type_.value;
                        completion_request
                            .type_path
                            .add_type(TypePathItem::InlineFragment { type_name });
                        build_request_from_selection_or_directives(
                            selections,
                            directives,
                            DirectiveLocation::InlineFragment,
                            position_span,
                            completion_request,
                        )
                    }
                }
                Selection::ScalarField(node) => {
                    let ScalarField {
                        directives, name, ..
                    } = node;
                    completion_request
                        .type_path
                        .add_type(TypePathItem::ScalarField { name: name.value });
                    build_request_from_directives(
                        directives,
                        DirectiveLocation::Scalar,
                        position_span,
                        completion_request,
                    );
                }
            }
        }
    }
}

fn build_request_from_directives(
    directives: &[Directive],
    location: DirectiveLocation,
    position_span: Span,
    completion_request: &mut CompletionRequest,
) {
    for Directive { span, .. } in directives {
        if span.contains(position_span) {
            completion_request.kind = CompletionKind::DirectiveName { location };
            break;
        }
    }
}

fn build_request_from_selection_or_directives(
    selections: &List<Selection>,
    directives: &[Directive],
    directive_location: DirectiveLocation,
    position_span: Span,
    completion_request: &mut CompletionRequest,
) {
    if selections.span.contains(position_span) {
        // TODO(brandondail) handle when the completion occurs at/within the start token
        build_request_from_selections(selections, position_span, completion_request);
    } else {
        build_request_from_directives(
            directives,
            directive_location,
            position_span,
            completion_request,
        )
    }
}

fn completion_item_from_directive(directive: &SchemaDirective, schema: &Schema) -> CompletionItem {
    let SchemaDirective {
        name, arguments, ..
    } = directive;

    use crate::lsp::InsertTextFormat;

    // Always use the name of the directive as the label
    let label = name.to_string();

    // We can return a snippet with the expected arguments of the directive
    let (insert_text, insert_text_format) = if arguments.is_empty() {
        (label.clone(), InsertTextFormat::PlainText)
    } else {
        let args = create_arguments_snippets(&arguments, schema);
        if args.is_empty() {
            (label.clone(), InsertTextFormat::PlainText)
        } else {
            let insert_text = format!("{}({})", label, args.join(", "));
            (insert_text, InsertTextFormat::Snippet)
        }
    };

    CompletionItem {
        label,
        kind: None,
        detail: None,
        documentation: None,
        deprecated: None,
        preselect: None,
        sort_text: None,
        filter_text: None,
        insert_text: Some(insert_text),
        insert_text_format: Some(insert_text_format),
        text_edit: None,
        additional_text_edits: None,
        command: None,
        data: None,
        tags: None,
    }
}

fn create_arguments_snippets(arguments: &ArgumentDefinitions, schema: &Schema) -> Vec<String> {
    let mut cursor_location = 1;
    let mut args = vec![];

    for arg in arguments.iter() {
        if let TypeReference::NonNull(type_) = &arg.type_ {
            let value_snippet = match type_ {
                t if t.is_list() => format!("[${}]", cursor_location),
                t if schema.is_string(t.inner()) => format!("\"${}\"", cursor_location),
                _ => format!("${}", cursor_location),
            };
            let str = format!("{}: {}", arg.name, value_snippet);
            args.push(str);
            cursor_location += 1;
        }
    }
    args
}

pub fn send_completion_response(
    items: Vec<CompletionItem>,
    request_id: ServerRequestId,
    sender: &Sender<Message>,
) {
    // If there are no items, don't send any response
    if items.is_empty() {
        return;
    }
    let completion_response = CompletionResponse::Array(items);
    let result = serde_json::to_value(&completion_response).ok();
    let response = ServerResponse {
        id: request_id,
        error: None,
        result,
    };
    sender.send(Message::Response(response)).ok();
}

/// Return a `CompletionPath` for this request, only if the completion request occurs
/// within a GraphQL document. Otherwise return `None`
pub fn get_completion_request(
    params: CompletionParams,
    graphql_source_cache: &HashMap<Url, Vec<GraphQLSource>>,
    file_categorizer: &FileCategorizer,
    root_dir: &PathBuf,
) -> Option<CompletionRequest> {
    let CompletionParams {
        text_document_position,
        ..
    } = params;

    let (document, position_span, project_name) = extract_executable_document_from_text(
        text_document_position,
        graphql_source_cache,
        file_categorizer,
        root_dir,
    )
    .ok()?;

    let completion_request = create_completion_request(document, position_span, project_name);
    info!("Completion request: {:#?}", completion_request);
    completion_request
}
<|endoftext|>


<commit_before>#![feature(btree_range, collections_bound)]
extern crate capnp;

#[macro_use]
extern crate rustfbp;
mod contract_capnp {
    include!("list_triple.rs");
    include!("quadruple.rs");
}
use contract_capnp::list_triple;
use contract_capnp::quadruple;
use std::collections::BTreeSet;
use std::collections::Bound::{Included, Unbounded, Excluded};
use std::str::FromStr;

fn process_data(ip: rustfbp::ports::IP) -> Result<(u32,u32,u32,f32)>
{
    let data_reader = try!(ip.get_reader());
    let data_reader: list_triple::Reader = try!(data_reader.get_root());
    let data = try!(data_reader.get_triples());
    let stats_length = data.len();
    let mut total :u32 = 0;
    let mut stats = BTreeSet::new();
    for i in 0..data.len() {
        let second = u32::from_str(try!(data.get(i).get_second())).unwrap();
        stats.insert(second);
        total += second;
    }
    let min =  stats.iter().next().unwrap();
    let max =  stats.iter().last().unwrap();
    let average :u32 = total / stats.len() as u32;
    let median :u32 = stats.iter().nth(&stats.len()/2).unwrap().clone();
    let median = if stats.len() as f32 % 2 as f32 != 0 as f32{
        let mid :f32 = stats.len() as f32 / 2 as f32;
        let floor = mid.floor();
        let ceil = mid.ceil();
        let floor_val = stats.iter().nth(floor as usize).unwrap().clone();
        let ceil_val = stats.iter().nth(ceil as usize).unwrap().clone();
        let median = floor_val as f32 + ceil_val as f32 / 2 as f32;
        median
    } else {
        stats.iter().nth(stats.len()).unwrap().clone() as f32
    };
    Ok((min.clone(),max.clone(),average.clone(),median.clone()))
}

component! {
    example_wrangle_stats,
    inputs(raw: list_triple, anonymous: list_triple),
    inputs_array(),
    outputs(raw: quadruple, anonymous: quadruple),
    outputs_array(),
    option(),
    acc(),
    fn run(&mut self) -> Result<()> {
        let (min, max, average, median): (u32, u32, u32, f32) = try!(process_data(try!(self.ports.recv("raw"))));
        let mut raw_ip = capnp::message::Builder::new_default();
        {
            let mut quad = raw_ip.init_root::<quadruple::Builder>();
            quad.set_first(min);
            quad.set_second(max);
            quad.set_third(average);
            quad.set_fourth(median);
        }
        let mut send_ip = IP::new();
        try!(send_ip.write_builder(&raw_ip));
        try!(self.ports.send("raw", send_ip));

        let (min, max, average, median): (u32, u32, u32, f32) = try!(process_data(try!(self.ports.recv("anonymous"))));
        let mut anonymous_ip = capnp::message::Builder::new_default();
        {
            let mut quad = anonymous_ip.init_root::<quadruple::Builder>();
            quad.set_first(min);
            quad.set_second(max);
            quad.set_third(average);
            quad.set_fourth(median);
        }
        let mut send_ip = IP::new();
        try!(send_ip.write_builder(&anonymous_ip));
        try!(self.ports.send("anonymous", send_ip));
        Ok(())
    }
}

<commit_msg>Problem: stats gets incorrect median array number<commit_after>#![feature(btree_range, collections_bound)]
extern crate capnp;

#[macro_use]
extern crate rustfbp;
mod contract_capnp {
    include!("list_triple.rs");
    include!("quadruple.rs");
}
use contract_capnp::list_triple;
use contract_capnp::quadruple;
use std::collections::BTreeSet;
use std::collections::Bound::{Included, Unbounded, Excluded};
use std::str::FromStr;

fn process_data(ip: rustfbp::ports::IP) -> Result<(u32,u32,u32,f32)>
{
    let data_reader = try!(ip.get_reader());
    let data_reader: list_triple::Reader = try!(data_reader.get_root());
    let data = try!(data_reader.get_triples());
    let stats_length = data.len();
    let mut total :u32 = 0;
    let mut stats = BTreeSet::new();
    for i in 0..data.len() {
        let second = u32::from_str(try!(data.get(i).get_second())).unwrap();
        stats.insert(second);
        total += second;
    }
    let min =  stats.iter().next().unwrap();
    let max =  stats.iter().last().unwrap();
    let average :u32 = total / stats.len() as u32;
    let median = if stats.len() as f32 % 2 as f32 != 0 as f32{
        let mid :f32 = stats.len() as f32 / 2 as f32;
        let floor = mid.floor();
        let ceil = mid.ceil();
        let floor_val = stats.iter().nth(floor as usize).unwrap().clone();
        let ceil_val = stats.iter().nth(ceil as usize).unwrap().clone();
        let median = floor_val as f32 + ceil_val as f32 / 2 as f32;
        median
    } else {
        stats.iter().nth(stats.len()/2).unwrap().clone() as f32
    };
    Ok((min.clone(),max.clone(),average.clone(),median.clone()))
}

component! {
    example_wrangle_stats,
    inputs(raw: list_triple, anonymous: list_triple),
    inputs_array(),
    outputs(raw: quadruple, anonymous: quadruple),
    outputs_array(),
    option(),
    acc(),
    fn run(&mut self) -> Result<()> {
        let (min, max, average, median): (u32, u32, u32, f32) = try!(process_data(try!(self.ports.recv("raw"))));
        let mut raw_ip = capnp::message::Builder::new_default();
        {
            let mut quad = raw_ip.init_root::<quadruple::Builder>();
            quad.set_first(min);
            quad.set_second(max);
            quad.set_third(average);
            quad.set_fourth(median);
        }
        let mut send_ip = IP::new();
        try!(send_ip.write_builder(&raw_ip));
        try!(self.ports.send("raw", send_ip));

        let (min, max, average, median): (u32, u32, u32, f32) = try!(process_data(try!(self.ports.recv("anonymous"))));
        let mut anonymous_ip = capnp::message::Builder::new_default();
        {
            let mut quad = anonymous_ip.init_root::<quadruple::Builder>();
            quad.set_first(min);
            quad.set_second(max);
            quad.set_third(average);
            quad.set_fourth(median);
        }
        let mut send_ip = IP::new();
        try!(send_ip.write_builder(&anonymous_ip));
        try!(self.ports.send("anonymous", send_ip));
        Ok(())
    }
}

<|endoftext|>