<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::codegen::Bindings::HistoryBinding;
use crate::dom::bindings::codegen::Bindings::HistoryBinding::HistoryMethods;
use crate::dom::bindings::codegen::Bindings::LocationBinding::LocationBinding::LocationMethods;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::bindings::structuredclone::StructuredCloneData;
use crate::dom::event::Event;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::hashchangeevent::HashChangeEvent;
use crate::dom::popstateevent::PopStateEvent;
use crate::dom::window::Window;
use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct;
use js::jsapi::{Heap, JSContext};
use js::jsval::{JSVal, NullValue, UndefinedValue};
use js::rust::HandleValue;
use msg::constellation_msg::{HistoryStateId, TraversalDirection};
use net_traits::{CoreResourceMsg, IpcSend};
use profile_traits::ipc;
use profile_traits::ipc::channel;
use script_traits::ScriptMsg;
use servo_url::ServoUrl;
use std::cell::Cell;

enum PushOrReplace {
    Push,
    Replace,
}

// https://html.spec.whatwg.org/multipage/#the-history-interface
#[dom_struct]
pub struct History {
    reflector_: Reflector,
    window: Dom<Window>,
    #[ignore_malloc_size_of = "mozjs"]
    state: Heap<JSVal>,
    state_id: Cell<Option<HistoryStateId>>,
}

impl History {
    pub fn new_inherited(window: &Window) -> History {
        let state = Heap::default();
        state.set(NullValue());
        History {
            reflector_: Reflector::new(),
            window: Dom::from_ref(&window),
            state: state,
            state_id: Cell::new(None),
        }
    }

    pub fn new(window: &Window) -> DomRoot<History> {
        reflect_dom_object(
            Box::new(History::new_inherited(window)),
            window,
            HistoryBinding::Wrap,
        )
    }
}

impl History {
    fn traverse_history(&self, direction: TraversalDirection) -> ErrorResult {
        if !self.window.Document().is_fully_active() {
            return Err(Error::Security);
        }
        let msg = ScriptMsg::TraverseHistory(direction);
        let _ = self
            .window
            .upcast::<GlobalScope>()
            .script_to_constellation_chan()
            .send(msg);
        Ok(())
    }

    // https://html.spec.whatwg.org/multipage/#history-traversal
    // Steps 5-16
    #[allow(unsafe_code)]
    pub fn activate_state(&self, state_id: Option<HistoryStateId>, url: ServoUrl) {
        // Steps 5
        let document = self.window.Document();
        let old_url = document.url().clone();
        document.set_url(url.clone());

        // Step 6
        let hash_changed = old_url.fragment() != url.fragment();

        // Step 8
        if let Some(fragment) = url.fragment() {
            document.check_and_scroll_fragment(fragment);
        }

        // Step 11
        let state_changed = state_id != self.state_id.get();
        self.state_id.set(state_id);
        let serialized_data = match state_id {
            Some(state_id) => {
                let (tx, rx) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
                let _ = self
                    .window
                    .upcast::<GlobalScope>()
                    .resource_threads()
                    .send(CoreResourceMsg::GetHistoryState(state_id, tx));
                rx.recv().unwrap()
            },
            None => None,
        };

        match serialized_data {
            Some(serialized_data) => {
                let global_scope = self.window.upcast::<GlobalScope>();
                rooted!(in(*global_scope.get_cx()) let mut state = UndefinedValue());
                StructuredCloneData::Vector(serialized_data)
                    .read(&global_scope, state.handle_mut());
                self.state.set(state.get());
            },
            None => {
                self.state.set(NullValue());
            },
        }

        // TODO: Queue events on DOM Manipulation task source if non-blocking flag is set.
        // Step 16.1
        if state_changed {
            PopStateEvent::dispatch_jsval(
                self.window.upcast::<EventTarget>(),
                &*self.window,
                unsafe { HandleValue::from_raw(self.state.handle()) },
            );
        }

        // Step 16.3
        if hash_changed {
            let event = HashChangeEvent::new(
                &self.window,
                atom!("hashchange"),
                false,
                false,
                old_url.into_string(),
                url.into_string(),
            );
            event
                .upcast::<Event>()
                .fire(self.window.upcast::<EventTarget>());
        }
    }

