<commit_before>path = require 'path'

_ = require 'underscore-plus'
async = require 'async'
CSON = require 'season'
fs = require 'fs-plus'
{Emitter, CompositeDisposable} = require 'event-kit'
Q = require 'q'
{includeDeprecatedAPIs, deprecate} = require 'grim'

ModuleCache = require './module-cache'
ScopedProperties = require './scoped-properties'

packagesCache = require('../package.json')?._atomPackages ? {}

# Loads and activates a package's main module and resources such as
# stylesheets, keymaps, grammar, editor properties, and menus.
module.exports =
class Package
  @isBundledPackagePath: (packagePath) ->
    if atom.packages.devMode
      return false unless atom.packages.resourcePath.startsWith("#{process.resourcesPath}#{path.sep}")

    @resourcePathWithTrailingSlash ?= "#{atom.packages.resourcePath}#{path.sep}"
    packagePath?.startsWith(@resourcePathWithTrailingSlash)

  @loadMetadata: (packagePath, ignoreErrors=false) ->
    packageName = path.basename(packagePath)
    if @isBundledPackagePath(packagePath)
      metadata = packagesCache[packageName]?.metadata
    unless metadata?
      if metadataPath = CSON.resolve(path.join(packagePath, 'package'))
        try
          metadata = CSON.readFileSync(metadataPath)
        catch error
          throw error unless ignoreErrors
    metadata ?= {}
    metadata.name = packageName

    if includeDeprecatedAPIs and metadata.stylesheetMain?
      deprecate("Use the `mainStyleSheet` key instead of `stylesheetMain` in the `package.json` of `#{packageName}`", {packageName})
      metadata.mainStyleSheet = metadata.stylesheetMain

    if includeDeprecatedAPIs and metadata.stylesheets?
      deprecate("Use the `styleSheets` key instead of `stylesheets` in the `package.json` of `#{packageName}`", {packageName})
      metadata.styleSheets = metadata.stylesheets

    metadata

  keymaps: null
  menus: null
  stylesheets: null
  stylesheetDisposables: null
  grammars: null
  settings: null
  mainModulePath: null
  resolvedMainModulePath: false
  mainModule: null

  ###
  Section: Construction
  ###

  constructor: (@path, @metadata) ->
    @emitter = new Emitter
    @metadata ?= Package.loadMetadata(@path)
    @bundledPackage = Package.isBundledPackagePath(@path)
    @name = @metadata?.name ? path.basename(@path)
    ModuleCache.add(@path, @metadata)
    @reset()

  ###
  Section: Event Subscription
  ###

  # Essential: Invoke the given callback when all packages have been activated.
  #
  # * `callback` {Function}
  #
  # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
  onDidDeactivate: (callback) ->
    @emitter.on 'did-deactivate', callback

  ###
  Section: Instance Methods
  ###

  enable: ->
    atom.config.removeAtKeyPath('core.disabledPackages', @name)

  disable: ->
    atom.config.pushAtKeyPath('core.disabledPackages', @name)

  isTheme: ->
    @metadata?.theme?

  measure: (key, fn) ->
    startTime = Date.now()
    value = fn()
    @[key] = Date.now() - startTime
    value

  getType: -> 'atom'

  getStyleSheetPriority: -> 0

  load: ->
    @measure 'loadTime', =>
      try
        @loadKeymaps()
        @loadMenus()
        @loadStylesheets()
        @settingsPromise = @loadSettings()
        @requireMainModule() unless @hasActivationCommands()
      catch error
        @handleError("Failed to load the #{@name} package", error)
    this

  reset: ->
    @stylesheets = []
    @keymaps = []
    @menus = []
    @grammars = []
    @settings = []

  activate: ->
    @grammarsPromise ?= @loadGrammars()

    unless @activationDeferred?
      @activationDeferred = Q.defer()
      @measure 'activateTime', =>
        try
          @activateResources()
          if @hasActivationCommands()
            @subscribeToActivationCommands()
          else
            @activateNow()
        catch error
          @handleError("Failed to activate the #{@name} package", error)

    Q.all([@grammarsPromise, @settingsPromise, @activationDeferred.promise])

  activateNow: ->
    try
      @activateConfig()
      @activateStylesheets()
      if @requireMainModule()
        @mainModule.activate?(atom.packages.getPackageState(@name) ? {})
        @mainActivated = true
        @activateServices()
    catch error
      @handleError("Failed to activate the #{@name} package", error)

    @activationDeferred?.resolve()

  activateConfig: ->
    return if @configActivated

    @requireMainModule()
    if @mainModule?
      if @mainModule.config? and typeof @mainModule.config is 'object'
        atom.config.setSchema @name, {type: 'object', properties: @mainModule.config}
      else if includeDeprecatedAPIs and @mainModule.configDefaults? and typeof @mainModule.configDefaults is 'object'
        deprecate """Use a config schema instead. See the configuration section
        of https://atom.io/docs/latest/hacking-atom-package-word-count and
        https://atom.io/docs/api/latest/Config for more details"""
        atom.config.setDefaults(@name, @mainModule.configDefaults)
      @mainModule.activateConfig?()
    @configActivated = true

  activateStylesheets: ->
    return if @stylesheetsActivated

    @stylesheetDisposables = new CompositeDisposable

    priority = @getStyleSheetPriority()
    for [sourcePath, source] in @stylesheets
      if match = path.basename(sourcePath).match(/[^.]*\.([^.]*)\./)
        context = match[1]
      else if @metadata.theme is 'syntax'
        context = 'atom-text-editor'
      else
        context = undefined

      @stylesheetDisposables.add(atom.styles.addStyleSheet(source, {sourcePath, priority, context}))
    @stylesheetsActivated = true

  activateResources: ->
    @activationDisposables = new CompositeDisposable
    @activationDisposables.add(atom.keymaps.add(keymapPath, map)) for [keymapPath, map] in @keymaps

    for [menuPath, map] in @menus when map['context-menu']?
      try
        @activationDisposables.add(atom.contextMenu.add(map['context-menu']))<commit_msg>Add package name to Grim.deprecate call for configDefaults<commit_after>path = require 'path'

