You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: no_dupe_keys.rs
    path of file: ./repos/deno_lint/src/rules
    
    the code of the file until where you have to start completion: // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

use super::{Context, LintRule};
use crate::handler::{Handler, Traverse};
use crate::swc_util::StringRepr;
use crate::Program;
use deno_ast::view::{
  GetterProp, KeyValueProp, MethodProp, ObjectLit, Prop, PropOrSpread,
  SetterProp,
};
use deno_ast::{SourceRange, SourceRanged};
use derive_more::Display;
use std::collections::hash_map::Entry;
use std::collections::HashMap;

#[derive(Debug)]
pub struct NoDupeKeys;

const CODE: &str = "no-dupe-keys";

#[derive(Display)]
enum NoDupeKeysMessage {
  #[display(fmt = "Duplicate key '{}'", _0)]
  Duplicate(String),
}

#[derive(Display)]
enum NoDupeKeysHint {
  #[display(fmt = "Remove or rename the duplicate key")]
  RemoveOrRename,
}

impl LintRule for NoDupeKeys {
  fn tags(&self) -> &'static [&'static str] {
    &["recommended"]
  }

  fn code(&self) -> &'static str {
    CODE
  }

  fn lint_program_with_ast_view(
    &self,
    context: &mut Context,
    program: Program,
  ) {
    NoDupeKeysHandler.traverse(program, context);
  }

  #[cfg(feature = "docs")]
  fn docs(&self) -> &'static str {
    include_str!("../../docs/rules/no_dupe_keys.md")
  }
}

struct NoDupeKeysHandler;

impl NoDupeKeysHandler {
  fn report(
    &mut self,
    range: SourceRange,
    key: impl Into<String>,
    ctx: &mut Context,
  ) {
    ctx.add_diagnostic_with_hint(
      range,
      CODE,
      NoDupeKeysMessage::Duplicate(key.into()),
      NoDupeKeysHint::RemoveOrRename,
    );
  }

  fn check_key<S: Into<String>>(
    &mut self,
    obj_range: SourceRange,
    key: Option<S>,
    keys: &mut HashMap<String, PropertyInfo>,
    ctx: &mut Context,
  ) {
    if let Some(key) = key {
      let key = key.into();

      match keys.entry(key) {
        Entry::Occupied(occupied) => {
          self.report(obj_range, occupied.key(), ctx);
        }
        Entry::Vacant(vacant) => {
          vacant.insert(PropertyInfo::default());
        }
      }
    }
  }

  fn check_getter<S: Into<String>>(
    &mut self,
    obj_range: SourceRange,
    key: Option<S>,
    keys: &mut HashMap<String, PropertyInfo>,
    ctx: &mut Context,
  ) {
    if let Some(key) = key {
      let key = key.into();

      match keys.entry(key) {
        Entry::Occupied(mut occupied) => {
          if occupied.get().setter_only() {
            occupied.get_mut().getter = true;
          } else {
            self.report(obj_range, occupied.key(), ctx);
          }
        }
        Entry::Vacant(vacant) => {
          vacant.insert(PropertyInfo {
            getter: true,
            setter: false,
          });
        }
      }
    }
  }

  fn check_setter<S: Into<String>>(
    &mut self,
    obj_range: SourceRange,
    key: Option<S>,
    keys: &mut HashMap<String, PropertyInfo>,
    ctx: &mut Context,
  ) {
    if let Some(key) = key {
      let key = key.into();

      match keys.entry(key) {
        Entry::Occupied(mut occupied) => {
          if occupied.get().getter_only() {
            occupied.get_mut().setter = true;
          } else {
            self.report(obj_range, occupied.key(), ctx);
          }
        }
        Entry::Vacant(vacant) => {
          vacant.insert(PropertyInfo {
            getter: false,
            setter: true,
          });
        }
      }
    }
  }
}

#[derive(Clone, Copy, Default)]
struct PropertyInfo {
  getter: bool,
  setter: bool,
}

impl PropertyInfo {
  fn getter_only(&self) -> bool {
    self.getter && !self.setter
  }