    pub fn remove_states(&self, states: Vec<HistoryStateId>) {
        let _ = self
            .window
            .upcast::<GlobalScope>()
            .resource_threads()
            .send(CoreResourceMsg::RemoveHistoryStates(states));
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-pushstate
    // https://html.spec.whatwg.org/multipage/#dom-history-replacestate
    fn push_or_replace_state(
        &self,
        cx: *mut JSContext,
        data: HandleValue,
        _title: DOMString,
        url: Option<USVString>,
        push_or_replace: PushOrReplace,
    ) -> ErrorResult {
        // Step 1
        let document = self.window.Document();

        // Step 2
        if !document.is_fully_active() {
            return Err(Error::Security);
        }

        // TODO: Step 3 Optionally abort these steps
        // https://github.com/servo/servo/issues/19159

        // TODO: Step 4

        // Step 5
        let serialized_data = StructuredCloneData::write(cx, data)?.move_to_arraybuffer();

        let new_url: ServoUrl = match url {
            // Step 6
            Some(urlstring) => {
                let document_url = document.url();

                // Step 6.1
                let new_url = match ServoUrl::parse_with_base(Some(&document_url), &urlstring.0) {
                    // Step 6.3
                    Ok(parsed_url) => parsed_url,
                    // Step 6.2
                    Err(_) => return Err(Error::Security),
                };

                // Step 6.4
                if new_url.scheme() != document_url.scheme() ||
                    new_url.host() != document_url.host() ||
                    new_url.port() != document_url.port() ||
                    new_url.username() != document_url.username() ||
                    new_url.password() != document_url.password()
                {
                    return Err(Error::Security);
                }

                // Step 6.5
                if new_url.origin() != document_url.origin() {
                    return Err(Error::Security);
                }

                new_url
            },
            // Step 7
            None => document.url(),
        };

        // Step 8
        let state_id = match push_or_replace {
            PushOrReplace::Push => {
                let state_id = HistoryStateId::new();
                self.state_id.set(Some(state_id));
                let msg = ScriptMsg::PushHistoryState(state_id, new_url.clone());
                let _ = self
                    .window
                    .upcast::<GlobalScope>()
                    .script_to_constellation_chan()
                    .send(msg);
                state_id
            },
            PushOrReplace::Replace => {
                let state_id = match self.state_id.get() {
                    Some(state_id) => state_id,
                    None => {
                        let state_id = HistoryStateId::new();
                        self.state_id.set(Some(state_id));
                        state_id
                    },
                };
                let msg = ScriptMsg::ReplaceHistoryState(state_id, new_url.clone());
                let _ = self
                    .window
                    .upcast::<GlobalScope>()
                    .script_to_constellation_chan()
                    .send(msg);
                state_id
            },
        };

        let _ = self.window.upcast::<GlobalScope>().resource_threads().send(
            CoreResourceMsg::SetHistoryState(state_id, serialized_data.clone()),
        );

        // TODO: Step 9 Update current entry to represent a GET request
        // https://github.com/servo/servo/issues/19156

        // Step 10
        document.set_url(new_url);

        // Step 11
        let global_scope = self.window.upcast::<GlobalScope>();
        rooted!(in(cx) let mut state = UndefinedValue());
        StructuredCloneData::Vector(serialized_data).read(&global_scope, state.handle_mut());

        // Step 12
        self.state.set(state.get());

        // TODO: Step 13 Update Document's latest entry to current entry
        // https://github.com/servo/servo/issues/19158

        Ok(())
    }
}

impl HistoryMethods for History {
    // https://html.spec.whatwg.org/multipage/#dom-history-state
    fn GetState(&self, _cx: SafeJSContext) -> Fallible<JSVal> {
        if !self.window.Document().is_fully_active() {
            return Err(Error::Security);
        }
        Ok(self.state.get())
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-length
    fn GetLength(&self) -> Fallible<u32> {
        if !self.window.Document().is_fully_active() {
            return Err(Error::Security);
        }
        let (sender, recv) = channel(self.global().time_profiler_chan().clone())
            .expect("Failed to create channel to send jsh length.");
        let msg = ScriptMsg::JointSessionHistoryLength(sender);
        let _ = self
            .window
            .upcast::<GlobalScope>()
            .script_to_constellation_chan()
            .send(msg);
        Ok(recv.recv().unwrap())
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-go
    fn Go(&self, delta: i32) -> ErrorResult {
        let direction = if delta > 0 {
            TraversalDirection::Forward(delta as usize)
        } else if delta < 0 {
            TraversalDirection::Back(-delta as usize)
        } else {
            return self.window.Location().Reload();
        };

        self.traverse_history(direction)
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-back
    fn Back(&self) -> ErrorResult {
        self.traverse_history(TraversalDirection::Back(1))
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-forward
    fn Forward(&self) -> ErrorResult {
        self.traverse_history(TraversalDirection::Forward(1))
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-pushstate
    fn PushState(
        &self,
        cx: SafeJSContext,
        data: HandleValue,
        title: DOMString,
        url: Option<USVString>,
    ) -> ErrorResult {
        self.push_or_replace_state(*cx, data, title, url, PushOrReplace::Push)
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-replacestate
    fn ReplaceState(
        &self,
        cx: SafeJSContext,
        data: HandleValue,
        title: DOMString,
        url: Option<USVString>,
    ) -> ErrorResult {
        self.push_or_replace_state(*cx, data, title, url, PushOrReplace::Replace)
    }
}
<commit_msg>Remove some usage of unsafe code in History<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::codegen::Bindings::HistoryBinding;
use crate::dom::bindings::codegen::Bindings::HistoryBinding::HistoryMethods;
use crate::dom::bindings::codegen::Bindings::LocationBinding::LocationBinding::LocationMethods;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::bindings::structuredclone::StructuredCloneData;
use crate::dom::event::Event;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::hashchangeevent::HashChangeEvent;
use crate::dom::popstateevent::PopStateEvent;
use crate::dom::window::Window;
use crate::script_runtime::JSContext;
use dom_struct::dom_struct;
use js::jsapi::Heap;
use js::jsval::{JSVal, NullValue, UndefinedValue};
use js::rust::HandleValue;
use msg::constellation_msg::{HistoryStateId, TraversalDirection};
use net_traits::{CoreResourceMsg, IpcSend};
use profile_traits::ipc;
use profile_traits::ipc::channel;
use script_traits::ScriptMsg;
use servo_url::ServoUrl;
use std::cell::Cell;

enum PushOrReplace {
    Push,
    Replace,
}

// https://html.spec.whatwg.org/multipage/#the-history-interface
#[dom_struct]
pub struct History {
    reflector_: Reflector,
    window: Dom<Window>,
    #[ignore_malloc_size_of = "mozjs"]
    state: Heap<JSVal>,
    state_id: Cell<Option<HistoryStateId>>,
}

impl History {
    pub fn new_inherited(window: &Window) -> History {
        let state = Heap::default();
        state.set(NullValue());
        History {
            reflector_: Reflector::new(),
            window: Dom::from_ref(&window),
            state: state,
            state_id: Cell::new(None),
        }
    }

    pub fn new(window: &Window) -> DomRoot<History> {
        reflect_dom_object(
            Box::new(History::new_inherited(window)),
            window,
            HistoryBinding::Wrap,
        )
    }
}

impl History {
    fn traverse_history(&self, direction: TraversalDirection) -> ErrorResult {
        if !self.window.Document().is_fully_active() {
            return Err(Error::Security);
        }
        let msg = ScriptMsg::TraverseHistory(direction);
        let _ = self
            .window
            .upcast::<GlobalScope>()
            .script_to_constellation_chan()
            .send(msg);
        Ok(())
    }

    // https://html.spec.whatwg.org/multipage/#history-traversal
    // Steps 5-16
    #[allow(unsafe_code)]
    pub fn activate_state(&self, state_id: Option<HistoryStateId>, url: ServoUrl) {
        // Steps 5
        let document = self.window.Document();
        let old_url = document.url().clone();
        document.set_url(url.clone());

        // Step 6
        let hash_changed = old_url.fragment() != url.fragment();

        // Step 8
        if let Some(fragment) = url.fragment() {
            document.check_and_scroll_fragment(fragment);
        }

        // Step 11
        let state_changed = state_id != self.state_id.get();
        self.state_id.set(state_id);
        let serialized_data = match state_id {
            Some(state_id) => {
                let (tx, rx) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap();
                let _ = self
                    .window
                    .upcast::<GlobalScope>()
                    .resource_threads()
                    .send(CoreResourceMsg::GetHistoryState(state_id, tx));
                rx.recv().unwrap()
            },
            None => None,
        };

        match serialized_data {
            Some(serialized_data) => {
                let global_scope = self.window.upcast::<GlobalScope>();
                rooted!(in(*global_scope.get_cx()) let mut state = UndefinedValue());
                StructuredCloneData::Vector(serialized_data)
                    .read(&global_scope, state.handle_mut());
                self.state.set(state.get());
            },
            None => {
                self.state.set(NullValue());
            },
        }

        // TODO: Queue events on DOM Manipulation task source if non-blocking flag is set.
        // Step 16.1
        if state_changed {
            PopStateEvent::dispatch_jsval(
                self.window.upcast::<EventTarget>(),
                &*self.window,
                unsafe { HandleValue::from_raw(self.state.handle()) },
            );
        }

        // Step 16.3
        if hash_changed {
            let event = HashChangeEvent::new(
                &self.window,
                atom!("hashchange"),
                false,
                false,
                old_url.into_string(),
                url.into_string(),
            );
            event
                .upcast::<Event>()
                .fire(self.window.upcast::<EventTarget>());
        }
    }

    pub fn remove_states(&self, states: Vec<HistoryStateId>) {
        let _ = self
            .window
            .upcast::<GlobalScope>()
            .resource_threads()
            .send(CoreResourceMsg::RemoveHistoryStates(states));
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-pushstate
    // https://html.spec.whatwg.org/multipage/#dom-history-replacestate
    fn push_or_replace_state(
        &self,
        cx: JSContext,
        data: HandleValue,
        _title: DOMString,
        url: Option<USVString>,
        push_or_replace: PushOrReplace,
    ) -> ErrorResult {
        // Step 1
        let document = self.window.Document();

        // Step 2
        if !document.is_fully_active() {
            return Err(Error::Security);
        }

        // TODO: Step 3 Optionally abort these steps
        // https://github.com/servo/servo/issues/19159

        // TODO: Step 4

        // Step 5
        let serialized_data = StructuredCloneData::write(*cx, data)?.move_to_arraybuffer();

        let new_url: ServoUrl = match url {
            // Step 6
            Some(urlstring) => {
                let document_url = document.url();

                // Step 6.1
                let new_url = match ServoUrl::parse_with_base(Some(&document_url), &urlstring.0) {
                    // Step 6.3
                    Ok(parsed_url) => parsed_url,
                    // Step 6.2
                    Err(_) => return Err(Error::Security),
                };

                // Step 6.4
                if new_url.scheme() != document_url.scheme() ||
                    new_url.host() != document_url.host() ||
                    new_url.port() != document_url.port() ||
                    new_url.username() != document_url.username() ||
                    new_url.password() != document_url.password()
                {
                    return Err(Error::Security);
                }

                // Step 6.5
                if new_url.origin() != document_url.origin() {
                    return Err(Error::Security);
                }

                new_url
            },
            // Step 7
            None => document.url(),
        };

        // Step 8
        let state_id = match push_or_replace {
            PushOrReplace::Push => {
                let state_id = HistoryStateId::new();
                self.state_id.set(Some(state_id));
                let msg = ScriptMsg::PushHistoryState(state_id, new_url.clone());
                let _ = self
                    .window
                    .upcast::<GlobalScope>()
                    .script_to_constellation_chan()
                    .send(msg);
                state_id
            },
            PushOrReplace::Replace => {
                let state_id = match self.state_id.get() {
                    Some(state_id) => state_id,
                    None => {
                        let state_id = HistoryStateId::new();
                        self.state_id.set(Some(state_id));
                        state_id
                    },
                };
                let msg = ScriptMsg::ReplaceHistoryState(state_id, new_url.clone());
                let _ = self
                    .window
                    .upcast::<GlobalScope>()
                    .script_to_constellation_chan()
                    .send(msg);
                state_id
            },
        };

        let _ = self.window.upcast::<GlobalScope>().resource_threads().send(
            CoreResourceMsg::SetHistoryState(state_id, serialized_data.clone()),
        );

        // TODO: Step 9 Update current entry to represent a GET request
        // https://github.com/servo/servo/issues/19156

        // Step 10
        document.set_url(new_url);

        // Step 11
        let global_scope = self.window.upcast::<GlobalScope>();
        rooted!(in(*cx) let mut state = UndefinedValue());
        StructuredCloneData::Vector(serialized_data).read(&global_scope, state.handle_mut());

        // Step 12
        self.state.set(state.get());

        // TODO: Step 13 Update Document's latest entry to current entry
        // https://github.com/servo/servo/issues/19158

        Ok(())
    }
}

impl HistoryMethods for History {
    // https://html.spec.whatwg.org/multipage/#dom-history-state
    fn GetState(&self, _cx: JSContext) -> Fallible<JSVal> {
        if !self.window.Document().is_fully_active() {
            return Err(Error::Security);
        }
        Ok(self.state.get())
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-length
    fn GetLength(&self) -> Fallible<u32> {
        if !self.window.Document().is_fully_active() {
            return Err(Error::Security);
        }
        let (sender, recv) = channel(self.global().time_profiler_chan().clone())
            .expect("Failed to create channel to send jsh length.");
        let msg = ScriptMsg::JointSessionHistoryLength(sender);
        let _ = self
            .window
            .upcast::<GlobalScope>()
            .script_to_constellation_chan()
            .send(msg);
        Ok(recv.recv().unwrap())
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-go
    fn Go(&self, delta: i32) -> ErrorResult {
        let direction = if delta > 0 {
            TraversalDirection::Forward(delta as usize)
        } else if delta < 0 {
            TraversalDirection::Back(-delta as usize)
        } else {
            return self.window.Location().Reload();
        };

        self.traverse_history(direction)
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-back
    fn Back(&self) -> ErrorResult {
        self.traverse_history(TraversalDirection::Back(1))
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-forward
    fn Forward(&self) -> ErrorResult {
        self.traverse_history(TraversalDirection::Forward(1))
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-pushstate
    fn PushState(
        &self,
        cx: JSContext,
        data: HandleValue,
        title: DOMString,
        url: Option<USVString>,
    ) -> ErrorResult {
        self.push_or_replace_state(cx, data, title, url, PushOrReplace::Push)
    }

    // https://html.spec.whatwg.org/multipage/#dom-history-replacestate
    fn ReplaceState(
        &self,
        cx: JSContext,
        data: HandleValue,
        title: DOMString,
        url: Option<USVString>,
    ) -> ErrorResult {
        self.push_or_replace_state(cx, data, title, url, PushOrReplace::Replace)
    }
}
<|endoftext|>


<commit_before>use crate::spec::{LinkerFlavor, TargetOptions};

pub fn opts() -> TargetOptions {
    let mut base = super::linux_gnu_base::opts();
    base.os = "android".to_string();
    // Many of the symbols defined in compiler-rt are also defined in libgcc.
    // Android's linker doesn't like that by default.
    base.pre_link_args
        .entry(LinkerFlavor::Gcc)
        .or_default()
        .push("-Wl,--allow-multiple-definition".to_string());
    base.dwarf_version = Some(2);
    base.position_independent_executables = true;
    base.has_elf_tls = false;
    // This is for backward compatibility, see https://github.com/rust-lang/rust/issues/49867
    // for context. (At that time, there was no `-C force-unwind-tables`, so the only solution
    // was to always emit `uwtable`).
    base.default_uwtable = true;
    base.crt_static_respected = false;
    base
}
<commit_msg>Rollup merge of #90834 - cuviper:android-gnu, r=petrochenkov<commit_after>use crate::spec::{LinkerFlavor, TargetOptions};

pub fn opts() -> TargetOptions {
    let mut base = super::linux_base::opts();
    base.os = "android".to_string();
    // Many of the symbols defined in compiler-rt are also defined in libgcc.
    // Android's linker doesn't like that by default.
    base.pre_link_args
        .entry(LinkerFlavor::Gcc)
        .or_default()
        .push("-Wl,--allow-multiple-definition".to_string());
    base.dwarf_version = Some(2);
    base.position_independent_executables = true;
    base.has_elf_tls = false;
    // This is for backward compatibility, see https://github.com/rust-lang/rust/issues/49867
    // for context. (At that time, there was no `-C force-unwind-tables`, so the only solution
    // was to always emit `uwtable`).
    base.default_uwtable = true;
    base.crt_static_respected = false;
    base
}
<|endoftext|>


<commit_before>use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::{self, Ty};
use rustc_span::{self, Span};

use super::Expectation::*;
use super::FnCtxt;

/// When type-checking an expression, we propagate downward
/// whatever type hint we are able in the form of an `Expectation`.
#[derive(Copy, Clone, Debug)]
pub enum Expectation<'tcx> {
    /// We know nothing about what type this expression should have.
    NoExpectation,

    /// This expression should have the type given (or some subtype).
    ExpectHasType(Ty<'tcx>),

    /// This expression will be cast to the `Ty`.
    ExpectCastableToType(Ty<'tcx>),

    /// This rvalue expression will be wrapped in `&` or `Box` and coerced
    /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
    ExpectRvalueLikeUnsized(Ty<'tcx>),

    IsLast(Span),
}

impl<'a, 'tcx> Expectation<'tcx> {
    // Disregard "castable to" expectations because they
    // can lead us astray. Consider for example `if cond
    // {22} else {c} as u8` -- if we propagate the
    // "castable to u8" constraint to 22, it will pick the
    // type 22u8, which is overly constrained (c might not
    // be a u8). In effect, the problem is that the
    // "castable to" expectation is not the tightest thing
    // we can say, so we want to drop it in this case.
    // The tightest thing we can say is "must unify with
    // else branch". Note that in the case of a "has type"
    // constraint, this limitation does not hold.

    // If the expected type is just a type variable, then don't use
    // an expected type. Otherwise, we might write parts of the type
    // when checking the 'then' block which are incompatible with the
    // 'else' branch.
    pub(super) fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
        match *self {
            ExpectHasType(ety) => {
                let ety = fcx.shallow_resolve(ety);
                if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation }
            }
            ExpectRvalueLikeUnsized(ety) => ExpectRvalueLikeUnsized(ety),
            _ => NoExpectation,
        }
    }

    /// Provides an expectation for an rvalue expression given an *optional*
    /// hint, which is not required for type safety (the resulting type might
    /// be checked higher up, as is the case with `&expr` and `box expr`), but
    /// is useful in determining the concrete type.
    ///
    /// The primary use case is where the expected type is a fat pointer,
    /// like `&[isize]`. For example, consider the following statement:
    ///
    ///    let x: &[isize] = &[1, 2, 3];
    ///
    /// In this case, the expected type for the `&[1, 2, 3]` expression is
    /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
    /// expectation `ExpectHasType([isize])`, that would be too strong --
    /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
    /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
    /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
    /// which still is useful, because it informs integer literals and the like.
    /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
    /// for examples of where this comes up,.
    pub(super) fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
        match fcx.tcx.struct_tail_without_normalization(ty).kind() {
            ty::Slice(_) | ty::Str | ty::Dynamic(..) => ExpectRvalueLikeUnsized(ty),
            _ => ExpectHasType(ty),
        }
    }

    // Resolves `expected` by a single level if it is a variable. If
    // there is no expected type or resolution is not possible (e.g.,
    // no constraints yet present), just returns `self`.
    fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
        match self {
            NoExpectation => NoExpectation,
            ExpectCastableToType(t) => ExpectCastableToType(fcx.resolve_vars_if_possible(t)),
            ExpectHasType(t) => ExpectHasType(fcx.resolve_vars_if_possible(t)),
            ExpectRvalueLikeUnsized(t) => ExpectRvalueLikeUnsized(fcx.resolve_vars_if_possible(t)),
            IsLast(sp) => IsLast(sp),
        }
    }

    pub(super) fn to_option(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
        match self.resolve(fcx) {
            NoExpectation | IsLast(_) => None,
            ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueLikeUnsized(ty) => Some(ty),
        }
    }

    /// It sometimes happens that we want to turn an expectation into
    /// a **hard constraint** (i.e., something that must be satisfied
    /// for the program to type-check). `only_has_type` will return
    /// such a constraint, if it exists.
    pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
        match self.resolve(fcx) {
            ExpectHasType(ty) => Some(ty),
            NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) | IsLast(_) => {
                None
            }
        }
    }

    /// Like `only_has_type`, but instead of returning `None` if no
    /// hard constraint exists, creates a fresh type variable.
    pub(super) fn coercion_target_type(self, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> Ty<'tcx> {
        self.only_has_type(fcx).unwrap_or_else(|| {
            fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span })
        })
    }
}
<commit_msg>Optimize out unneeded type resolving<commit_after>use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::{self, Ty};
use rustc_span::{self, Span};

use super::Expectation::*;
use super::FnCtxt;

/// When type-checking an expression, we propagate downward
/// whatever type hint we are able in the form of an `Expectation`.
#[derive(Copy, Clone, Debug)]
pub enum Expectation<'tcx> {
    /// We know nothing about what type this expression should have.
    NoExpectation,

    /// This expression should have the type given (or some subtype).
    ExpectHasType(Ty<'tcx>),

    /// This expression will be cast to the `Ty`.
    ExpectCastableToType(Ty<'tcx>),

    /// This rvalue expression will be wrapped in `&` or `Box` and coerced
    /// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
    ExpectRvalueLikeUnsized(Ty<'tcx>),

    IsLast(Span),
}

impl<'a, 'tcx> Expectation<'tcx> {
    // Disregard "castable to" expectations because they
    // can lead us astray. Consider for example `if cond
    // {22} else {c} as u8` -- if we propagate the
    // "castable to u8" constraint to 22, it will pick the
    // type 22u8, which is overly constrained (c might not
    // be a u8). In effect, the problem is that the
    // "castable to" expectation is not the tightest thing
    // we can say, so we want to drop it in this case.
    // The tightest thing we can say is "must unify with
    // else branch". Note that in the case of a "has type"
    // constraint, this limitation does not hold.

    // If the expected type is just a type variable, then don't use
    // an expected type. Otherwise, we might write parts of the type
    // when checking the 'then' block which are incompatible with the
    // 'else' branch.
    pub(super) fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
        match *self {
            ExpectHasType(ety) => {
                let ety = fcx.shallow_resolve(ety);
                if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation }
            }
            ExpectRvalueLikeUnsized(ety) => ExpectRvalueLikeUnsized(ety),
            _ => NoExpectation,
        }
    }

    /// Provides an expectation for an rvalue expression given an *optional*
    /// hint, which is not required for type safety (the resulting type might
    /// be checked higher up, as is the case with `&expr` and `box expr`), but
    /// is useful in determining the concrete type.
    ///
    /// The primary use case is where the expected type is a fat pointer,
    /// like `&[isize]`. For example, consider the following statement:
    ///
    ///    let x: &[isize] = &[1, 2, 3];
    ///
    /// In this case, the expected type for the `&[1, 2, 3]` expression is
    /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
    /// expectation `ExpectHasType([isize])`, that would be too strong --
    /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
    /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
    /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
    /// which still is useful, because it informs integer literals and the like.
    /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
    /// for examples of where this comes up,.
    pub(super) fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
        match fcx.tcx.struct_tail_without_normalization(ty).kind() {
            ty::Slice(_) | ty::Str | ty::Dynamic(..) => ExpectRvalueLikeUnsized(ty),
            _ => ExpectHasType(ty),
        }
    }

    // Resolves `expected` by a single level if it is a variable. If
    // there is no expected type or resolution is not possible (e.g.,
    // no constraints yet present), just returns `self`.
    fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
        match self {
            NoExpectation => NoExpectation,
            ExpectCastableToType(t) => ExpectCastableToType(fcx.resolve_vars_if_possible(t)),
            ExpectHasType(t) => ExpectHasType(fcx.resolve_vars_if_possible(t)),
            ExpectRvalueLikeUnsized(t) => ExpectRvalueLikeUnsized(fcx.resolve_vars_if_possible(t)),
            IsLast(sp) => IsLast(sp),
        }
    }

    pub(super) fn to_option(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
        match self.resolve(fcx) {
            NoExpectation | IsLast(_) => None,
            ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueLikeUnsized(ty) => Some(ty),
        }
    }

    /// It sometimes happens that we want to turn an expectation into
    /// a **hard constraint** (i.e., something that must be satisfied
    /// for the program to type-check). `only_has_type` will return
    /// such a constraint, if it exists.
    pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
        match self {
            ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)),
            NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) | IsLast(_) => {
                None
            }
        }
    }

    /// Like `only_has_type`, but instead of returning `None` if no
    /// hard constraint exists, creates a fresh type variable.
    pub(super) fn coercion_target_type(self, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> Ty<'tcx> {
        self.only_has_type(fcx).unwrap_or_else(|| {
            fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span })
        })
    }
}
<|endoftext|>