_ = require 'underscore-plus'
async = require 'async'
CSON = require 'season'
fs = require 'fs-plus'
{Emitter, CompositeDisposable} = require 'event-kit'
Q = require 'q'
{includeDeprecatedAPIs, deprecate} = require 'grim'

ModuleCache = require './module-cache'
ScopedProperties = require './scoped-properties'

packagesCache = require('../package.json')?._atomPackages ? {}

# Loads and activates a package's main module and resources such as
# stylesheets, keymaps, grammar, editor properties, and menus.
module.exports =
class Package
  @isBundledPackagePath: (packagePath) ->
    if atom.packages.devMode
      return false unless atom.packages.resourcePath.startsWith("#{process.resourcesPath}#{path.sep}")

    @resourcePathWithTrailingSlash ?= "#{atom.packages.resourcePath}#{path.sep}"
    packagePath?.startsWith(@resourcePathWithTrailingSlash)

  @loadMetadata: (packagePath, ignoreErrors=false) ->
    packageName = path.basename(packagePath)
    if @isBundledPackagePath(packagePath)
      metadata = packagesCache[packageName]?.metadata
    unless metadata?
      if metadataPath = CSON.resolve(path.join(packagePath, 'package'))
        try
          metadata = CSON.readFileSync(metadataPath)
        catch error
          throw error unless ignoreErrors
    metadata ?= {}
    metadata.name = packageName

    if includeDeprecatedAPIs and metadata.stylesheetMain?
      deprecate("Use the `mainStyleSheet` key instead of `stylesheetMain` in the `package.json` of `#{packageName}`", {packageName})
      metadata.mainStyleSheet = metadata.stylesheetMain

    if includeDeprecatedAPIs and metadata.stylesheets?
      deprecate("Use the `styleSheets` key instead of `stylesheets` in the `package.json` of `#{packageName}`", {packageName})
      metadata.styleSheets = metadata.stylesheets

    metadata

  keymaps: null
  menus: null
  stylesheets: null
  stylesheetDisposables: null
  grammars: null
  settings: null
  mainModulePath: null
  resolvedMainModulePath: false
  mainModule: null

  ###
  Section: Construction
  ###

  constructor: (@path, @metadata) ->
    @emitter = new Emitter
    @metadata ?= Package.loadMetadata(@path)
    @bundledPackage = Package.isBundledPackagePath(@path)
    @name = @metadata?.name ? path.basename(@path)
    ModuleCache.add(@path, @metadata)
    @reset()

  ###
  Section: Event Subscription
  ###

  # Essential: Invoke the given callback when all packages have been activated.
  #
  # * `callback` {Function}
  #
  # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
  onDidDeactivate: (callback) ->
    @emitter.on 'did-deactivate', callback

  ###
  Section: Instance Methods
  ###

  enable: ->
    atom.config.removeAtKeyPath('core.disabledPackages', @name)

  disable: ->
    atom.config.pushAtKeyPath('core.disabledPackages', @name)

  isTheme: ->
    @metadata?.theme?

  measure: (key, fn) ->
    startTime = Date.now()
    value = fn()
    @[key] = Date.now() - startTime
    value

  getType: -> 'atom'

  getStyleSheetPriority: -> 0

  load: ->
    @measure 'loadTime', =>
      try
        @loadKeymaps()
        @loadMenus()
        @loadStylesheets()
        @settingsPromise = @loadSettings()
        @requireMainModule() unless @hasActivationCommands()
      catch error
        @handleError("Failed to load the #{@name} package", error)
    this

  reset: ->
    @stylesheets = []
    @keymaps = []
    @menus = []
    @grammars = []
    @settings = []

  activate: ->
    @grammarsPromise ?= @loadGrammars()

    unless @activationDeferred?
      @activationDeferred = Q.defer()
      @measure 'activateTime', =>
        try
          @activateResources()
          if @hasActivationCommands()
            @subscribeToActivationCommands()
          else
            @activateNow()
        catch error
          @handleError("Failed to activate the #{@name} package", error)

    Q.all([@grammarsPromise, @settingsPromise, @activationDeferred.promise])

  activateNow: ->
    try
      @activateConfig()
      @activateStylesheets()
      if @requireMainModule()
        @mainModule.activate?(atom.packages.getPackageState(@name) ? {})
        @mainActivated = true
        @activateServices()
    catch error
      @handleError("Failed to activate the #{@name} package", error)

    @activationDeferred?.resolve()

  activateConfig: ->
    return if @configActivated

    @requireMainModule()
    if @mainModule?
      if @mainModule.config? and typeof @mainModule.config is 'object'
        atom.config.setSchema @name, {type: 'object', properties: @mainModule.config}
      else if includeDeprecatedAPIs and @mainModule.configDefaults? and typeof @mainModule.configDefaults is 'object'
        deprecate("""Use a config schema instead. See the configuration section
        of https://atom.io/docs/latest/hacking-atom-package-word-count and
        https://atom.io/docs/api/latest/Config for more details""", {packageName: @name})
        atom.config.setDefaults(@name, @mainModule.configDefaults)
      @mainModule.activateConfig?()
    @configActivated = true

  activateStylesheets: ->
    return if @stylesheetsActivated

    @stylesheetDisposables = new CompositeDisposable

    priority = @getStyleSheetPriority()
    for [sourcePath, source] in @stylesheets
      if match = path.basename(sourcePath).match(/[^.]*\.([^.]*)\./)
        context = match[1]
      else if @metadata.theme is 'syntax'
        context = 'atom-text-editor'
      else
        context = undefined

      @stylesheetDisposables.add(atom.styles.addStyleSheet(source, {sourcePath, priority, context}))
    @stylesheetsActivated = true

  activateResources: ->
    @activationDisposables = new CompositeDisposable
    @activationDisposables.add(atom.keymaps.add(keymapPath, map)) for [keymapPath, map] in @keymaps

    for [menuPath, map] in @menus when map['context-menu']?
      try
        @activationDisposables.add(atom.contextMenu.add(map['context-menu']))
{'fraction_non_alphanumeric': 0.11940049958368026, 'fraction_numerical': 0.00033305578684429644, 'mean_word_length': 3.428834808259587, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 41, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2803924', 'n_tokens_mistral': 3600, 'n_tokens_neox': 3476, 'n_words': 823}