ronantakizawa/codereview-bench huggingface dataset:
Repository: tauri-apps/tauri
File: crates/tauri-cli/src/dev.rs (Rust)

Code before:
          error,
        })?;
        if !status.success() {
          crate::error::bail!(
            "beforeDevCommand `{}` failed with exit code {}",
            before_dev,
            status.code().unwrap_or_default()
          );
        }
      } else {
        command.stdin(Stdio::piped());
        command.stdout(os_pipe::dup_stdout().unwrap());
        command.stderr(os_pipe::dup_stderr().unwrap());

        let child = SharedChild::spawn(&mut command)
          .unwrap_or_else(|_| panic!("failed to run `{before_dev}`"));
        let child = Arc::new(child);
        let child_ = child.clone();

        std::thread::spawn(move || {
          let status = child_
            .wait()
            .expect("failed to wait on \"beforeDevCommand\"");
          if !(status.success() || KILL_BEFORE_DEV_FLAG.load(Ordering::Relaxed)) {
            log::error!("The \"beforeDevCommand\" terminated with a non-zero status code.");
            exit(status.code().unwrap_or(1));
          }
        });

        BEFORE_DEV.set(Mutex::new(child)).unwrap();

        let _ = ctrlc::set_handler(move || {
          kill_before_dev_process();
          exit(130);
        });
      }
    }
  }

  if options.runner.is_none() {
    options.runner = config
      .lock()
      .unwrap()
      .as_ref()
      .unwrap()
      .build
      .runner
      .clone();
  }

  let mut cargo_features = config

Review comment (suggestion):
Although implausible, there's nothing stopping the child to exit before the flag gets initialized. Because the thread is spawned, this panic might be hard to detect.

Code after:
            if cfg!(windows) { "cmd /S /C" } else { "sh -c" }
          ),
          error,
        })?;
        if !status.success() {
          crate::error::bail!(
            "beforeDevCommand `{}` failed with exit code {}",
            before_dev,
            status.code().unwrap_or_default()
          );
        }
      } else {
        command.stdin(Stdio::piped());
        command.stdout(os_pipe::dup_stdout().unwrap());
        command.stderr(os_pipe::dup_stderr().unwrap());

        let child = SharedChild::spawn(&mut command)
          .unwrap_or_else(|_| panic!("failed to run `{before_dev}`"));
        let child = Arc::new(child);
        let child_ = child.clone();

        std::thread::spawn(move || {
          let status = child_
            .wait()
            .expect("failed to wait on \"beforeDevCommand\"");
          if !(status.success() || KILL_BEFORE_DEV_FLAG.load(Ordering::Relaxed)) {
            log::error!("The \"beforeDevCommand\" terminated with a non-zero status code.");
            exit(status.code().unwrap_or(1));
          }
        });

        BEFORE_DEV.set(Mutex::new(child)).unwrap();

        let _ = ctrlc::set_handler(move || {
          kill_before_dev_process();
          exit(130);
        });
      }
    }
  }

  if options.runner.is_none() {
    options.runner = config
      .lock()
      .unwrap()
      .as_ref()
      .unwrap()
      .build
      .runner
      .clone();
  }
Repository: tauri-apps/tauri
File: crates/tauri-build/src/lib.rs (Rust)