<commit_before>//! Layout handling

use rustwlc::handle::{WlcView, WlcOutput};
use std::rc::{Rc, Weak};

#[derive(PartialEq, Clone, Copy)]
pub enum ContainerType {
    Root,        /* Root container, only one exists */
    Output,      /* Output, like a monitor or head */
    Workspace,   /* A workspace */
    View         /* A view (aka a window) */
}

/// Types of container
enum ContainerTypes {
    /// Root container, only one exists
    Root,
    /// WlcOutput/monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Layout mode for a container
enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Vec<Weak<Box<Containable>>>;

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(&self);

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Finds a parent container with the given type, if there is any
    fn get_parent_by_type(&self, type_: ContainerType) -> Option<&Containable> {
        let mut container = self.get_parent();
        while container.is_some() && container.unwrap().get_type() != type_ {
            container = container.unwrap().get_parent();
        }
        container
    }
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Returns true if this view is a parent is an ancestor of the child
    fn is_parent_of<T: Containable>(&self, child: T) -> bool;

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of<T: Containable>(&self, parent: T) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace<T: Containable>(&self) -> T;
}

struct Container {
    handle: Option<WlcOutput>,

    parent: Box<Containable>,
    children: Vec<Rc<Box<Containable>>>,
    type_: ContainerType,
    layout: Layout,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for Container {

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable> {
        match self.type_ {
            ContainerType::Root => None,
            _ => Some(&*self.parent),
        }
    }
    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Vec<Weak<Box<Containable>>> {
        self.children.iter().map(|child| Rc::downgrade(&child)).collect()
    }

    fn get_type(&self) -> ContainerType {
        self.type_
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) {
        for child in self.get_children() {
            if let Some(child) = child.upgrade() {
                if let Ok(child) = Rc::try_unwrap(child) {
                    child.remove_container();
                    drop(child);
                }
            }
        }
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X (width) and Y (height) dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }

}

struct View {
    handle: Option<WlcView>,
    parent: Box<Containable>,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for View {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable> {
        Some(&*self.parent)
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Vec<Weak<Box<Containable>>> {
        unimplemented!();
    }

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType {
        ContainerType::View
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) {
        unimplemented!();
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }

    /// Finds a parent container with the given type
    fn get_parent_by_type(&self, type_: ContainerType) -> Option<&Containable> {
        unimplemented!();
    }
}
<commit_msg>Removed bad view implementation of get_parent_by_type<commit_after>//! Layout handling

use rustwlc::handle::{WlcView, WlcOutput};
use std::rc::{Rc, Weak};

#[derive(PartialEq, Clone, Copy)]
pub enum ContainerType {
    Root,        /* Root container, only one exists */
    Output,      /* Output, like a monitor or head */
    Workspace,   /* A workspace */
    View         /* A view (aka a window) */
}

/// Types of container
enum ContainerTypes {
    /// Root container, only one exists
    Root,
    /// WlcOutput/monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Layout mode for a container
enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Vec<Weak<Box<Containable>>>;

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(&self);

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Finds a parent container with the given type, if there is any
    fn get_parent_by_type(&self, type_: ContainerType) -> Option<&Containable> {
        let mut container = self.get_parent();
        while container.is_some() && container.unwrap().get_type() != type_ {
            container = container.unwrap().get_parent();
        }
        container
    }
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Returns true if this view is a parent is an ancestor of the child
    fn is_parent_of<T: Containable>(&self, child: T) -> bool;

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of<T: Containable>(&self, parent: T) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace<T: Containable>(&self) -> T;
}

struct Container {
    handle: Option<WlcOutput>,

    parent: Box<Containable>,
    children: Vec<Rc<Box<Containable>>>,
    type_: ContainerType,
    layout: Layout,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for Container {

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable> {
        match self.type_ {
            ContainerType::Root => None,
            _ => Some(&*self.parent),
        }
    }
    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Vec<Weak<Box<Containable>>> {
        self.children.iter().map(|child| Rc::downgrade(&child)).collect()
    }

    fn get_type(&self) -> ContainerType {
        self.type_
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) {
        for child in self.get_children() {
            if let Some(child) = child.upgrade() {
                if let Ok(child) = Rc::try_unwrap(child) {
                    child.remove_container();
                    drop(child);
                }
            }
        }
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X (width) and Y (height) dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }

}

struct View {
    handle: Option<WlcView>,
    parent: Box<Containable>,

    width: u64,
    height: u64,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for View {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<&Containable> {
        Some(&*self.parent)
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Vec<Weak<Box<Containable>>> {
        unimplemented!();
    }

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType {
        ContainerType::View
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) {
        unimplemented!();
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u64, u64) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }
}
<|endoftext|>


<commit_before>mod support;

use serde_json::json;
use ra_lsp_server::req::{Runnables, RunnablesParams, CodeActionRequest, CodeActionParams};
use languageserver_types::{Position, Range, CodeActionContext};

use crate::support::project;

const LOG: &'static str = "";

#[test]
fn test_runnables_no_project() {
    let server = project(
        r"
//- lib.rs
#[test]
fn foo() {
}
",
    );
    server.wait_for_feedback("workspace loaded");
    server.request::<Runnables>(
        RunnablesParams {
            text_document: server.doc_id("lib.rs"),
            position: None,
        },
        json!([
          {
            "args": [ "test", "--", "foo", "--nocapture" ],
            "bin": "cargo",
            "env": { "RUST_BACKTRACE": "short" },
            "label": "test foo",
            "range": {
              "end": { "character": 1, "line": 2 },
              "start": { "character": 0, "line": 0 }
            }
          },
          {
            "args": [
              "check",
              "--all"
            ],
            "bin": "cargo",
            "env": {},
            "label": "cargo check --all",
            "range": {
              "end": {
                "character": 0,
                "line": 0
              },
              "start": {
                "character": 0,
                "line": 0
              }
            }
          }
        ]),
    );
}

#[test]
fn test_runnables_project() {
    let server = project(
        r#"
//- Cargo.toml
[package]
name = "foo"
version = "0.0.0"

//- src/lib.rs
pub fn foo() {}

//- tests/spam.rs
#[test]
fn test_eggs() {}
"#,
    );
    server.wait_for_feedback("workspace loaded");
    server.request::<Runnables>(
        RunnablesParams {
            text_document: server.doc_id("tests/spam.rs"),
            position: None,
        },
        json!([
          {
            "args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--nocapture" ],
            "bin": "cargo",
            "env": { "RUST_BACKTRACE": "short" },
            "label": "test test_eggs",
            "range": {
              "end": { "character": 17, "line": 1 },
              "start": { "character": 0, "line": 0 }
            }
          },
          {
            "args": [
              "check",
              "--package",
              "foo",
              "--test",
              "spam"
            ],
            "bin": "cargo",
            "env": {},
            "label": "cargo check -p foo",
            "range": {
              "end": {
                "character": 0,
                "line": 0
              },
              "start": {
                "character": 0,
                "line": 0
              }
            }
          }
        ])
    );
}

#[test]
fn test_missing_module_code_action() {
    let server = project(
        r#"
//- Cargo.toml
[package]
name = "foo"
version = "0.0.0"

//- src/lib.rs
mod bar;

fn main() {}
"#,
    );
    server.wait_for_feedback("workspace loaded");
    let empty_context = || CodeActionContext {
        diagnostics: Vec::new(),
        only: None,
    };
    server.request::<CodeActionRequest>(
        CodeActionParams {
            text_document: server.doc_id("src/lib.rs"),
            range: Range::new(Position::new(0, 0), Position::new(0, 7)),
            context: empty_context(),
        },
        json!([
            {
              "arguments": [
                {
                  "cursorPosition": null,
                  "fileSystemEdits": [
                    {
                        "type": "createFile",
                        "uri": "file:///[..]/src/bar.rs"
                    }
                  ],
                  "label": "create module",
                  "sourceFileEdits": []
                }
              ],
              "command": "ra-lsp.applySourceChange",
              "title": "create module"
            }
        ]),
    );

    server.request::<CodeActionRequest>(
        CodeActionParams {
            text_document: server.doc_id("src/lib.rs"),
            range: Range::new(Position::new(2, 0), Position::new(2, 7)),
            context: empty_context(),
        },
        json!([]),
    );
}
<commit_msg>fix the test<commit_after>mod support;

use serde_json::json;
use ra_lsp_server::req::{Runnables, RunnablesParams, CodeActionRequest, CodeActionParams};
use languageserver_types::{Position, Range, CodeActionContext};

use crate::support::project;

const LOG: &'static str = "";

#[test]
fn test_runnables_no_project() {
    let server = project(
        r"
//- lib.rs
#[test]
fn foo() {
}
",
    );
    server.wait_for_feedback("workspace loaded");
    server.request::<Runnables>(
        RunnablesParams {
            text_document: server.doc_id("lib.rs"),
            position: None,
        },
        json!([
          {
            "args": [ "test", "--", "foo", "--nocapture" ],
            "bin": "cargo",
            "env": { "RUST_BACKTRACE": "short" },
            "label": "test foo",
            "range": {
              "end": { "character": 1, "line": 2 },
              "start": { "character": 0, "line": 0 }
            }
          },
          {
            "args": [
              "check",
              "--all"
            ],
            "bin": "cargo",
            "env": {},
            "label": "cargo check --all",
            "range": {
              "end": {
                "character": 0,
                "line": 0
              },
              "start": {
                "character": 0,
                "line": 0
              }
            }
          }
        ]),
    );
}

#[test]
fn test_runnables_project() {
    let server = project(
        r#"
//- Cargo.toml
[package]
name = "foo"
version = "0.0.0"

//- src/lib.rs
pub fn foo() {}

//- tests/spam.rs
#[test]
fn test_eggs() {}
"#,
    );
    server.wait_for_feedback("workspace loaded");
    server.request::<Runnables>(
        RunnablesParams {
            text_document: server.doc_id("tests/spam.rs"),
            position: None,
        },
        json!([
          {
            "args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--nocapture" ],
            "bin": "cargo",
            "env": { "RUST_BACKTRACE": "short" },
            "label": "test test_eggs",
            "range": {
              "end": { "character": 17, "line": 1 },
              "start": { "character": 0, "line": 0 }
            }
          },
          {
            "args": [
              "check",
              "--package",
              "foo",
              "--test",
              "spam"
            ],
            "bin": "cargo",
            "env": {},
            "label": "cargo check -p foo",
            "range": {
              "end": {
                "character": 0,
                "line": 0
              },
              "start": {
                "character": 0,
                "line": 0
              }
            }
          }
        ])
    );
}

#[test]
fn test_missing_module_code_action() {
    let server = project(
        r#"
//- Cargo.toml
[package]
name = "foo"
version = "0.0.0"

//- src/lib.rs
mod bar;

fn main() {}
"#,
    );
    server.wait_for_feedback("workspace loaded");
    let empty_context = || CodeActionContext {
        diagnostics: Vec::new(),
        only: None,
    };
    server.request::<CodeActionRequest>(
        CodeActionParams {
            text_document: server.doc_id("src/lib.rs"),
            range: Range::new(Position::new(0, 4), Position::new(0, 7)),
            context: empty_context(),
        },
        json!([
            {
              "arguments": [
                {
                  "cursorPosition": null,
                  "fileSystemEdits": [
                    {
                        "type": "createFile",
                        "uri": "file:///[..]/src/bar.rs"
                    }
                  ],
                  "label": "create module",
                  "sourceFileEdits": []
                }
              ],
              "command": "ra-lsp.applySourceChange",
              "title": "create module"
            }
        ]),
    );

    server.request::<CodeActionRequest>(
        CodeActionParams {
            text_document: server.doc_id("src/lib.rs"),
            range: Range::new(Position::new(2, 4), Position::new(2, 7)),
            context: empty_context(),
        },
        json!([]),
    );
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate crossbeam_channel;
extern crate flexi_logger;
extern crate gen_lsp_server;
extern crate languageserver_types;
extern crate ra_lsp_server;
extern crate serde;
extern crate serde_json;
extern crate tempdir;

mod support;

use ra_lsp_server::req::{Runnables, RunnablesParams};

use crate::support::project;

const LOG: &'static str = "";

#[test]
fn test_runnables_no_project() {
    let server = project(
        r"
//- lib.rs
#[test]
fn foo() {
}
",
    );
    server.request::<Runnables>(
        RunnablesParams {
            text_document: server.doc_id("lib.rs"),
            position: None,
        },
        r#"[
          {
            "args": [ "test", "--", "foo", "--nocapture" ],
            "bin": "cargo",
            "env": { "RUST_BACKTRACE": "short" },
            "label": "test foo",
            "range": {
              "end": { "character": 1, "line": 2 },
              "start": { "character": 0, "line": 0 }
            }
          }
        ]"#,
    );
}

#[test]
fn test_runnables_project() {
    let server = project(
        r#"
//- Cargo.toml
[package]
name = "foo"
version = "0.0.0"

//- src/lib.rs
pub fn foo() {}

//- tests/spam.rs
#[test]
fn test_eggs() {}
"#,
    );
    server.wait_for_feedback("workspace loaded");
    server.request::<Runnables>(
        RunnablesParams {
            text_document: server.doc_id("tests/spam.rs"),
            position: None,
        },
        r#"[
          {
            "args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--nocapture" ],
            "bin": "cargo",
            "env": { "RUST_BACKTRACE": "short" },
            "label": "test test_eggs",
            "range": {
              "end": { "character": 17, "line": 1 },
              "start": { "character": 0, "line": 0 }
            }
          }
        ]"#
    );
}

// #[test]
// fn test_deps() {
//     let server = project(r#"
// //- Cargo.toml
// [package]
// name = "foo"
// version = "0.0.0"
// [dependencies]
// regex = "=1.0.4"

// //- src/lib.rs
// extern crate regex;
// "#);
//     server.wait_for_feedback("workspace loaded");
//     server.wait_for_feedback_n("library loaded", 9);
// }
<commit_msg>Fix the test<commit_after>#[macro_use]
extern crate crossbeam_channel;
extern crate flexi_logger;
extern crate gen_lsp_server;
extern crate languageserver_types;
extern crate ra_lsp_server;
extern crate serde;
extern crate serde_json;
extern crate tempdir;

mod support;

use ra_lsp_server::req::{Runnables, RunnablesParams};

use crate::support::project;

const LOG: &'static str = "";

#[test]
fn test_runnables_no_project() {
    let server = project(
        r"
//- lib.rs
#[test]
fn foo() {
}
",
    );
    server.request::<Runnables>(
        RunnablesParams {
            text_document: server.doc_id("lib.rs"),
            position: None,
        },
        r#"[
          {
            "args": [ "test", "--", "foo", "--nocapture" ],
            "bin": "cargo",
            "env": { "RUST_BACKTRACE": "short" },
            "label": "test foo",
            "range": {
              "end": { "character": 1, "line": 2 },
              "start": { "character": 0, "line": 0 }
            }
          },
          {
            "args": [
              "check",
              "--all"
            ],
            "bin": "cargo",
            "env": {},
            "label": "cargo check --all",
            "range": {
              "end": {
                "character": 0,
                "line": 0
              },
              "start": {
                "character": 0,
                "line": 0
              }
            }
          }
        ]"#,
    );
}