  fn setter_only(&self) -> bool {
    self.setter && !self.getter
  }
}

impl Handler for NoDupeKeysHandler {
  fn object_lit(&mut self, obj_lit: &ObjectLit, ctx: &mut Context) {
    let range = obj_lit.range();
    let mut keys: HashMap<String, PropertyInfo> = HashMap::new();

    for prop in obj_lit.props {
      if let PropOrSpread::Prop(prop) = prop 
    
  fn no_dupe_keys_invalid() {
    assert_lint_err! {
      NoDupeKeys,
      r#"var foo = { bar: "baz", bar: "qux" };"#: [
        {
          col: 10,
          message: variant!(NoDupeKeysMessage, Duplicate, "bar"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var foo = { bar: "baz", bar: "qux", quux: "boom", quux: "bang" };"#: [
        {
          col: 10,
          message: variant!(NoDupeKeysMessage, Duplicate, "bar"),
          hint: NoDupeKeysHint::RemoveOrRename,
        },
        {
          col: 10,
          message: variant!(NoDupeKeysMessage, Duplicate, "quux"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var foo = { bar: "baz", "bar": "qux" };"#: [
        {
          col: 10,
          message: variant!(NoDupeKeysMessage, Duplicate, "bar"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var foo = { 1: "baz", 0x1: "qux" };"#: [
        {
          col: 10,
          message: variant!(NoDupeKeysMessage, Duplicate, "1"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var foo = { bar: "baz", get bar() {} };"#: [
        {
          col: 10,
          message: variant!(NoDupeKeysMessage, Duplicate, "bar"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var foo = { bar: "baz", set bar() {} };"#: [
        {
          col: 10,
          message: variant!(NoDupeKeysMessage, Duplicate, "bar"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var x = { a: b, ['a']: b };"#: [
        {
          col: 8,
          message: variant!(NoDupeKeysMessage, Duplicate, "a"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var x = { '': 1, '': 2 };"#: [
        {
          col: 8,
          message: variant!(NoDupeKeysMessage, Duplicate, ""),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var x = { '': 1, [``]: 2 };"#: [
        {
          col: 8,
          message: variant!(NoDupeKeysMessage, Duplicate, ""),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var x = { 012: 1, 10: 2 };"#: [
        {
          col: 8,
          message: variant!(NoDupeKeysMessage, Duplicate, "10"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var x = { 0b1: 1, 1: 2 };"#: [
        {
          col: 8,
          message: variant!(NoDupeKeysMessage, Duplicate, "1"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var x = { 0o1: 1, 1: 2 };"#: [
        {
          col: 8,
          message: variant!(NoDupeKeysMessage, Duplicate, "1"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var x = { 1n: 1, 1: 2 };"#: [
        {
          col: 8,
          message: variant!(NoDupeKeysMessage, Duplicate, "1"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var x = { 1_0: 1, 10: 2 };"#: [
        {
          col: 8,
          message: variant!(NoDupeKeysMessage, Duplicate, "10"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var x = { "z": 1, z: 2 };"#: [
        {
          col: 8,
          message: variant!(NoDupeKeysMessage, Duplicate, "z"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"
var foo = {
  bar: 1,
  bar: 1,
}
"#: [
        {
          line: 2,
          col: 10,
          message: variant!(NoDupeKeysMessage, Duplicate, "bar"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var x = { a: 1, b: { a: 2 }, get b() {} };"#: [
        {
          col: 8,
          message: variant!(NoDupeKeysMessage, Duplicate, "b"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],
      r#"var x = ({ '/(?<zero>0)/': 1, [/(?<zero>0)/]: 2 })"#: [
        {
          col: 9,
          message: variant!(NoDupeKeysMessage, Duplicate, "/(?<zero>0)/"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ],

      // nested
      r#"
let x = {
  key: {
    dup: 0,
    dup: 1,
  },
};
"#: [
        {
          line: 3,
          col: 7,
          message: variant!(NoDupeKeysMessage, Duplicate, "dup"),
          hint: NoDupeKeysHint::RemoveOrRename,
        }
      ]
    };
  }