Code before:
      }
    }
  }

  if target_triple.contains("ios") {
    println!(
      "cargo:rustc-env=IPHONEOS_DEPLOYMENT_TARGET={}",
      config.bundle.ios.minimum_system_version
    );
  }

  if target_triple.contains("windows") {
    use semver::Version;
    use tauri_winres::{VersionInfo, WindowsResource};

    let window_icon_path = attributes
      .windows_attributes
      .window_icon_path
      .unwrap_or_else(|| {
        config
          .bundle
          .icon
          .iter()
          .find(|i| i.ends_with(".ico"))
          .map(AsRef::as_ref)
          .unwrap_or_else(|| "icons/icon.ico")
          .into()
      });

    let mut res = WindowsResource::new();

    if let Some(manifest) = attributes.windows_attributes.app_manifest {
      res.set_manifest(&manifest);
    }

    if let Some(version_str) = &config.version {
      if let Ok(v) = Version::parse(version_str) {
        let version = (v.major << 48) | (v.minor << 32) | (v.patch << 16);
        res.set_version_info(VersionInfo::FILEVERSION, version);
        res.set_version_info(VersionInfo::PRODUCTVERSION, version);
      }
    }

    if let Some(product_name) = &config.product_name {
      res.set("ProductName", product_name);
    }

    let company_name = config.bundle.publisher.unwrap_or_else(|| {
      config
        .identifier
        .split('.')

Review comment (suggestion):
```suggestion
          .unwrap_or("icons/icon.ico")
```

Code after:
      }
    }
  }

  if target_triple.contains("ios") {
    println!(
      "cargo:rustc-env=IPHONEOS_DEPLOYMENT_TARGET={}",
      config.bundle.ios.minimum_system_version
    );
  }

  if target_triple.contains("windows") {
    use semver::Version;
    use tauri_winres::{VersionInfo, WindowsResource};

    let window_icon_path = attributes
      .windows_attributes
      .window_icon_path
      .unwrap_or_else(|| {
        config
          .bundle
          .icon
          .iter()
          .find(|i| i.ends_with(".ico"))
          .map(AsRef::as_ref)
          .unwrap_or("icons/icon.ico")
          .into()
      });

    let mut res = WindowsResource::new();

    if let Some(manifest) = attributes.windows_attributes.app_manifest {
      res.set_manifest(&manifest);
    }

    if let Some(version_str) = &config.version {
      if let Ok(v) = Version::parse(version_str) {
        let version = (v.major << 48) | (v.minor << 32) | (v.patch << 16);
        res.set_version_info(VersionInfo::FILEVERSION, version);
        res.set_version_info(VersionInfo::PRODUCTVERSION, version);
      }
    }

    if let Some(product_name) = &config.product_name {
      res.set("ProductName", product_name);
    }

    let company_name = config.bundle.publisher.unwrap_or_else(|| {
      config
        .identifier
        .split('.')
Repository: th-ch/youtube-music
File: src/plugins/discord/main.ts (TypeScript)

Code before:
const clientId = '1177081335727267940';

export interface Info {
  rpc: DiscordClient;
  ready: boolean;
  autoReconnect: boolean;
  lastSongInfo?: SongInfo;
}

const info: Info = {
  rpc: new DiscordClient({
    clientId,
  }),
  ready: false,
  autoReconnect: true,
  lastSongInfo: undefined,
};

/**
 * @type {(() => void)[]}
 */
const refreshCallbacks: (() => void)[] = [];

const truncateString = (str: string, length: number): string => {
  if (str.length > length)
    return `${str.substring(0, str.length - 3)}...`;
  return str;
}

const resetInfo = () => {
  info.ready = false;
  clearTimeout(clearActivity);
  if (dev()) {
    console.log(LoggerPrefix, t('plugins.discord.backend.disconnected'));
  }

  for (const cb of refreshCallbacks) {
    cb();
  }
};

const connectTimeout = () =>
  new Promise((resolve, reject) =>
    setTimeout(() => {
      if (!info.autoReconnect || info.rpc.isConnected) {
        return;
      }

      info.rpc.login().then(resolve).catch(reject);
    }, 5000),
  );

Review comment (suggestion):
```suggestion
    return `${str.substring(0, 125)}...`;
```

Code after:
const clientId = '1177081335727267940';

export interface Info {
  rpc: DiscordClient;
  ready: boolean;
  autoReconnect: boolean;
  lastSongInfo?: SongInfo;
}

const info: Info = {
  rpc: new DiscordClient({
    clientId,
  }),
  ready: false,
  autoReconnect: true,
  lastSongInfo: undefined,
};

/**
 * @type {(() => void)[]}
 */
const refreshCallbacks: (() => void)[] = [];

const truncateString = (str: string, length: number): string => {
  if (str.length > length)
    return `${str.substring(0, length - 3)}...`;
  return str;
}

const resetInfo = () => {
  info.ready = false;
  clearTimeout(clearActivity);
  if (dev()) {
    console.log(LoggerPrefix, t('plugins.discord.backend.disconnected'));
  }

  for (const cb of refreshCallbacks) {
    cb();
  }
};

const connectTimeout = () =>
  new Promise((resolve, reject) =>
    setTimeout(() => {
      if (!info.autoReconnect || info.rpc.isConnected) {
        return;
      }

      info.rpc.login().then(resolve).catch(reject);
    }, 5000),
  );
Repository: th-ch/youtube-music
File: src/plugins/synced-lyrics/renderer/utils.tsx (TypeScript)

Code before:
export const romanizeJapanese = async (line: string) =>
  (await kuroshiro.get()).convert(line, {
    to: 'romaji',
    mode: 'spaced',
  }) ?? line;

export const romanizeHangul = (line: string) =>
  esHangulRomanize(hanja.translate(line, 'SUBSTITUTION'));

export const romanizeChinese = (line: string) => {
  return line.replaceAll(/[\u4E00-\u9FFF]+/g, (match) =>
    pinyin.convertToPinyin(match, ' ', true),
  );
};

const thaiSegmenter = Intl.Segmenter.supportedLocalesOf('th').includes('th')
  ? new Intl.Segmenter('th', { granularity: 'word' })
  : null;

export const romanizeThai = (line: string) => {
  if (!thaiSegmenter) return romanizeThaiFrag(line);

  const segments = Array.from(thaiSegmenter.segment(line));
  const latin = segments
    .map((segment) => segment.isWordLike ? romanizeThaiFrag(segment.segment) + ' ' : segment.segment.trim())
    .join('')
    .trim();

  return latin;
};

const handlers: Record<string, (line: string) => Promise<string> | string> = {
  ja: romanizeJapanese,
  ko: romanizeHangul,
  zh: romanizeChinese,
  th: romanizeThai,
};

export const romanize = async (line: string) => {
  const lang = detect(line);

  const NO_OP = (l: string) => l;
  const handler = handlers[lang] ?? NO_OP;

  line = await handler(line);

  if (hasJapanese([line])) line = await romanizeJapanese(line);
  if (hasKorean([line])) line = romanizeHangul(line);
  if (hasChinese([line])) line = romanizeChinese(line);
  if (hasThai([line])) line = romanizeThai(line);


Review comment (suggestion):
```suggestion
    .map((segment) => segment.isWordLike ? romanizeThaiFrag(segment.segment) : segment.segment.trim())
    .join(' ')
```

Code after:
export const romanizeHangul = (line: string) =>
  esHangulRomanize(hanja.translate(line, 'SUBSTITUTION'));

export const romanizeChinese = (line: string) => {
  return line.replaceAll(/[\u4E00-\u9FFF]+/g, (match) =>
    pinyin.convertToPinyin(match, ' ', true),
  );
};

const thaiSegmenter = Intl.Segmenter.supportedLocalesOf('th').includes('th')
  ? new Intl.Segmenter('th', { granularity: 'word' })
  : null;

export const romanizeThai = (line: string) => {
  if (!thaiSegmenter) return romanizeThaiFrag(line);

  const segments = Array.from(thaiSegmenter.segment(line));
  const latin = segments
    .map((segment) =>
      segment.isWordLike
        ? romanizeThaiFrag(segment.segment)
        : segment.segment.trim(),
    )
    .join(' ')
    .trim();

  return latin;
};

const handlers: Record<string, (line: string) => Promise<string> | string> = {
  ja: romanizeJapanese,
  ko: romanizeHangul,
  zh: romanizeChinese,
  th: romanizeThai,
};

export const romanize = async (line: string) => {
  const lang = detect(line);

  const handler = handlers[lang];
  if (handler) {
    return handler(line);
  }

  // fallback
  if (hasJapanese([line])) line = await romanizeJapanese(line);
  if (hasKorean([line])) line = romanizeHangul(line);
  if (hasChinese([line])) line = romanizeChinese(line);
  if (hasThai([line])) line = romanizeThai(line);

  return line;
Repository: th-ch/youtube-music
File: src/plugins/custom-output-device/renderer.ts (TypeScript)

Code before:
    return;
  }
  await context.setSinkId(options.output)
}

const audioCanPlayHandler = ({ detail: { audioContext } }: CustomEvent<Compressor>) => {
  audio_context = audioContext
  updateSinkId(audioContext);
}

export const onPlayerApiReady = async (_: YoutubePlayer, context: RendererContext<CustomOutputPluginConfig>) => {
  options = await context.getConfig();
  cached_context = context

  document.addEventListener('ytmd:audio-can-play', audioCanPlayHandler, { once: true, passive: true });
  await updateDeviceList();
}

export const stop = () => {
  document.removeEventListener('ytmd:audio-can-play', audioCanPlayHandler)
}

export const onConfigChange = (config: CustomOutputPluginConfig) => {
  options = config;
  updateSinkId(audio_context);
}


Review comment (suggestion):
You should use the `createRenderer` util

```typescript
export const renderer = createRenderer({
    // ...
})
```

Code after:
  {
    options?: CustomOutputPluginConfig;
    audioContext?: AudioContext;
    audioCanPlayHandler: (event: CustomEvent<Compressor>) => Promise<void>;
  },
  CustomOutputPluginConfig
>({
  async audioCanPlayHandler({ detail: { audioContext } }) {
    this.audioContext = audioContext;
    await updateSinkId(audioContext, this.options!.output);
  },

  async onPlayerApiReady(_: YoutubePlayer, context) {
    this.options = await context.getConfig();
    await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
    navigator.mediaDevices.ondevicechange = async () =>
      await updateDeviceList(context);

    document.addEventListener('ytmd:audio-can-play', this.audioCanPlayHandler, {
      once: true,
      passive: true,
    });
    await updateDeviceList(context);
  },

  stop() {
    document.removeEventListener(
      'ytmd:audio-can-play',
      this.audioCanPlayHandler,
    );
    navigator.mediaDevices.ondevicechange = null;
  },

  async onConfigChange(config) {
    this.options = config;
    await updateSinkId(this.audioContext, config.output);
  },
});
Repository: th-ch/youtube-music
File: src/plugins/custom-output-device/index.ts (TypeScript)

Code before:
    devices: {}
  } as CustomOutputPluginConfig,
  menu: async ({ setConfig, getConfig, window }) => {

    const promptDeviceSelector = async () => {
      const options = await getConfig();

      const response = await prompt({
        title: 'Select Output Device',
        label: 'Choose the output media device to be used',
        value: options.output || 'default',
        type: 'select',
        selectOptions: options.devices,
        width: 500,
        ...promptOptions(),
      }, window).catch(console.error);

      if (!response) return;
      options.output = response;
      setConfig(options);
    }

    return [
      {
        label: 'Select Device',
        click: () => promptDeviceSelector()
      }
    ]
  },

  renderer: {
    onPlayerApiReady,
    stop,
    onConfigChange,
  }
})