#[test]
fn test_runnables_project() {
    let server = project(
        r#"
//- Cargo.toml
[package]
name = "foo"
version = "0.0.0"

//- src/lib.rs
pub fn foo() {}

//- tests/spam.rs
#[test]
fn test_eggs() {}
"#,
    );
    server.wait_for_feedback("workspace loaded");
    server.request::<Runnables>(
        RunnablesParams {
            text_document: server.doc_id("tests/spam.rs"),
            position: None,
        },
        r#"[
          {
            "args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--nocapture" ],
            "bin": "cargo",
            "env": { "RUST_BACKTRACE": "short" },
            "label": "test test_eggs",
            "range": {
              "end": { "character": 17, "line": 1 },
              "start": { "character": 0, "line": 0 }
            }
          },
          {
            "args": [
              "check",
              "--package",
              "foo",
              "--test",
              "spam"
            ],
            "bin": "cargo",
            "env": {},
            "label": "cargo check -p foo",
            "range": {
              "end": {
                "character": 0,
                "line": 0
              },
              "start": {
                "character": 0,
                "line": 0
              }
            }
          }
        ]"#
    );
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use cfb::CompoundFile;
use std::{
    fs::read_dir,
    io::{Cursor, Read, Seek, SeekFrom, Write},
    path::Path,
    sync::mpsc,
    thread,
    time::Duration,
};