Review comment (suggestion):
```suggestion
        click: promptDeviceSelector
```

Code after:
    devices: {},
  } as CustomOutputPluginConfig,
  menu: ({ setConfig, getConfig, window }) => {
    const promptDeviceSelector = async () => {
      const options = await getConfig();

      const response = await prompt(
        {
          title: t('plugins.custom-output-device.prompt.device-selector.title'),
          label: t('plugins.custom-output-device.prompt.device-selector.label'),
          value: options.output || 'default',
          type: 'select',
          selectOptions: options.devices,
          width: 500,
          ...promptOptions(),
        },
        window,
      ).catch(console.error);

      if (!response) return;
      options.output = response;
      setConfig(options);
    };

    return [
      {
        label: t('plugins.custom-output-device.menu.device-selector'),
        click: promptDeviceSelector,
      },
    ];
  },

  renderer,
});
Repository: th-ch/youtube-music
File: src/plugins/custom-output-device/index.ts (TypeScript)

Code before:
// import { t } from "@/i18n";
import promptOptions from "@/providers/prompt-options";
import { createPlugin } from "@/utils";
import prompt from "custom-electron-prompt";
import { onConfigChange, onPlayerApiReady, stop } from "./renderer";

export interface CustomOutputPluginConfig {
  enabled: boolean;
  output: string;
  devices: Record<string, string>;
}