// Run function on another thread, panic if it takes too long
fn panic_after<T, F>(d: Duration, f: F) -> T
where
    T: Send + 'static,
    F: FnOnce() -> T,
    F: Send + 'static,
{
    let (done_tx, done_rx) = mpsc::channel();
    let handle = thread::spawn(move || {
        let val = f();
        done_tx.send(()).expect("Unable to send completion signal");
        val
    });

    match done_rx.recv_timeout(d) {
        Ok(_) => handle.join().expect("Thread panicked"),
        Err(_) => panic!("Thread took too long"),
    }
}

// Checks to see if a file can be walked over and read properly, or fail if it can not be read
fn can_read(path: &Path) {
    let data = std::fs::read(&path).unwrap();

    let cursor = Cursor::new(data);
    let mut cfb = match CompoundFile::open(cursor) {
        Ok(cfb) => cfb,
        Err(_) => return,
    };

    #[allow(clippy::needless_collect)]
    let stream_paths = cfb
        .walk()
        .filter(|e| e.is_stream())
        .map(|e| e.path().to_path_buf())
        .collect::<Vec<_>>();

    let _unused = stream_paths
        .into_iter()
        .map(|s| -> Result<Vec<u8>, std::io::Error> {
            let mut data = Vec::new();
            cfb.open_stream(&s)?.read_to_end(&mut data)?;
            Ok(data)
        })
        .collect::<Vec<_>>();
}

/// Regression test for https://github.com/mdsteele/rust-cfb/issues/16.
#[test]
#[should_panic(
    expected = "Found reference to mini sector 123456789, but MiniFAT has \
                only 2 entries"
)]
fn invalid_mini_sector_issue_16() {
    // Create a CFB file with a mini stream.
    let cursor = Cursor::new(Vec::new());
    let mut comp = CompoundFile::create(cursor).unwrap();
    let version = comp.version();
    comp.create_stream("foo").unwrap().write_all(&[0u8; 80]).unwrap();
    let mut cursor = comp.into_inner();

    // Corrupt the starting mini sector ID of the stream.  Due to how we
    // constructed the CFB file, this will be at byte 116 of the second
    // 128-byte directory entry in the third sector of the CFB file.
    let offset = 116 + 128 * 1 + (version.sector_len() as u64) * 2;
    cursor.seek(SeekFrom::Start(offset)).unwrap();
    cursor.write_u32::<LittleEndian>(123456789).unwrap();

    // Re-open the CFB file and try to read the mini stream.
    let mut comp = CompoundFile::open(cursor).unwrap();
    let mut data = Vec::new();
    comp.open_stream("foo").unwrap().read_to_end(&mut data).unwrap();
}

#[test]
fn check_for_infinite_loops() {
    // Loop through the provided files
    for entry in read_dir("tests/infinite_loops_fuzzed").unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();

        // Test will panic if it takes more than 1 second to load the file ie. stuck in a loop
        panic_after(Duration::from_secs(1), move || can_read(&path))
    }
}
<commit_msg>Add regression test for issue #17<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use cfb::CompoundFile;
use std::{
    fs::read_dir,
    io::{Cursor, Read, Seek, SeekFrom, Write},
    path::Path,
    sync::mpsc,
    thread,
    time::Duration,
};

// Run function on another thread, panic if it takes too long
fn panic_after<T, F>(d: Duration, f: F) -> T
where
    T: Send + 'static,
    F: FnOnce() -> T,
    F: Send + 'static,
{
    let (done_tx, done_rx) = mpsc::channel();
    let handle = thread::spawn(move || {
        let val = f();
        done_tx.send(()).expect("Unable to send completion signal");
        val
    });

    match done_rx.recv_timeout(d) {
        Ok(_) => handle.join().expect("Thread panicked"),
        Err(_) => panic!("Thread took too long"),
    }
}

// Checks to see if a file can be walked over and read properly, or fail if it can not be read
fn can_read(path: &Path) {
    let data = std::fs::read(&path).unwrap();

    let cursor = Cursor::new(data);
    let mut cfb = match CompoundFile::open(cursor) {
        Ok(cfb) => cfb,
        Err(_) => return,
    };

    #[allow(clippy::needless_collect)]
    let stream_paths = cfb
        .walk()
        .filter(|e| e.is_stream())
        .map(|e| e.path().to_path_buf())
        .collect::<Vec<_>>();

    let _unused = stream_paths
        .into_iter()
        .map(|s| -> Result<Vec<u8>, std::io::Error> {
            let mut data = Vec::new();
            cfb.open_stream(&s)?.read_to_end(&mut data)?;
            Ok(data)
        })
        .collect::<Vec<_>>();
}

/// Regression test for https://github.com/mdsteele/rust-cfb/issues/16.
#[test]
#[should_panic(
    expected = "Found reference to mini sector 123456789, but MiniFAT has \
                only 2 entries"
)]
fn invalid_mini_sector_issue_16() {
    // Create a CFB file with a mini stream.
    let cursor = Cursor::new(Vec::new());
    let mut comp = CompoundFile::create(cursor).unwrap();
    let version = comp.version();
    comp.create_stream("foo").unwrap().write_all(&[0u8; 80]).unwrap();
    let mut cursor = comp.into_inner();

    // Corrupt the starting mini sector ID of the stream.  Due to how we
    // constructed the CFB file, this will be at byte 116 of the second
    // 128-byte directory entry in the third sector of the CFB file.
    let offset = 116 + 128 * 1 + (version.sector_len() as u64) * 2;
    cursor.seek(SeekFrom::Start(offset)).unwrap();
    cursor.write_u32::<LittleEndian>(123456789).unwrap();

    // Re-open the CFB file and try to read the mini stream.
    let mut comp = CompoundFile::open(cursor).unwrap();
    let mut data = Vec::new();
    comp.open_stream("foo").unwrap().read_to_end(&mut data).unwrap();
}

/// Regression test for https://github.com/mdsteele/rust-cfb/issues/16.
#[test]
#[should_panic(expected = "DIFAT chain includes duplicate sector index 0")]
fn infinite_loop_difat_issue_17() {
    let data = vec![
        208, 207, 17, 224, 161, 177, 26, 225, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
        128, 0, 0, 0, 0, 62, 0, 3, 0, 254, 255, 9, 0, 6, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 255,
        255, 255, 255, 255, 255, 255, 27, 80, 255, 255, 253, 0, 0, 0, 254,
        255, 255, 255, 28, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 8, 0,
        0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 12, 0, 0, 0, 13, 0, 0, 0,
        14, 0, 0, 0, 15, 208, 207, 17, 224, 161, 177, 26, 225, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 3, 0, 254, 255, 9, 0, 6, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 16,
        0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 254, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0,
        0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0,
        0, 19, 0, 0, 0, 20, 0, 1, 0, 0, 0, 0, 0, 9, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 253, 255, 255, 255, 27, 0, 0, 0, 254, 255, 255, 255,
        28, 0, 0, 0, 5, 0, 0, 0, 0, 255, 27, 0, 0, 0, 254, 255, 255, 255, 28,
        0, 0, 0, 5, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 62, 0, 3, 0, 254, 255, 9,
        0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
        0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 254, 255,
        255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 27, 0, 0, 0,
        254, 255, 255, 255, 28, 0, 0, 0, 5, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 253, 255, 255, 255, 27, 0, 0, 0, 254, 255, 255, 255, 28, 0, 0, 0,
        5, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255, 255,
    ];
    CompoundFile::open(Cursor::new(data)).unwrap();
}

#[test]
fn check_for_infinite_loops() {
    // Loop through the provided files
    for entry in read_dir("tests/infinite_loops_fuzzed").unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();

        // Test will panic if it takes more than 1 second to load the file ie. stuck in a loop
        panic_after(Duration::from_secs(1), move || can_read(&path))
    }
}
<|endoftext|>


<commit_before>extern crate fitsio;
extern crate ndarray;

use std::ops::{Deref, Range};
use fitsio::fitsfile::ReadImage;
use fitsio::types::HduInfo;
use fitsio::{FitsFile, FitsHdu};
use fitsio::errors::Result;

// Newtype so we can implement ReadImage
#[derive(Debug, Default)]
pub struct NdArray(ndarray::Array2<u32>);