export default createPlugin({
  name: () => 'Custom Output Device',
  description: () => 'Configure a custom output media device for songs.',
  restartNeeded: true,
  config: {
    enabled: false,
    output: 'default',
    devices: {}
  } as CustomOutputPluginConfig,
  menu: async ({ setConfig, getConfig, window }) => {

    const promptDeviceSelector = async () => {
      const options = await getConfig();

      const response = await prompt({
        title: 'Select Output Device',
        label: 'Choose the output media device to be used',
        value: options.output || 'default',
        type: 'select',
        selectOptions: options.devices,
        width: 500,
        ...promptOptions(),
      }, window).catch(console.error);

      if (!response) return;
      options.output = response;
      setConfig(options);
    }

    return [
      {
        label: 'Select Device',
        click: () => promptDeviceSelector()
      }
    ]

Review comment (suggestion):
You are not using await in this scope.

```suggestion
  menu: ({ setConfig, getConfig, window }) => {
```

Code after:
import prompt from 'custom-electron-prompt';

import { t } from '@/i18n';
import promptOptions from '@/providers/prompt-options';
import { createPlugin } from '@/utils';
import { renderer } from './renderer';

export interface CustomOutputPluginConfig {
  enabled: boolean;
  output: string;
  devices: Record<string, string>;
}

export default createPlugin({
  name: () => t('plugins.custom-output-device.name'),
  description: () => t('plugins.custom-output-device.description'),
  restartNeeded: true,
  config: {
    enabled: false,
    output: 'default',
    devices: {},
  } as CustomOutputPluginConfig,
  menu: ({ setConfig, getConfig, window }) => {
    const promptDeviceSelector = async () => {
      const options = await getConfig();

      const response = await prompt(
        {
          title: t('plugins.custom-output-device.prompt.device-selector.title'),
          label: t('plugins.custom-output-device.prompt.device-selector.label'),
          value: options.output || 'default',
          type: 'select',
          selectOptions: options.devices,
          width: 500,
          ...promptOptions(),
        },
        window,
      ).catch(console.error);

      if (!response) return;
      options.output = response;
      setConfig(options);
    };

    return [
      {
        label: t('plugins.custom-output-device.menu.device-selector'),
        click: promptDeviceSelector,
Repository: th-ch/youtube-music
File: src/plugins/custom-output-device/renderer.ts (TypeScript)

Code before:
import { YoutubePlayer } from "@/types/youtube-player";
import { CustomOutputPluginConfig } from ".";
import { RendererContext } from "@/types/contexts";
import { createRenderer } from "@/utils";

const updateDeviceList = async (context: RendererContext<CustomOutputPluginConfig>) => {
  const new_devices: Record<string, string> = {};
  const devices = await navigator.mediaDevices.enumerateDevices().then(devices => devices.filter(device => device.kind === 'audiooutput'));
  for (const device of devices) {
    new_devices[device.deviceId] = device.label;
  }
  const options = await context.getConfig();
  options.devices = new_devices;
  context.setConfig(options);
}

const updateSinkId = async (audioContext?: AudioContext, sinkId?: string) => {
  if (!audioContext || !sinkId) return;

  if (!('setSinkId' in audioContext)) {
    console.log('setSinkId not in context')
    return;
  }
  if (typeof audioContext.setSinkId !== 'function') {
    console.log('setSinkId not a function')
    return;
  }
  await audioContext.setSinkId(sinkId)
}

export const renderer = createRenderer<{
  options?: CustomOutputPluginConfig;

Review comment (suggestion):
Use `camelCase` instead of `snake_case`.

```suggestion
  const newDevices: Record<string, string> = {};
```

like this.

Code after:
import { createRenderer } from '@/utils';

import type { YoutubePlayer } from '@/types/youtube-player';
import type { RendererContext } from '@/types/contexts';
import type { CustomOutputPluginConfig } from './index';

const updateDeviceList = async (
  context: RendererContext<CustomOutputPluginConfig>,
) => {
  const newDevices: Record<string, string> = {};
  const devices = await navigator.mediaDevices
    .enumerateDevices()
    .then((devices) =>
      devices.filter((device) => device.kind === 'audiooutput'),
    );
  for (const device of devices) {
    newDevices[device.deviceId] = device.label;
  }
  const options = await context.getConfig();
  options.devices = newDevices;
  context.setConfig(options);
};

const updateSinkId = async (audioContext?: AudioContext, sinkId?: string) => {
  if (!audioContext || !sinkId) return;
  if (!('setSinkId' in audioContext)) return;
  if (typeof audioContext.setSinkId !== 'function') return;

  await audioContext.setSinkId(sinkId);
};

export const renderer = createRenderer<
Repository: th-ch/youtube-music
File: src/plugins/custom-output-device/renderer.ts (TypeScript)

Code before:
import { type YoutubePlayer } from '@/types/youtube-player';
import { type CustomOutputPluginConfig } from '.';
import { type RendererContext } from '@/types/contexts';
import { createRenderer } from '@/utils';

const updateDeviceList = async (
  context: RendererContext<CustomOutputPluginConfig>,
) => {
  const newDevices: Record<string, string> = {};
  const devices = await navigator.mediaDevices
    .enumerateDevices()
    .then((devices) =>
      devices.filter((device) => device.kind === 'audiooutput'),
    );
  for (const device of devices) {
    newDevices[device.deviceId] = device.label;
  }
  const options = await context.getConfig();
  options.devices = newDevices;
  context.setConfig(options);
};

const updateSinkId = async (audioContext?: AudioContext, sinkId?: string) => {
  if (!audioContext || !sinkId) return;
  if (!('setSinkId' in audioContext)) return;
  if (typeof audioContext.setSinkId !== 'function') return;

  await audioContext.setSinkId(sinkId);
};

Review comment (suggestion):
```suggestion
import { createRenderer } from '@/utils';

import type { YoutubePlayer } from '@/types/youtube-player';
import type { RendererContext } from '@/types/contexts';
import type { CustomOutputPluginConfig } from './index';
```

Code after:
import { createRenderer } from '@/utils';

import type { YoutubePlayer } from '@/types/youtube-player';
import type { RendererContext } from '@/types/contexts';
import type { CustomOutputPluginConfig } from './index';

const updateDeviceList = async (
  context: RendererContext<CustomOutputPluginConfig>,
) => {
  const newDevices: Record<string, string> = {};
  const devices = await navigator.mediaDevices
    .enumerateDevices()
    .then((devices) =>
      devices.filter((device) => device.kind === 'audiooutput'),
    );
  for (const device of devices) {
    newDevices[device.deviceId] = device.label;
  }
  const options = await context.getConfig();
  options.devices = newDevices;
  context.setConfig(options);
};

const updateSinkId = async (audioContext?: AudioContext, sinkId?: string) => {
  if (!audioContext || !sinkId) return;
  if (!('setSinkId' in audioContext)) return;
  if (typeof audioContext.setSinkId !== 'function') return;

  await audioContext.setSinkId(sinkId);