impl Deref for NdArray {
    type Target = ndarray::Array2<u32>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl ReadImage for NdArray {
    fn read_section(
        _fits_file: &mut FitsFile,
        _hdu: &FitsHdu,
        _range: Range<usize>,
    ) -> Result<Self> {
        unimplemented!()
    }

    fn read_rows(
        fits_file: &mut FitsFile,
        hdu: &FitsHdu,
        start_row: usize,
        num_rows: usize,
    ) -> Result<Self> {
        if num_rows == 0 || num_rows == 1 {
            unimplemented!("not implemented for ndarray::Array2")
        }
        let data: Vec<u32> = ReadImage::read_rows(fits_file, hdu, start_row, num_rows)?;
        let arr = ndarray::Array::from_vec(data);
        let row_length = arr.len() / num_rows;
        Ok(NdArray(arr.into_shape((num_rows, row_length)).unwrap()))
    }

    fn read_row(_fits_file: &mut FitsFile, _hdu: &FitsHdu, _row: usize) -> Result<Self> {
        unimplemented!()
    }

    fn read_region(
        _fits_file: &mut FitsFile,
        _hdu: &FitsHdu,
        _ranges: &[&Range<usize>],
    ) -> Result<Self> {
        unimplemented!()
    }

    fn read_image(fits_file: &mut FitsFile, hdu: &FitsHdu) -> Result<Self> {
        let data: Vec<u32> = ReadImage::read_image(fits_file, hdu)?;
        let arr = ndarray::Array::from_vec(data);
        match hdu.info {
            HduInfo::ImageInfo { ref shape, .. } => {
                Ok(NdArray(arr.into_shape((shape[0], shape[1])).unwrap()))
            }
            _ => unreachable!(),
        }
    }
}

fn run() -> std::result::Result<(), Box<std::error::Error>> {
    let mut f = FitsFile::open("../testdata/full_example.fits")?;
    let hdu = f.primary_hdu()?;

    {
        /* Check read_image */
        let data: NdArray = hdu.read_image(&mut f)?;
        assert_eq!(data.dim(), (100, 100));
        assert_eq!(data[[20, 5]], 152);
    }

    {
        /* Check read_rows */
        let data: NdArray = hdu.read_rows(&mut f, 0, 2)?;
        assert_eq!(data.dim(), (2, 100));
        assert_eq!(data[[1, 52]], 184);
    }

    Ok(())
}

fn main() {
    run().unwrap();
}
<commit_msg>Implement read_row<commit_after>extern crate fitsio;
extern crate ndarray;

use std::ops::{Deref, Range};
use fitsio::fitsfile::ReadImage;
use fitsio::types::HduInfo;
use fitsio::{FitsFile, FitsHdu};
use fitsio::errors::Result;

// Newtype so we can implement ReadImage
#[derive(Debug, Default)]
pub struct NdArray(ndarray::Array2<u32>);

impl Deref for NdArray {
    type Target = ndarray::Array2<u32>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl ReadImage for NdArray {
    fn read_section(
        _fits_file: &mut FitsFile,
        _hdu: &FitsHdu,
        _range: Range<usize>,
    ) -> Result<Self> {
        unimplemented!()
    }

    fn read_rows(
        fits_file: &mut FitsFile,
        hdu: &FitsHdu,
        start_row: usize,
        num_rows: usize,
    ) -> Result<Self> {
        if num_rows == 0 || num_rows == 1 {
            unimplemented!("not implemented for ndarray::Array2")
        }
        let data: Vec<u32> = ReadImage::read_rows(fits_file, hdu, start_row, num_rows)?;
        let arr = ndarray::Array::from_vec(data);
        let row_length = arr.len() / num_rows;
        Ok(NdArray(arr.into_shape((num_rows, row_length)).unwrap()))
    }

    fn read_row(fits_file: &mut FitsFile, hdu: &FitsHdu, row: usize) -> Result<Self> {
        Self::read_rows(fits_file, hdu, row, 1)
    }

    fn read_region(
        _fits_file: &mut FitsFile,
        _hdu: &FitsHdu,
        _ranges: &[&Range<usize>],
    ) -> Result<Self> {
        unimplemented!()
    }

    fn read_image(fits_file: &mut FitsFile, hdu: &FitsHdu) -> Result<Self> {
        let data: Vec<u32> = ReadImage::read_image(fits_file, hdu)?;
        let arr = ndarray::Array::from_vec(data);
        match hdu.info {
            HduInfo::ImageInfo { ref shape, .. } => {
                Ok(NdArray(arr.into_shape((shape[0], shape[1])).unwrap()))
            }
            _ => unreachable!(),
        }
    }
}

fn run() -> std::result::Result<(), Box<std::error::Error>> {
    let mut f = FitsFile::open("../testdata/full_example.fits")?;
    let hdu = f.primary_hdu()?;

    {
        /* Check read_image */
        let data: NdArray = hdu.read_image(&mut f)?;
        assert_eq!(data.dim(), (100, 100));
        assert_eq!(data[[20, 5]], 152);
    }

    {
        /* Check read_rows */
        let data: NdArray = hdu.read_rows(&mut f, 0, 2)?;
        assert_eq!(data.dim(), (2, 100));
        assert_eq!(data[[1, 52]], 184);
    }

    Ok(())
}

fn main() {
    run().unwrap();
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use std::sync::atomic::{AtomicBool, AtomicI64, Ordering};

/// BaseMetric is a struct used by `Counter` and `Gauge`
struct BaseMetric {
    counter_name: String,
    counter_help: String,
    counter: AtomicI64,
}

impl BaseMetric {
    pub fn new(counter_name: String, counter_help: String) -> Self {
        Self {
            counter_name,
            counter_help,
            counter: std::sync::atomic::AtomicI64::new(0),
        }
    }

    pub fn inc_by(&self, i: i64) {
        self.counter.fetch_add(i, Ordering::Relaxed);
    }

    pub fn inc(&self) {
        self.inc_by(1);
    }
}

/// PushMetricFormat contains a single function which converts the
/// metric into a string format which can be pushed to Prometheus
pub trait PushMetricFormat {
    fn get_push_metric_format(&self) -> String;
}

/// A Counter is a cumulative metric that represents a single
/// monotonically increasing counter whose value can only
/// increase or be reset to zero on restart.
pub struct Counter {
    base_counter: BaseMetric,
}

impl Counter {
    pub fn new(counter_name: String, counter_help: String) -> Self {
        Self {
            base_counter: BaseMetric::new(counter_name, counter_help),
        }
    }

    pub fn inc_by(&self, i: i64) {
        self.base_counter.inc_by(i);
    }

    pub fn inc(&self) {
        self.base_counter.inc();
    }
}

impl PushMetricFormat for Counter {
    fn get_push_metric_format(&self) -> String {
        format!(
            "# HELP {} {}\n# TYPE {} {}\n{} {}\n",
            self.base_counter.counter_name,
            self.base_counter.counter_help,
            self.base_counter.counter_name,
            "counter",
            self.base_counter.counter_name,
            self.base_counter.counter.load(Ordering::Relaxed)
        )
    }
}

/// A Gauge is a metric that represents a single
/// numerical value that can arbitrarily go up and down.
pub struct Gauge {
    base_counter: BaseMetric,
    has_been_set: AtomicBool,
}

impl Gauge {
    pub fn new(counter_name: String, counter_help: String) -> Self {
        Self {
            base_counter: BaseMetric::new(counter_name, counter_help),
            has_been_set: AtomicBool::new(false),
        }
    }
}

impl PushMetricFormat for Gauge {
    fn get_push_metric_format(&self) -> String {
        if self.has_been_set.load(Ordering::Relaxed) {
            format!(
                "# HELP {} {}\n# TYPE {} {}\n{} {}\n",
                self.base_counter.counter_name,
                self.base_counter.counter_help,
                self.base_counter.counter_name,
                "gauge",
                self.base_counter.counter_name,
                self.base_counter.counter.load(Ordering::Relaxed)
            )
        } else {
            String::new()
        }
    }
}

pub trait Metrics {
    fn get_metrics(&self) -> Vec<&dyn PushMetricFormat>;
}
<commit_msg>[secure-counters] Implement gauge<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use std::sync::atomic::{AtomicBool, AtomicI64, Ordering};

/// BaseMetric is a struct used by `Counter` and `Gauge`
struct BaseMetric {
    counter_name: String,
    counter_help: String,
    counter: AtomicI64,
}

impl BaseMetric {
    pub fn new(counter_name: String, counter_help: String) -> Self {
        Self {
            counter_name,
            counter_help,
            counter: std::sync::atomic::AtomicI64::new(0),
        }
    }

    pub fn inc(&self) {
        self.inc_by(1);
    }

    pub fn inc_by(&self, i: i64) {
        self.counter.fetch_add(i, Ordering::Relaxed);
    }

    pub fn set(&self, i: i64) {
        self.counter.store(i, Ordering::Relaxed);
    }
}

/// PushMetricFormat contains a single function which converts the
/// metric into a string format which can be pushed to Prometheus
pub trait PushMetricFormat {
    fn get_push_metric_format(&self) -> String;
}

/// A Counter is a cumulative metric that represents a single
/// monotonically increasing counter whose value can only
/// increase or be reset to zero on restart.
pub struct Counter {
    base_counter: BaseMetric,
}

impl Counter {
    pub fn new(counter_name: String, counter_help: String) -> Self {
        Self {
            base_counter: BaseMetric::new(counter_name, counter_help),
        }
    }

    pub fn inc(&self) {
        self.base_counter.inc();
    }

    pub fn inc_by(&self, i: i64) {
        self.base_counter.inc_by(i);
    }
}

impl PushMetricFormat for Counter {
    fn get_push_metric_format(&self) -> String {
        format!(
            "# HELP {} {}\n# TYPE {} {}\n{} {}\n",
            self.base_counter.counter_name,
            self.base_counter.counter_help,
            self.base_counter.counter_name,
            "counter",
            self.base_counter.counter_name,
            self.base_counter.counter.load(Ordering::Relaxed)
        )
    }
}

/// A Gauge is a metric that represents a single
/// numerical value that can arbitrarily go up and down.
pub struct Gauge {
    base_counter: BaseMetric,
    has_been_set: AtomicBool,
}

impl Gauge {
    pub fn new(counter_name: String, counter_help: String) -> Self {
        Self {
            base_counter: BaseMetric::new(counter_name, counter_help),
            has_been_set: AtomicBool::new(false),
        }
    }

    pub fn set(&self, i: i64) {
        self.base_counter.set(i)
    }
}

impl PushMetricFormat for Gauge {
    fn get_push_metric_format(&self) -> String {
        if self.has_been_set.load(Ordering::Relaxed) {
            format!(
                "# HELP {} {}\n# TYPE {} {}\n{} {}\n",
                self.base_counter.counter_name,
                self.base_counter.counter_help,
                self.base_counter.counter_name,
                "gauge",
                self.base_counter.counter_name,
                self.base_counter.counter.load(Ordering::Relaxed)
            )
        } else {
            String::new()
        }
    }
}

pub trait Metrics {
    fn get_metrics(&self) -> Vec<&dyn PushMetricFormat>;
}
<|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 goto definition feature

use crate::{
    location::to_lsp_location_of_graphql_literal,
    lsp::GotoDefinitionResponse,
    lsp_runtime_error::{LSPRuntimeError, LSPRuntimeResult},
    resolution_path::utils::find_selection_parent_type,
    resolution_path::{
        IdentParent, IdentPath, LinkedFieldPath, ResolutionPath, ResolvePosition, ScalarFieldPath,
        SelectionParent, TypeConditionPath,
    },
    server::LSPState,
    LSPExtraDataProvider,
};
use common::PerfLogger;
use graphql_ir::Program;
use interner::StringKey;
use lsp_types::{
    request::{GotoDefinition, Request},
    Url,
};
use schema::Schema;
use std::{
    collections::HashMap,
    path::PathBuf,
    str,
    sync::{Arc, RwLock},
};

fn get_goto_definition_response<'a>(
    node_path: ResolutionPath<'a>,
    project_name: StringKey,
    source_programs: &Arc<RwLock<HashMap<StringKey, Program>>>,
    root_dir: &PathBuf,
    // https://github.com/rust-lang/rust-clippy/issues/3971
    #[allow(clippy::borrowed_box)] extra_data_provider: &Box<dyn LSPExtraDataProvider + 'static>,
) -> LSPRuntimeResult<GotoDefinitionResponse> {
    match node_path {
        ResolutionPath::Ident(IdentPath {
            inner: fragment_name,
            parent: IdentParent::FragmentSpreadName(_),
        }) => {
            if let Some(source_program) = source_programs.read().unwrap().get(&project_name) {
                let fragment = source_program
                    .fragment(fragment_name.value)
                    .ok_or_else(|| {
                        LSPRuntimeError::UnexpectedError(format!(
                            "Could not find fragment with name {}",
                            fragment_name
                        ))
                    })?;

                Ok(GotoDefinitionResponse::Scalar(
                    to_lsp_location_of_graphql_literal(fragment.name.location, root_dir)?,
                ))
            } else {
                Err(LSPRuntimeError::UnexpectedError(format!(
                    "Project name {} not found",
                    project_name
                )))
            }
        }
        ResolutionPath::Ident(IdentPath {
            inner: field_name,
            parent:
                IdentParent::LinkedFieldName(LinkedFieldPath {
                    inner: _,
                    parent: selection_path,
                }),
        }) => resolve_field(
            field_name.value.to_string(),
            selection_path.parent,
            project_name,
            source_programs,
            root_dir,
            extra_data_provider,
        ),
        ResolutionPath::Ident(IdentPath {
            inner: field_name,
            parent:
                IdentParent::ScalarFieldName(ScalarFieldPath {
                    inner: _,
                    parent: selection_path,
                }),
        }) => resolve_field(
            field_name.value.to_string(),
            selection_path.parent,
            project_name,
            source_programs,
            root_dir,
            extra_data_provider,
        ),
        ResolutionPath::Ident(IdentPath {
            inner: _,
            parent:
                IdentParent::TypeConditionType(TypeConditionPath {
                    inner: type_condition,
                    parent: _,
                }),
        }) => {
            let provider_response = extra_data_provider
                .resolve_field_definition(
                    project_name.to_string(),
                    root_dir,
                    type_condition.type_.value.to_string(),
                    None,
                )
                .ok_or(LSPRuntimeError::ExpectedError)?;
            let (path, line) = provider_response.map_err(|e| -> LSPRuntimeError {
                LSPRuntimeError::UnexpectedError(format!(
                    "Error resolving field definition location: {}",
                    e
                ))
            })?;
            Ok(GotoDefinitionResponse::Scalar(get_location(&path, line)?))
        }
        _ => Err(LSPRuntimeError::ExpectedError),
    }
}

fn resolve_field<'a>(
    field_name: String,
    selection_parent: SelectionParent<'a>,
    project_name: StringKey,
    source_programs: &Arc<RwLock<HashMap<StringKey, Program>>>,
    root_dir: &PathBuf,
    // https://github.com/rust-lang/rust-clippy/issues/3971
    #[allow(clippy::borrowed_box)] extra_data_provider: &Box<dyn LSPExtraDataProvider + 'static>,
) -> LSPRuntimeResult<GotoDefinitionResponse> {
    let programs = source_programs.read().unwrap();
    let source_program = programs.get(&project_name).ok_or_else(|| {
        LSPRuntimeError::UnexpectedError(format!("Project name {} not found", project_name))
    })?;

    let parent_type = find_selection_parent_type(selection_parent, &source_program.schema)
        .ok_or(LSPRuntimeError::ExpectedError)?;

    let parent_name = source_program.schema.get_type_name(parent_type);

    let provider_response = extra_data_provider
        .resolve_field_definition(
            project_name.to_string(),
            root_dir,
            parent_name.to_string(),
            Some(field_name),
        )
        .ok_or(LSPRuntimeError::ExpectedError)?;
    let (path, line) = provider_response.map_err(|e| -> LSPRuntimeError {
        LSPRuntimeError::UnexpectedError(format!(
            "Error resolving field definition location: {}",
            e
        ))
    })?;
    Ok(GotoDefinitionResponse::Scalar(get_location(&path, line)?))
}

pub(crate) fn on_goto_definition<TPerfLogger: PerfLogger + 'static>(
    state: &mut LSPState<TPerfLogger>,
    params: <GotoDefinition as Request>::Params,
) -> LSPRuntimeResult<<GotoDefinition as Request>::Result> {
    let (document, position_span, project_name) =
        state.extract_executable_document_from_text(params, 1)?;
    let path = document.resolve((), position_span);

    let goto_definition_response = get_goto_definition_response(
        path,
        project_name,
        state.get_source_programs_ref(),
        state.root_dir(),
        &state.extra_data_provider,
    )?;

    Ok(Some(goto_definition_response))
}

fn get_location(path: &str, line: u64) -> Result<lsp_types::Location, LSPRuntimeError> {
    let start = lsp_types::Position { line, character: 0 };
    let range = lsp_types::Range { start, end: start };

    let uri = Url::parse(&format!("file://{}", path)).map_err(|e| {
        LSPRuntimeError::UnexpectedError(format!("Could not parse path as URL: {}", e))
    })?;

    Ok(lsp_types::Location { uri, range })
}
<commit_msg>Change unwrap() to expect() with specific error messages<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 goto definition feature

use crate::{
    location::to_lsp_location_of_graphql_literal,
    lsp::GotoDefinitionResponse,
    lsp_runtime_error::{LSPRuntimeError, LSPRuntimeResult},
    resolution_path::utils::find_selection_parent_type,
    resolution_path::{
        IdentParent, IdentPath, LinkedFieldPath, ResolutionPath, ResolvePosition, ScalarFieldPath,
        SelectionParent, TypeConditionPath,
    },
    server::LSPState,
    LSPExtraDataProvider,
};
use common::PerfLogger;
use graphql_ir::Program;
use interner::StringKey;
use lsp_types::{
    request::{GotoDefinition, Request},
    Url,
};
use schema::Schema;
use std::{
    collections::HashMap,
    path::PathBuf,
    str,
    sync::{Arc, RwLock},
};

fn get_goto_definition_response<'a>(
    node_path: ResolutionPath<'a>,
    project_name: StringKey,
    source_programs: &Arc<RwLock<HashMap<StringKey, Program>>>,
    root_dir: &PathBuf,
    // https://github.com/rust-lang/rust-clippy/issues/3971
    #[allow(clippy::borrowed_box)] extra_data_provider: &Box<dyn LSPExtraDataProvider + 'static>,
) -> LSPRuntimeResult<GotoDefinitionResponse> {
    match node_path {
        ResolutionPath::Ident(IdentPath {
            inner: fragment_name,
            parent: IdentParent::FragmentSpreadName(_),
        }) => {
            if let Some(source_program) = source_programs
                .read()
                .expect("get_goto_definition_response: expect to acquire a read lock on programs")
                .get(&project_name)
            {
                let fragment = source_program
                    .fragment(fragment_name.value)
                    .ok_or_else(|| {
                        LSPRuntimeError::UnexpectedError(format!(
                            "Could not find fragment with name {}",
                            fragment_name
                        ))
                    })?;

                Ok(GotoDefinitionResponse::Scalar(
                    to_lsp_location_of_graphql_literal(fragment.name.location, root_dir)?,
                ))
            } else {
                Err(LSPRuntimeError::UnexpectedError(format!(
                    "Project name {} not found",
                    project_name
                )))
            }
        }
        ResolutionPath::Ident(IdentPath {
            inner: field_name,
            parent:
                IdentParent::LinkedFieldName(LinkedFieldPath {
                    inner: _,
                    parent: selection_path,
                }),
        }) => resolve_field(
            field_name.value.to_string(),
            selection_path.parent,
            project_name,
            source_programs,
            root_dir,
            extra_data_provider,
        ),
        ResolutionPath::Ident(IdentPath {
            inner: field_name,
            parent:
                IdentParent::ScalarFieldName(ScalarFieldPath {
                    inner: _,
                    parent: selection_path,
                }),
        }) => resolve_field(
            field_name.value.to_string(),
            selection_path.parent,
            project_name,
            source_programs,
            root_dir,
            extra_data_provider,
        ),
        ResolutionPath::Ident(IdentPath {
            inner: _,
            parent:
                IdentParent::TypeConditionType(TypeConditionPath {
                    inner: type_condition,
                    parent: _,
                }),
        }) => {
            let provider_response = extra_data_provider
                .resolve_field_definition(
                    project_name.to_string(),
                    root_dir,
                    type_condition.type_.value.to_string(),
                    None,
                )
                .ok_or(LSPRuntimeError::ExpectedError)?;
            let (path, line) = provider_response.map_err(|e| -> LSPRuntimeError {
                LSPRuntimeError::UnexpectedError(format!(
                    "Error resolving field definition location: {}",
                    e
                ))
            })?;
            Ok(GotoDefinitionResponse::Scalar(get_location(&path, line)?))
        }
        _ => Err(LSPRuntimeError::ExpectedError),
    }
}

fn resolve_field<'a>(
    field_name: String,
    selection_parent: SelectionParent<'a>,
    project_name: StringKey,
    source_programs: &Arc<RwLock<HashMap<StringKey, Program>>>,
    root_dir: &PathBuf,
    // https://github.com/rust-lang/rust-clippy/issues/3971
    #[allow(clippy::borrowed_box)] extra_data_provider: &Box<dyn LSPExtraDataProvider + 'static>,
) -> LSPRuntimeResult<GotoDefinitionResponse> {
    let programs = source_programs
        .read()
        .expect("get_goto_definition_response: expect to acquire a read lock on programs");
    let source_program = programs.get(&project_name).ok_or_else(|| {
        LSPRuntimeError::UnexpectedError(format!("Project name {} not found", project_name))
    })?;

    let parent_type = find_selection_parent_type(selection_parent, &source_program.schema)
        .ok_or(LSPRuntimeError::ExpectedError)?;

    let parent_name = source_program.schema.get_type_name(parent_type);

    let provider_response = extra_data_provider
        .resolve_field_definition(
            project_name.to_string(),
            root_dir,
            parent_name.to_string(),
            Some(field_name),
        )
        .ok_or(LSPRuntimeError::ExpectedError)?;
    let (path, line) = provider_response.map_err(|e| -> LSPRuntimeError {
        LSPRuntimeError::UnexpectedError(format!(
            "Error resolving field definition location: {}",
            e
        ))
    })?;
    Ok(GotoDefinitionResponse::Scalar(get_location(&path, line)?))
}

pub(crate) fn on_goto_definition<TPerfLogger: PerfLogger + 'static>(
    state: &mut LSPState<TPerfLogger>,
    params: <GotoDefinition as Request>::Params,
) -> LSPRuntimeResult<<GotoDefinition as Request>::Result> {
    let (document, position_span, project_name) =
        state.extract_executable_document_from_text(params, 1)?;
    let path = document.resolve((), position_span);

    let goto_definition_response = get_goto_definition_response(
        path,
        project_name,
        state.get_source_programs_ref(),
        state.root_dir(),
        &state.extra_data_provider,
    )?;

    Ok(Some(goto_definition_response))
}

fn get_location(path: &str, line: u64) -> Result<lsp_types::Location, LSPRuntimeError> {
    let start = lsp_types::Position { line, character: 0 };
    let range = lsp_types::Range { start, end: start };

    let uri = Url::parse(&format!("file://{}", path)).map_err(|e| {
        LSPRuntimeError::UnexpectedError(format!("Could not parse path as URL: {}", e))
    })?;

    Ok(lsp_types::Location { uri, range })
}
<|endoftext|>