<commit_before>const fs = require("fs")
const path = require("path")

import {AnonymousFunctionContext, ClassContext, InterfaceContext, TraitContext, UnknownClassContext} from "./class-context"
import {FileContext} from "./file-context"
import * as PHPError from "./php-error"
import PHPLint from "./php-lint"
import PHPAutoloader from "./php-autoloader"

/**
 * @type {boolean} If true, autoload failure may throw. This can help with
 * debugging unexpected loads.
 */
const DEBUG_AUTOLOAD = false

/** @type {number} The maximum depth we're willing to scan files at */
const MAX_DEPTH = Infinity

/**
 * @type {string[]} From `print json_encode(get_declared_classes(), JSON_PRETTY_PRINT);`
 */
const PHPClasses = JSON.parse(fs.readFileSync(__dirname + "/../../data/php-classes.json", "utf8"))

/**
 * @type {string[]} From `print json_encode(get_declared_interfaces(), JSON_PRETTY_PRINT);`
 */
const PHPInterfaces = JSON.parse(fs.readFileSync(__dirname + "/../../data/php-interfaces.json", "utf8"))

/**
 * This defines content that's defined from the global scope, ie. everything
 * that is not anonymous.
 */
export class GlobalContext {
    /**
     * This returns autoload config from the given composer.json
     * @param {?string} filename eg. /foo/bar/composer.json
     * @param {?string} vendor_path If unset, this will be based on the filename
     * @returns {?PHPAutoloader}
     */
    static autoloadFromComposer(filename, vendor_path = null) {
        if(!filename) return null
        /** @type {string} The current module (or whole project) root */
        let current_module_path = path.dirname(filename)
        try {
            let composer_config = JSON.parse(fs.readFileSync(filename, "utf8"))
            let autoload_paths = {}
            let classmap_paths = []
            if(composer_config.autoload) {
                let psr0 = composer_config.autoload["psr-0"]
                if(psr0) {
                    Object.keys(psr0).forEach(
                        prefix => {
                            autoload_paths[prefix] = [psr0[prefix]].map(
                                path => `${current_module_path}/${path}${prefix.replace(/[_\\]/g, "/")}/`
                            )
                        }
                    )
                }
                let psr4 = composer_config.autoload["psr-4"]
                if(psr4) {
                    Object.keys(psr4).forEach(
                        prefix => {
                            autoload_paths[prefix] = (psr4[prefix] instanceof Array ?
                                psr4[prefix] :
                                [psr4[prefix]]
                            ).map(
                                path => {
                                    if(path.match(/\/$/) || path == "") {
                                        return `${current_module_path}/${path}`
                                    } else {
                                        //console.log(`Path ${path} for ${prefix} is missing a trailing slash`)
                                        return `${current_module_path}/${path}/`
                                    }
                                }
                            )
                        }
                    )
                }
                let classmap = composer_config.autoload["classmap"]
                if(classmap) {
                    console.log("WARNING, this project uses classmap autoload, this is extremely unwise and takes non-trivial time to parse")
                    classmap_paths = classmap.map(
                        path => {
                            if(path.match(/\/$/) || path == "") {
                                return `${current_module_path}/${path}`
                            } else {
                                //console.log(`Path ${path} for ${prefix} is missing a trailing slash`)
                                return `${current_module_path}/${path}/`
                            }
                        }
                    )
                }
            }
            if(!vendor_path) {
                vendor_path = path.dirname(filename) + "/vendor"
            }
            let autoloader = new PHPAutoloader(autoload_paths, classmap_paths)
            if(composer_config.require) {
                Object.keys(composer_config.require).filter(
                    uid => uid.match(/\//)
                ).forEach(
                    uid => autoloader.add(
                        this.autoloadFromComposer(
                            `${vendor_path}/${uid}/composer.json`,
                            vendor_path
                        )
                    )
                )
            }
            return autoloader
        } catch(e) {
            if(e.errno == -2) {
                console.log(`${filename} missing, not installed?`)
                return new PHPAutoloader({})
            } else {
                throw e
            }
        }
    }

    /**
     * Builds the context
     */
    constructor() {
        /** @type {{[x: string]: ClassContext}} */
        this.classes = {}
        /** @type {{[x: string]: number}} The minimum depth for each class */
        this.depths = {
        }
        /** @type {{[x: string]: boolean | Error}} */
        this.results = {
        }
        /** @type {{[x: string]: boolean}} */
        this.filesSeen = {}

        /** @type {?string} */
        this.workingDirectory = null
        PHPClasses.forEach(
            name => this.addUnknownClass("\\" + name)
        )
        PHPInterfaces.forEach(
            name => this.addUnknownClass("\\" + name)
        )
        this.addUnknownClass("mixed")
        this.addUnknownClass("object")
    }

    /**
     * @type {{[x: number]: number}} The number of classes at each depth
     */
    get depthCounts() {
        let counts = {}
        Object.values(this.depths).forEach(n => {
            if(!counts[n]) counts[n] = 0
            counts[n]++
        })
        return counts
    }

    /**
     * Adds a known class
     * @param {string} name Fully qualified only
     * @param {?ClassContext} [superclass]
     * @param {?FileContext} [file_context]
     * @returns {ClassContext}
     */
    addClass(name, superclass = null, file_context = null) {
        if(this.classes[name] && !(this.classes[name] instanceof UnknownClassContext)) {
            return this.classes[name]
        } else {
            return this.classes[name] = new ClassContext(
                name,
                superclass,
                file_context
            )
        }
    }

    /**
     * Adds an unknown class. For when the real name isn't known and you have to
     * use a placeholder. You can get the name from the return value.
     * @param {?string} [name]
     * @returns {UnknownClassContext}
     */
    addUnknownClass(name = null) {
        if(!name) {
            name = "Unknown" + Math.random()
        }
        return this.classes[name] = new UnknownClassContext(name)
    }

    /**
     * Adds a known trait
     * @param {string} name Fully qualified only
     * @param {?ClassContext} [superclass]
     * @param {?FileContext} [file_context]
     * @returns {ClassContext}
     */
    addTrait(name, superclass = null, file_context = null) {
        return this.classes[name] = this.classes[name] || new TraitContext(
            name,
            superclass,
            file_context
        )
    }

    /**
     * Adds a known interface
     * @param {string} name Fully qualified only
     * @param {?ClassContext} [superclass]
     * @param {?FileContext} [file_context]
     * @returns {ClassContext}
     */
    addInterface(name, superclass = null, file_context = null) {
        return this.classes[name] = this.classes[name] || new InterfaceContext(
            name,
            superclass,
            file_context
        )
    }

    /**
     * Checks a PHP file. This will typically affect what's defined in the
     * global namespace, including classes.
     * @param {string} filename
     * @param {number} [depth]
     */
    checkFile(filename, depth = 0) {
        let resolved_filename = path.resolve(filename)
        if(!this.filesSeen[resolved_filename]) {
            this.filesSeen[resolved_filename] = true
            PHPLint.checkFileSync(filename, false, depth)
        }
    }

    /**
     * Given a path for the current file, walks up the tree looking for composer.json.
     *
     * @param {string} actual_path eg. /foo/bar/lib/Baz/
     * @return {?string} eg. /foo/bar/composer.json
     */
    findComposerConfig(actual_path) {
        while(actual_path.match(/^\/+[^\/]/)) {
            if(fs.existsSync(`${actual_path}/composer.json`)) {
                return `${actual_path}/composer.json`
            }
            actual_path = path.dirname(actual_path)
        }
        return null
    }

    /**
     * Finds the class context with the given name
     * @param {string} name Fully qualified only
     * @param {FileContext} file_context
     * @param {number} [depth] The current load depth
     * @returns {?ClassContext}
     */
    findClass(name, file_context, depth = 0) {
        if(name.match(/ -> /)) {
            return AnonymousFunctionContext.inst
        }
        let load_depth = depth + 1
        let filename = file_context.filename
        if(this.classes.hasOwnProperty(name)) {
            let c = this.classes[name]
            if(c.fileContext && load_depth < this.depths[c.fileContext.filename]) {
                this.depths[c.fileContext.filename] = load_depth
            }
            return this.classes[name]
        } else if(load_depth > MAX_DEPTH) {
            return new UnknownClassContext(name)
        } else {
            this.addUnknownClass(name)
            // Autoload go!
            if(!this.autoloader) {
                this.autoloader = GlobalContext.autoloadFromComposer(
                    this.findComposerConfig(file_context.directory)
                )
            }
            if(this.autoloader) {
                let full_path = this.autoloader.findClassFile(name)
                if(full_path) {
                    this.checkFile(full_path, load_depth)
                    if(!this.classes[name]) {
                        console.log(
                            `Class ${name} not found at ${full_path}`
                        )
                        this.addUnknownClass(name)
                    }
                    return this.classes[name]
                }
            }
            if(DEBUG_AUTOLOAD) {
                console.log(this.autoloader)
                throw new PHPError.ClassLoadFailed(`Could not load ${name}`)
            } else {
                console.log(`Could not load ${name}`)
                return this.classes[name]
            }
        }
    }
}<commit_msg>Look for composer from the working directory not the current file one<commit_after>const fs = require("fs")
const path = require("path")

import {AnonymousFunctionContext, ClassContext, InterfaceContext, TraitContext, UnknownClassContext} from "./class-context"
import {FileContext} from "./file-context"
import * as PHPError from "./php-error"
import PHPLint from "./php-lint"
import PHPAutoloader from "./php-autoloader"

/**
 * @type {boolean} If true, autoload failure may throw. This can help with
 * debugging unexpected loads.
 */
const DEBUG_AUTOLOAD = false

/** @type {number} The maximum depth we're willing to scan files at */
const MAX_DEPTH = Infinity

/**
 * @type {string[]} From `print json_encode(get_declared_classes(), JSON_PRETTY_PRINT);`
 */
const PHPClasses = JSON.parse(fs.readFileSync(__dirname + "/../../data/php-classes.json", "utf8"))

/**
 * @type {string[]} From `print json_encode(get_declared_interfaces(), JSON_PRETTY_PRINT);`
 */
const PHPInterfaces = JSON.parse(fs.readFileSync(__dirname + "/../../data/php-interfaces.json", "utf8"))

/**
 * This defines content that's defined from the global scope, ie. everything
 * that is not anonymous.
 */
export class GlobalContext {
    /**
     * This returns autoload config from the given composer.json
     * @param {?string} filename eg. /foo/bar/composer.json
     * @param {?string} vendor_path If unset, this will be based on the filename
     * @returns {?PHPAutoloader}
     */
    static autoloadFromComposer(filename, vendor_path = null) {
        if(!filename) return null
        /** @type {string} The current module (or whole project) root */
        let current_module_path = path.dirname(filename)
        try {
            let composer_config = JSON.parse(fs.readFileSync(filename, "utf8"))
            let autoload_paths = {}
            let classmap_paths = []
            if(composer_config.autoload) {
                let psr0 = composer_config.autoload["psr-0"]
                if(psr0) {
                    Object.keys(psr0).forEach(
                        prefix => {
                            autoload_paths[prefix] = [psr0[prefix]].map(
                                path => `${current_module_path}/${path}${prefix.replace(/[_\\]/g, "/")}/`
                            )
                        }
                    )
                }
                let psr4 = composer_config.autoload["psr-4"]
                if(psr4) {
                    Object.keys(psr4).forEach(
                        prefix => {
                            autoload_paths[prefix] = (psr4[prefix] instanceof Array ?
                                psr4[prefix] :
                                [psr4[prefix]]
                            ).map(
                                path => {
                                    if(path.match(/\/$/) || path == "") {
                                        return `${current_module_path}/${path}`
                                    } else {
                                        //console.log(`Path ${path} for ${prefix} is missing a trailing slash`)
                                        return `${current_module_path}/${path}/`
                                    }
                                }
                            )
                        }
                    )
                }
                let classmap = composer_config.autoload["classmap"]
                if(classmap) {
                    console.log("WARNING, this project uses classmap autoload, this is extremely unwise and takes non-trivial time to parse")
                    classmap_paths = classmap.map(
                        path => {
                            if(path.match(/\/$/) || path == "") {
                                return `${current_module_path}/${path}`
                            } else {
                                //console.log(`Path ${path} for ${prefix} is missing a trailing slash`)
                                return `${current_module_path}/${path}/`
                            }
                        }
                    )
                }
            }
            if(!vendor_path) {
                vendor_path = path.dirname(filename) + "/vendor"
            }
            let autoloader = new PHPAutoloader(autoload_paths, classmap_paths)
            if(composer_config.require) {
                Object.keys(composer_config.require).filter(
                    uid => uid.match(/\//)
                ).forEach(
                    uid => autoloader.add(
                        this.autoloadFromComposer(
                            `${vendor_path}/${uid}/composer.json`,
                            vendor_path
                        )
                    )
                )
            }
            return autoloader
        } catch(e) {
            if(e.errno == -2) {
                console.log(`${filename} missing, not installed?`)
                return new PHPAutoloader({})
            } else {
                throw e
            }
        }
    }

    /**
     * Builds the context
     */
    constructor() {
        /** @type {{[x: string]: ClassContext}} */
        this.classes = {}
        /** @type {{[x: string]: number}} The minimum depth for each class */
        this.depths = {
        }
        /** @type {{[x: string]: boolean | Error}} */
        this.results = {
        }
        /** @type {{[x: string]: boolean}} */
        this.filesSeen = {}

        /** @type {?string} */
        this.workingDirectory = null
        PHPClasses.forEach(
            name => this.addUnknownClass("\\" + name)
        )
        PHPInterfaces.forEach(
            name => this.addUnknownClass("\\" + name)
        )
        this.addUnknownClass("mixed")
        this.addUnknownClass("object")
    }

    /**
     * @type {{[x: number]: number}} The number of classes at each depth
     */
    get depthCounts() {
        let counts = {}
        Object.values(this.depths).forEach(n => {
            if(!counts[n]) counts[n] = 0
            counts[n]++
        })
        return counts
    }

    /**
     * Adds a known class
     * @param {string} name Fully qualified only
     * @param {?ClassContext} [superclass]
     * @param {?FileContext} [file_context]
     * @returns {ClassContext}
     */
    addClass(name, superclass = null, file_context = null) {
        if(this.classes[name] && !(this.classes[name] instanceof UnknownClassContext)) {
            return this.classes[name]
        } else {
            return this.classes[name] = new ClassContext(
                name,
                superclass,
                file_context
            )
        }
    }

    /**
     * Adds an unknown class. For when the real name isn't known and you have to
     * use a placeholder. You can get the name from the return value.
     * @param {?string} [name]
     * @returns {UnknownClassContext}
     */
    addUnknownClass(name = null) {
        if(!name) {
            name = "Unknown" + Math.random()
        }
        return this.classes[name] = new UnknownClassContext(name)
    }

    /**
     * Adds a known trait
     * @param {string} name Fully qualified only
     * @param {?ClassContext} [superclass]
     * @param {?FileContext} [file_context]
     * @returns {ClassContext}
     */
    addTrait(name, superclass = null, file_context = null) {
        return this.classes[name] = this.classes[name] || new TraitContext(
            name,
            superclass,
            file_context
        )
    }

    /**
     * Adds a known interface
     * @param {string} name Fully qualified only
     * @param {?ClassContext} [superclass]
     * @param {?FileContext} [file_context]
     * @returns {ClassContext}
     */
    addInterface(name, superclass = null, file_context = null) {
        return this.classes[name] = this.classes[name] || new InterfaceContext(
            name,
            superclass,
            file_context
        )
    }

    /**
     * Checks a PHP file. This will typically affect what's defined in the
     * global namespace, including classes.
     * @param {string} filename
     * @param {number} [depth]
     */
    checkFile(filename, depth = 0) {
        let resolved_filename = path.resolve(filename)
        if(!this.filesSeen[resolved_filename]) {
            this.filesSeen[resolved_filename] = true
            PHPLint.checkFileSync(filename, false, depth)
        }
    }

    /**
     * Given a path for the current file, walks up the tree looking for composer.json.
     *
     * @param {string} actual_path eg. /foo/bar/lib/Baz/
     * @return {?string} eg. /foo/bar/composer.json
     */
    findComposerConfig(actual_path) {
        while(actual_path.match(/^\/+[^\/]/)) {
            if(fs.existsSync(`${actual_path}/composer.json`)) {
                return `${actual_path}/composer.json`
            }
            actual_path = path.dirname(actual_path)
        }
        return null
    }

    /**
     * Finds the class context with the given name
     * @param {string} name Fully qualified only
     * @param {FileContext} file_context
     * @param {number} [depth] The current load depth
     * @returns {?ClassContext}
     */
    findClass(name, file_context, depth = 0) {
        if(name.match(/ -> /)) {
            return AnonymousFunctionContext.inst
        }
        let load_depth = depth + 1
        let filename = file_context.filename
        if(this.classes.hasOwnProperty(name)) {
            let c = this.classes[name]
            if(c.fileContext && load_depth < this.depths[c.fileContext.filename]) {
                this.depths[c.fileContext.filename] = load_depth
            }
            return this.classes[name]
        } else if(load_depth > MAX_DEPTH) {
            return new UnknownClassContext(name)
        } else {
            this.addUnknownClass(name)
            // Autoload go!
            if(!this.autoloader) {
                this.autoloader = GlobalContext.autoloadFromComposer(
                    this.findComposerConfig(this.workingDirectory)
                )
            }
            if(this.autoloader) {
                let full_path = this.autoloader.findClassFile(name)
                if(full_path) {
                    this.checkFile(full_path, load_depth)
                    if(!this.classes[name]) {
                        console.log(
                            `Class ${name} not found at ${full_path}`
                        )
                        this.addUnknownClass(name)
                    }
                    return this.classes[name]
                }
            }
            if(DEBUG_AUTOLOAD) {
                console.log(this.autoloader)
                throw new PHPError.ClassLoadFailed(`Could not load ${name}`)
            } else {
                console.log(`Could not load ${name}`)
                return this.classes[name]
            }
        }
    }
}<|endoftext|>


<commit_before>import Fs from 'fs'
import Path from 'path'
import Util from './util.js'

/**
 * Sizes required for the ICNS file.
 * @type {Array}
 */
const REQUIRED_IMAGE_SIZES = [32, 64, 128, 256, 512, 1024]

/**
 * The size of the ICNS header.
 * @type {Number}
 */
const HEADER_SIZE = 8

/**
 * Identifier of the ICNS file, in ASCII "icns".
 * @type {Number}
 */
const FILE_HEADER_ID = 'icns'

/**
 * ICNS file extension.
 * @type {String}
 */
const FILE_EXTENSION = '.icns'

/**
 * Information of the images, Mac OS 8.x (il32, is32, l8mk, s8mk) is unsupported.
 * If icp4, icp5, icp6 is present, Icon will not be supported because it can not be set as Folder of Finder.
 *
 * @type {Array.<ICNSIconInfo>}
 */
const ICON_INFOS = [
  // Normal
  {id: 'ic07', size: 128},
  {id: 'ic08', size: 256},
  {id: 'ic09', size: 512},
  {id: 'ic10', size: 1024},

  // Retina
  {id: 'ic11', size: 32},
  {id: 'ic12', size: 64},
  {id: 'ic13', size: 256},
  {id: 'ic14', size: 512}

  // TODO: Implement later...
  /*
  // Mac OS 8.5
  {id: 'is32', mask: 's8mk', size: 16},
  {id: 'il32', mask: 'l8mk', size: 32}
  */
]

/**
 * Generate the ICNS file from a PNG images.
 * However, Mac OS 8.x is unsupported.
 */
export default class ICNSGenerator {
  /**
   * Create the ICNS file from a PNG images.
   *
   * @param {Array.<ImageInfo>} images Information of the image files.
   * @param {String}            dir     Output destination the path of directory.
   * @param {Object}            options Options.
   * @param {Logger}            logger  Logger.
   *
   * @return {Promise} Promise object.
   */
  static generate (images, dir, options, logger) {
    return new Promise((resolve, reject) => {
      logger.log('ICNS:')

      const dest    = Path.join(dir, options.names.icns + FILE_EXTENSION)
      const targets = Util.filterImagesBySizes(images, Util.checkImageSizes(REQUIRED_IMAGE_SIZES, options, 'icns'))

      if (ICNSGenerator._createIcon(targets, dest)) {
        logger.log('  Create: ' + dest)
        resolve(dest)
      } else {
        Fs.unlinkSync(dest)
        reject(new Error('Faild to read/write image.'))
      }
    })
  }

  /**
   * Get the size of the required PNG.
   *
   * @return {Array.<Number>} Sizes.
   */
  static getRequiredImageSizes () {
    return REQUIRED_IMAGE_SIZES
  }

  /**
   * Creat a file header and icon blocks.
   *
   * @param {Array.<ImageInfo>} images Information of the image files.
   * @param {String}            dest   The path of the output destination file.
   *
   * @return {Boolean} "true" if it succeeds.
   */
  static _createIcon (images, dest) {
    // Write a temporary file size
    let fileSize = HEADER_SIZE
    let stream   = Fs.createWriteStream(dest)
    stream.write(ICNSGenerator._createFileHeader(fileSize), 'binary')

    for (let i = 0, max = ICON_INFOS.length; i < max; ++i) {
      const info = ICON_INFOS[i]
      const image = ICNSGenerator._imageFromIconSize(info.size, images)
      if (!(image)) {
        // Depending on the command line option, there may be no corresponding size
        continue
      }

      const block = ICNSGenerator._createIconBlock(info, image)
      if (block) {
        stream.write(block, 'binary')
        fileSize += block.length
      } else {
        fileSize = 0
        break
      }
    }

    stream.end()

    if (fileSize === 0) {
      return false
    }

    // Update an actual file size
    stream = Fs.createWriteStream(dest)
    stream.write(ICNSGenerator._createFileHeader(fileSize), 'binary')
    stream.end()

    return true
  }

  /**
   * Create an icon block.
   *
   * @param {ICNSIconInfo} info  Information of the icon.
   * @param {ImageInfo}    image Information of the image.
   *
   * @return {Buffer} If successful it wrote the icon block. "null" on failure.
   */
  static _createIconBlock (info, image) {
    switch (info.id) {
      case 'is32':
      case 'il32':
        return ICNSGenerator._createIconBlockPackBits(info.id, info.mask, image)

      default:
        return ICNSGenerator._createIconBlockPNG(info.id, image)
    }
  }

  /**
   * Create an icon block for PNG.
   *
   * @param {String}    id    Identifier of the icon.
   * @param {ImageInfo} image Information of the image.
   *
   * @return {Buffer} If successful it wrote the icon block. "null" on failure.
   */
  static _createIconBlockPNG (id, image) {
    const png = Fs.readFileSync(image.path)
    if (!(png)) {
      return null
    }

    const header = ICNSGenerator._createIconHeader(id, png.length)
    return Buffer.concat([header, png], header.length + png.length)
  }

  /**
   * Create an icon blocks (Color and mask) for PackBits.
   *
   * @param {String}    id    Identifier of the icon (color block).
   * @param {String}    mask  Identifier of the icon (mask block).
   * @param {ImageInfo} image Information of the image.
   *
   * @return {Buffer} If successful it wrote the icon block. "null" on failure.
   */
  static _createIconBlockPackBits (id, mask, image) {
    // TODO: Implement later...
    return null
  }

  /**
   * Create the ICNS file header.
   *
   * @param {Number} fileSize File size.
   *
   * @return {Buffer} Header data.
   */
  static _createFileHeader (fileSize) {
    const buffer = Buffer.alloc(HEADER_SIZE)
    buffer.write(FILE_HEADER_ID, 0, 'ascii')
    buffer.writeUInt32BE(fileSize, 4)

    return buffer
  }

  /**
   * Create the Icon header in ICNS file.
   *
   * @param {Object} id        Identifier of the icon.
   * @param {Number} imageSize Size of the image data.
   *
   * @return {Buffer} Header data.
   */
  static _createIconHeader (id, imageSize) {
    const buffer = Buffer.alloc(HEADER_SIZE)
    buffer.write(id, 0, 'ascii')
    buffer.writeUInt32BE(HEADER_SIZE + imageSize, 4)

    return buffer
  }

  /**
   * Select the support image from the icon size.
   *
   * @param {Number}            size   Sizo of icon.
   * @param {Array.<ImageInfo>} images File informations..
   *
   * @return {ImageInfo} If successful image information, otherwise null.
   */
  static _imageFromIconSize (size, images) {
    let result = null
    images.some((image) => {
      if (image.size === size) {
        result = image
        return true
      }

      return false
    })

    return result
  }
}
<commit_msg>#71 Implement a PackBits blocks<commit_after>import Fs from 'fs'
import Path from 'path'
import Util from './util.js'
import {PNG} from 'pngjs'
import PackBits from './packbits.js'
import { Buffer } from 'buffer'
import { Promise } from 'es6-promise'

/**
 * Sizes required for the ICNS file.
 * @type {Array}
 */
const REQUIRED_IMAGE_SIZES = [16, 32, 64, 128, 256, 512, 1024]

/**
 * The size of the ICNS header.
 * @type {Number}
 */
const HEADER_SIZE = 8

/**
 * Identifier of the ICNS file, in ASCII "icns".
 * @type {Number}
 */
const FILE_HEADER_ID = 'icns'

/**
 * ICNS file extension.
 * @type {String}
 */
const FILE_EXTENSION = '.icns'

/**
 * Information of the images, Mac OS 8.x (il32, is32, l8mk, s8mk) is unsupported.
 * If icp4, icp5, icp6 is present, Icon will not be supported because it can not be set as Folder of Finder.
 *
 * @type {Array.<ICNSIconInfo>}
 */
const ICON_INFOS = [
  // Normal
  {id: 'ic07', size: 128},
  {id: 'ic08', size: 256},
  {id: 'ic09', size: 512},
  {id: 'ic10', size: 1024},

  // Retina
  {id: 'ic11', size: 32},
  {id: 'ic12', size: 64},
  {id: 'ic13', size: 256},
  {id: 'ic14', size: 512},

  // Mac OS 8.5
  {id: 'is32', mask: 's8mk', size: 16},
  {id: 'il32', mask: 'l8mk', size: 32}
]

/**
 * Generate the ICNS file from a PNG images.
 * However, Mac OS 8.x is unsupported.
 */
export default class ICNSGenerator {
  /**
   * Create the ICNS file from a PNG images.
   *
   * @param {Array.<ImageInfo>} images Information of the image files.
   * @param {String}            dir     Output destination the path of directory.
   * @param {Object}            options Options.
   * @param {Logger}            logger  Logger.
   *
   * @return {Promise} Promise object.
   */
  static generate (images, dir, options, logger) {
    return new Promise((resolve, reject) => {
      logger.log('ICNS:')

      const dest    = Path.join(dir, options.names.icns + FILE_EXTENSION)
      const targets = Util.filterImagesBySizes(images, Util.checkImageSizes(REQUIRED_IMAGE_SIZES, options, 'icns'))

      if (ICNSGenerator._createIcon(targets, dest)) {
        logger.log('  Create: ' + dest)
        resolve(dest)
      } else {
        Fs.unlinkSync(dest)
        reject(new Error('Faild to read/write image.'))
      }
    })
  }

  /**
   * Get the size of the required PNG.
   *
   * @return {Array.<Number>} Sizes.
   */
  static getRequiredImageSizes () {
    return REQUIRED_IMAGE_SIZES
  }

  /**
   * Creat a file header and icon blocks.
   *
   * @param {Array.<ImageInfo>} images Information of the image files.
   * @param {String}            dest   The path of the output destination file.
   *
   * @return {Boolean} "true" if it succeeds.
   */
  static _createIcon (images, dest) {
    // Write a temporary file size
    let fileSize = HEADER_SIZE
    let stream   = Fs.createWriteStream(dest)
    stream.write(ICNSGenerator._createFileHeader(fileSize), 'binary')

    for (let i = 0, max = ICON_INFOS.length; i < max; ++i) {
      const info = ICON_INFOS[i]
      const image = ICNSGenerator._imageFromIconSize(info.size, images)
      if (!(image)) {
        // Depending on the command line option, there may be no corresponding size
        continue
      }

      let block = null
      switch (info.id) {
        case 'is32':
        case 'il32':
          block = ICNSGenerator._createIconBlockPackBits(info.id, info.mask, Fs.readFileSync(image.path))
          break

        default:
          block = ICNSGenerator._createIconBlock(info.id, Fs.readFileSync(image.path))
          break
      }

      if (block) {
        stream.write(block, 'binary')
        fileSize += block.length
      } else {
        fileSize = 0
        break
      }
    }

    stream.end()

    if (fileSize === 0) {
      return false
    }

    // Update an actual file size
    stream = Fs.createWriteStream(dest)
    stream.write(ICNSGenerator._createFileHeader(fileSize), 'binary')
    stream.end()

    return true
  }

  /**
   * Create an icon block's data.
   *
   * @param {String} id   Identifier of the icon.
   * @param {Buffer} data Body data of the icon.
   *
   * @return {Buffer} data.
   */
  static _createIconBlock (id, data) {
    if (!(data)) {
      return null
    }

    const header = ICNSGenerator._createIconHeader(id, data.length)
    return Buffer.concat([header, data], header.length + data.length)
  }

  /**
   * Create an icon blocks (Color and mask) for PackBits.
   *
   * @param {String} id    Identifier of the icon (color block).
   * @param {String} mask  Identifier of the icon (mask block).
   * @param {Buffer} data Binary of the PNG image.
   *
   * @return {Buffer} If successful it wrote the icon block. "null" on failure.
   */
  static _createIconBlockPackBits (id, mask, data) {
    const bodies = ICNSGenerator._createIconBlockPackBitsBodies(data)
    if (!(bodies)) {
      return null
    }

    const colorBlock = ICNSGenerator._createIconBlock(id, Buffer.from(bodies.color))
    const maskBlock  = ICNSGenerator._createIconBlock(mask, Buffer.from(bodies.mask))

    return Buffer.concat([colorBlock, maskBlock], colorBlock.length + maskBlock.length)
  }

  /**
   * Create a color and mask data.
   *
   * @param {ImageInfo} image Information of the image.
   *
   * @return {Object} Bodies, "color" is a color (Compressed by PackBits), "mask" is a mask.
   */
  static _createIconBlockPackBitsBodies (data) {
    if (!(data)) {
      return null
    }

    const png     = PNG.sync.read(data)
    const results = {color: [], mask: []}

    for (let i = 0, max = png.data.length; i < max; i += 4) {
      // RGB
      results.color.push(png.data.readUInt8(i))
      results.color.push(png.data.readUInt8(i + 1))
      results.color.push(png.data.readUInt8(i + 2))

      // Alpha
      results.mask.push(png.data.readUInt8(i + 3))
    }

    results.color = PackBits.pack(results.color)
    return results
  }

  /**
   * Create the ICNS file header.
   *
   * @param {Number} fileSize File size.
   *
   * @return {Buffer} Header data.
   */
  static _createFileHeader (fileSize) {
    const buffer = Buffer.alloc(HEADER_SIZE)
    buffer.write(FILE_HEADER_ID, 0, 'ascii')
    buffer.writeUInt32BE(fileSize, 4)

    return buffer
  }

  /**
   * Create the Icon header in ICNS file.
   *
   * @param {Object} id        Identifier of the icon.
   * @param {Number} imageSize Size of the image data.
   *
   * @return {Buffer} Header data.
   */
  static _createIconHeader (id, imageSize) {
    const buffer = Buffer.alloc(HEADER_SIZE)
    buffer.write(id, 0, 'ascii')
    buffer.writeUInt32BE(HEADER_SIZE + imageSize, 4)

    return buffer
  }

  /**
   * Select the support image from the icon size.
   *
   * @param {Number}            size   Sizo of icon.
   * @param {Array.<ImageInfo>} images File informations..
   *
   * @return {ImageInfo} If successful image information, otherwise null.
   */
  static _imageFromIconSize (size, images) {
    let result = null
    images.some((image) => {
      if (image.size === size) {
        result = image
        return true
      }

      return false
    })

    return result
  }

  /**
   * Unpack an icon block files from ICNS file (For debug).
   *
   * @param {String} src  Path of the ICNS file.
   * @param {String} dest Path of directory to output icon block files.
   *
   * @return {Promise} Promise object.
   */
  static _debugUnpackIconBlocks (src, dest) {
    return new Promise((resolve, reject) => {
      Fs.readFile(src, (err, data) => {
        if (err) {
          return reject(err)
        }

        for (let pos = HEADER_SIZE, max = data.length; pos < max;) {
          const header = data.slice(pos, HEADER_SIZE)
          const id     = header.toString('ascii', 0, 4)
          const size   = header.readUInt32BE(4)

          pos += HEADER_SIZE
          const body   = data.slice(pos, size)
          const block = Buffer.concat(header, body)

          const path = Path.join(dest, id + '.block')
          Fs.writeFileSync(path, block, 'binary')

          pos += size
        }

        resolve()
      })
    })
  }
}
<|endoftext|>


<commit_before>/*eslint-disable react/no-danger*/
import React from "react";
import serialize from "serialize-javascript";
import process from "process";
import getAssetPath from "../getAssetPath";
import getAssetPathForFile from "../getAssetPathForFile";

const isProduction = process.env.NODE_ENV === "production";

// eslint-disable-next-line no-unused-vars
export default (config, entryPoint, assets) => {
  const tags = [];
  let key = 0;
  const assetPath = getAssetPath(config);

  if (isProduction) {
    tags.push(<link key={key++} rel="stylesheet" type="text/css" href={getAssetPathForFile(`${entryPoint}`, "styles")} />);
  }

  tags.push(<script key={key++} type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/script.js/2.5.8/script.min.js" />);

  tags.push(
    <script key={key++} type="text/javascript" dangerouslySetInnerHTML={{__html: `window.__GS_PUBLIC_PATH__ = ${serialize(assetPath)}; window.__GS_ENVIRONMENT__ = ${serialize(process.env.NODE_ENV)}`}}></script>
  );

  const scriptPaths = {
    commons: getAssetPathForFile("commons", "javascript"),
    vendor: getAssetPathForFile("vendor", "javascript"),
    entryPoint: getAssetPathForFile(entryPoint, "javascript")
  };

  tags.push(getScriptLoader(scriptPaths));

  return tags.concat(getScriptSubresources(scriptPaths));
};

function getScriptLoader ({commons, vendor, entryPoint}:Object) {
  // eslint-disable-next-line quotes
  const scriptLoader = `
  /*!
    * $script.js JS loader & dependency manager
    * https://github.com/ded/script.js
    * (c) Dustin Diaz 2014 | License MIT
    */
    (function(e,t){typeof module!="undefined"&&module.exports?module.exports=t():typeof define=="function"&&define.amd?define(t):this[e]=t()})("$script",function(){function p(e,t){for(var n=0,i=e.length;n<i;++n)if(!t(e[n]))return r;return 1}function d(e,t){p(e,function(e){return t(e),1})}function v(e,t,n){function g(e){return e.call?e():u[e]}function y(){if(!--h){u[o]=1,s&&s();for(var e in f)p(e.split("|"),g)&&!d(f[e],g)&&(f[e]=[])}}e=e[i]?e:[e];var r=t&&t.call,s=r?t:n,o=r?e.join(""):t,h=e.length;return setTimeout(function(){d(e,function t(e,n){if(e===null)return y();!n&&!/^https?:\\\/\\\//.test(e)&&c&&(e=e.indexOf(".js")===-1?c+e+".js":c+e);if(l[e])return o&&(a[o]=1),l[e]==2?y():setTimeout(function(){t(e,!0)},0);l[e]=1,o&&(a[o]=1),m(e,y)})},0),v}function m(n,r){var i=e.createElement("script"),u;i.onload=i.onerror=i[o]=function(){if(i[s]&&!/^c|loade/.test(i[s])||u)return;i.onload=i[o]=null,u=1,l[n]=2,r()},i.async=1,i.src=h?n+(n.indexOf("?")===-1?"?":"&")+h:n,t.insertBefore(i,t.lastChild)}var e=document,t=e.getElementsByTagName("head")[0],n="string",r=!1,i="push",s="readyState",o="onreadystatechange",u={},a={},f={},l={},c,h;return v.get=m,v.order=function(e,t,n){(function r(i){i=e.shift(),e.length?v(i,r):v(i,t,n)})()},v.path=function(e){c=e},v.urlArgs=function(e){h=e},v.ready=function(e,t,n){e=e[i]?e:[e];var r=[];return!d(e,function(e){u[e]||r[i](e)})&&p(e,function(e){return u[e]})?t():!function(e){f[e]=f[e]||[],f[e][i](t),n&&n(r)}(e.join("|")),v},v.done=function(e){v([null],e)},v})
    $script("${commons}", function () {
      $script("${vendor}", function () {
        $script("${entryPoint}");
      });
    });
  `;

  return <script type="text/javascript" dangerouslySetInnerHTML={{__html: scriptLoader}} />;
}

// Sub resources give browsers a clue to assets they can preload and cache
function getScriptSubresources ({commons, vendor, entryPoint}) {
  return [
    commons,
    vendor,
    entryPoint
  ].map((src) => {
    return <link rel="subresource" href={src} />;
  });
}

<commit_msg>remove script tag, add keys<commit_after>/*eslint-disable react/no-danger*/
import React from "react";
import serialize from "serialize-javascript";
import process from "process";
import getAssetPath from "../getAssetPath";
import getAssetPathForFile from "../getAssetPathForFile";

const isProduction = process.env.NODE_ENV === "production";

// eslint-disable-next-line no-unused-vars
export default (config, entryPoint, assets) => {
  const tags = [];
  let key = 0;
  const assetPath = getAssetPath(config);

  if (isProduction) {
    tags.push(<link key={key++} rel="stylesheet" type="text/css" href={getAssetPathForFile(`${entryPoint}`, "styles")} />);
  }

  tags.push(
    <script key={key++} type="text/javascript" dangerouslySetInnerHTML={{__html: `window.__GS_PUBLIC_PATH__ = ${serialize(assetPath)}; window.__GS_ENVIRONMENT__ = ${serialize(process.env.NODE_ENV)}`}}></script>
  );

  const scriptPaths = {
    commons: getAssetPathForFile("commons", "javascript"),
    vendor: getAssetPathForFile("vendor", "javascript"),
    entryPoint: getAssetPathForFile(entryPoint, "javascript")
  };

  tags.push(getScriptLoader(scriptPaths));

  return tags.concat(getScriptSubresources(scriptPaths));
};

function getScriptLoader ({commons, vendor, entryPoint}:Object) {
  // eslint-disable-next-line quotes
  const scriptLoader = `
  /*!
    * $script.js JS loader & dependency manager
    * https://github.com/ded/script.js
    * (c) Dustin Diaz 2014 | License MIT
    */
    (function(e,t){typeof module!="undefined"&&module.exports?module.exports=t():typeof define=="function"&&define.amd?define(t):this[e]=t()})("$script",function(){function p(e,t){for(var n=0,i=e.length;n<i;++n)if(!t(e[n]))return r;return 1}function d(e,t){p(e,function(e){return t(e),1})}function v(e,t,n){function g(e){return e.call?e():u[e]}function y(){if(!--h){u[o]=1,s&&s();for(var e in f)p(e.split("|"),g)&&!d(f[e],g)&&(f[e]=[])}}e=e[i]?e:[e];var r=t&&t.call,s=r?t:n,o=r?e.join(""):t,h=e.length;return setTimeout(function(){d(e,function t(e,n){if(e===null)return y();!n&&!/^https?:\\\/\\\//.test(e)&&c&&(e=e.indexOf(".js")===-1?c+e+".js":c+e);if(l[e])return o&&(a[o]=1),l[e]==2?y():setTimeout(function(){t(e,!0)},0);l[e]=1,o&&(a[o]=1),m(e,y)})},0),v}function m(n,r){var i=e.createElement("script"),u;i.onload=i.onerror=i[o]=function(){if(i[s]&&!/^c|loade/.test(i[s])||u)return;i.onload=i[o]=null,u=1,l[n]=2,r()},i.async=1,i.src=h?n+(n.indexOf("?")===-1?"?":"&")+h:n,t.insertBefore(i,t.lastChild)}var e=document,t=e.getElementsByTagName("head")[0],n="string",r=!1,i="push",s="readyState",o="onreadystatechange",u={},a={},f={},l={},c,h;return v.get=m,v.order=function(e,t,n){(function r(i){i=e.shift(),e.length?v(i,r):v(i,t,n)})()},v.path=function(e){c=e},v.urlArgs=function(e){h=e},v.ready=function(e,t,n){e=e[i]?e:[e];var r=[];return!d(e,function(e){u[e]||r[i](e)})&&p(e,function(e){return u[e]})?t():!function(e){f[e]=f[e]||[],f[e][i](t),n&&n(r)}(e.join("|")),v},v.done=function(e){v([null],e)},v})
    $script("${commons}", function () {
      $script("${vendor}", function () {
        $script("${entryPoint}");
      });
    });
  `;

  return <script key="script-loader" type="text/javascript" dangerouslySetInnerHTML={{__html: scriptLoader}} />;
}

// Sub resources give browsers a clue to assets they can preload and cache
function getScriptSubresources ({commons, vendor, entryPoint}) {
  return [
    commons,
    vendor,
    entryPoint
  ].map((src, i) => {
    return <link key={`sub-${i}`} rel="subresource" href={src} />;
  });
}

<|endoftext|>


<commit_before>import ConstRef from "./constref"
import Operation from "./operation"
import Expression from "./expression"
import {Context, ContextTypes, Doc, ParserStateOption} from "./node"
import Variable from "./variable"
import * as PHPType from "../php-type"
import * as PHPError from "../php-error"
import BooleanState, { Assertion } from "../boolean-state";
export default class Bin extends Operation {
    /** @type {string} */
    get type() {
        return this.node.type
    }
    /** @type {Expression} */
    get left() {
        return this.cacheNode("left")
    }
    /** @type {Expression} */
    get right() {
        return this.cacheNode("right")
    }
    /**
     * Checks that syntax seems ok
     * @param {Context} context
     * @param {Set<ParserStateOption.Base>} [parser_state]
     * @param {?Doc} [doc]
     * @returns {?ContextTypes} The set of types applicable to this value
     */
    check(context, parser_state = new Set(), doc = null) {
        super.check(context, parser_state, doc)

        let left = this.left.check(context, new Set(), null)

        let boolean_state

        let right_context = context.childContext(false)
        right_context.importNamespaceFrom(context)
        let types = PHPType.Union.empty
        switch(this.type) {
            case "||":
            case "|":
            case "or":
                // Boolean (or)
                left.booleanState.falseStates.forEach(s => {
                    let c_right_context = right_context.childContext(false)
                    c_right_context.importNamespaceFrom(right_context)
                    c_right_context.importAssertions(s.assertions)
                    this.right.check(c_right_context, new Set(), null)
                    context.importNamespaceFrom(c_right_context)
                })
                types = types.addTypesFrom(PHPType.Core.types.bool)
                break
            case "&":
            case "&&":
            case "and":
                // Boolean (and)
                left.booleanState.trueStates.forEach(s => {
                    let c_right_context = right_context.childContext(false)
                    c_right_context.importNamespaceFrom(right_context)
                    c_right_context.importAssertions(s.assertions)
                    this.right.check(c_right_context, new Set(), null)
                    context.importNamespaceFrom(c_right_context)
                })
                types = types.addTypesFrom(PHPType.Core.types.bool)
                break
            case "*":
            case "/":
            case "-":
            case "%":
            case "**":
            case "<<":
            case ">>":
            case "^":
                // Numeric (1)
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                types = types.addTypesFrom(PHPType.Core.types.float)
                break
            case "+":
                // Numeric (2)
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                left.expressionType.types.forEach(type => {
                    if(type instanceof PHPType.Mixed) {
                        types = types.addTypesFrom(type.union)
                    } else {
                        switch(type.typeSignature) {
                            case "null":
                                // Yes null casts to number.
                            case "int":
                            case "float":
                                types = types.addTypesFrom(PHPType.Core.types.float)
                                break
                            case "array":
                                types = types.addTypesFrom(PHPType.Core.types.array)
                                break
                            default:
                                this.throw(
                                    new PHPError.BadTypeCast(`Possibly bad cast from type ${type} for +`),
                                    context,
                                    this.loc
                                )
                                types = types.addTypesFrom(PHPType.Core.types.float)
                        }
                    }
                })
                break
            case ".":
                // String
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                types = types.addTypesFrom(PHPType.Core.types.string)
                break
            case "~":
            case "!~":
            case "=":
            case "!=":
            case "?":
            case "<":
            case "<=":
            case ">":
            case "=>":
            case ">=":
            case "==":
            case "!==":
            case "===":
                // Comparison (boolean)
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                types = types.addTypesFrom(PHPType.Core.types.bool)
                break
            case "instanceof":
                // Comparison (boolean) (instanceof)
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                types = types.addTypesFrom(PHPType.Core.types.bool)
                if(
                    this.left instanceof Variable &&
                    this.right instanceof ConstRef
                ) {
                    boolean_state = new BooleanState().withType(
                        types,
                        new Assertion(
                            false,
                            '$' + this.left.name,
                            PHPType.Core.named(context.resolveNodeName(this.right))
                        )
                    )
                }
                break
            case "??":
                // Left (not null) or right
                types = types.addTypesFrom(
                    left.expressionType.excluding("null")
                ).addTypesFrom(
                    this.right.check(right_context, new Set(), null).expressionType
                )
                context.importNamespaceFrom(right_context)
                break
            default:
                console.log(this.node)
                console.log(`Don't know how to parse operator type ${this.type}`)
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                types = types.addTypesFrom(left.expressionType)
        }
        if(boolean_state) {
            return new ContextTypes(
                types,
                PHPType.Union.empty,
                boolean_state
            )
        } else {
            return new ContextTypes(types)
        }
    }
}
<commit_msg>Retain type when combining arrays<commit_after>import ConstRef from "./constref"
import Operation from "./operation"
import Expression from "./expression"
import {Context, ContextTypes, Doc, ParserStateOption} from "./node"
import Variable from "./variable"
import * as PHPType from "../php-type"
import * as PHPError from "../php-error"
import BooleanState, { Assertion } from "../boolean-state";
export default class Bin extends Operation {
    /** @type {string} */
    get type() {
        return this.node.type
    }
    /** @type {Expression} */
    get left() {
        return this.cacheNode("left")
    }
    /** @type {Expression} */
    get right() {
        return this.cacheNode("right")
    }
    /**
     * Checks that syntax seems ok
     * @param {Context} context
     * @param {Set<ParserStateOption.Base>} [parser_state]
     * @param {?Doc} [doc]
     * @returns {?ContextTypes} The set of types applicable to this value
     */
    check(context, parser_state = new Set(), doc = null) {
        super.check(context, parser_state, doc)

        let left = this.left.check(context, new Set(), null)

        let boolean_state

        let right_context = context.childContext(false)
        right_context.importNamespaceFrom(context)
        let types = PHPType.Union.empty
        switch(this.type) {
            case "||":
            case "|":
            case "or":
                // Boolean (or)
                left.booleanState.falseStates.forEach(s => {
                    let c_right_context = right_context.childContext(false)
                    c_right_context.importNamespaceFrom(right_context)
                    c_right_context.importAssertions(s.assertions)
                    this.right.check(c_right_context, new Set(), null)
                    context.importNamespaceFrom(c_right_context)
                })
                types = types.addTypesFrom(PHPType.Core.types.bool)
                break
            case "&":
            case "&&":
            case "and":
                // Boolean (and)
                left.booleanState.trueStates.forEach(s => {
                    let c_right_context = right_context.childContext(false)
                    c_right_context.importNamespaceFrom(right_context)
                    c_right_context.importAssertions(s.assertions)
                    this.right.check(c_right_context, new Set(), null)
                    context.importNamespaceFrom(c_right_context)
                })
                types = types.addTypesFrom(PHPType.Core.types.bool)
                break
            case "*":
            case "/":
            case "-":
            case "%":
            case "**":
            case "<<":
            case ">>":
            case "^":
                // Numeric (1)
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                types = types.addTypesFrom(PHPType.Core.types.float)
                break
            case "+":
                // Numeric (2)
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                left.expressionType.types.forEach(type => {
                    if(type instanceof PHPType.Mixed) {
                        types = types.addTypesFrom(type.union)
                    } else {
                        switch(type.typeSignature) {
                            case "null":
                                // Yes null casts to number.
                            case "int":
                            case "float":
                                types = types.addTypesFrom(PHPType.Core.types.float)
                                break
                            case "array":
                                types = types.addType(type)
                                break
                            default:
                                this.throw(
                                    new PHPError.BadTypeCast(`Possibly bad cast from type ${type} for +`),
                                    context,
                                    this.loc
                                )
                                types = types.addTypesFrom(PHPType.Core.types.float)
                        }
                    }
                })
                break
            case ".":
                // String
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                types = types.addTypesFrom(PHPType.Core.types.string)
                break
            case "~":
            case "!~":
            case "=":
            case "!=":
            case "?":
            case "<":
            case "<=":
            case ">":
            case "=>":
            case ">=":
            case "==":
            case "!==":
            case "===":
                // Comparison (boolean)
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                types = types.addTypesFrom(PHPType.Core.types.bool)
                break
            case "instanceof":
                // Comparison (boolean) (instanceof)
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                types = types.addTypesFrom(PHPType.Core.types.bool)
                if(
                    this.left instanceof Variable &&
                    this.right instanceof ConstRef
                ) {
                    boolean_state = new BooleanState().withType(
                        types,
                        new Assertion(
                            false,
                            '$' + this.left.name,
                            PHPType.Core.named(context.resolveNodeName(this.right))
                        )
                    )
                }
                break
            case "??":
                // Left (not null) or right
                types = types.addTypesFrom(
                    left.expressionType.excluding("null")
                ).addTypesFrom(
                    this.right.check(right_context, new Set(), null).expressionType
                )
                context.importNamespaceFrom(right_context)
                break
            default:
                console.log(this.node)
                console.log(`Don't know how to parse operator type ${this.type}`)
                this.right.check(right_context, new Set(), null)
                context.importNamespaceFrom(right_context)
                types = types.addTypesFrom(left.expressionType)
        }
        if(boolean_state) {
            return new ContextTypes(
                types,
                PHPType.Union.empty,
                boolean_state
            )
        } else {
            return new ContextTypes(types)
        }
    }
}
<|endoftext|>


<commit_before>const minMaxTypes = ['str', 'string', 'int', 'integer', 'num', 'number', 'float'];
const regexTypes = ['reg', 'regex', 'regexp'];

/**
 * Represents a possibility in a usage Tag
 */
class Possible {

	/**
	 * @param {string[]} regexResults The regex results from parsing the tag member
	 * @since 0.2.1
	 */
	constructor([, name, type = 'literal', min, max, regex, flags]) {
		/**
		 * The name of this possible
		 * @since 0.2.1
		 * @type {string}
		 */
		this.name = name;

		/**
		 * The type of this possible
		 * @since 0.2.1
		 * @type {string}
		 */
		this.type = type.toLowerCase();

		/**
		 * The min of this possible
		 * @since 0.2.1
		 * @type {?number}
		 */
		this.min = minMaxTypes.includes(this.type) && min ? this.constructor.resolveLimit(min, this.type, 'min') : undefined;

		/**
		 * The max of this possible
		 * @since 0.2.1
		 * @type {?number}
		 */
		this.max = minMaxTypes.includes(this.type) && max ? this.constructor.resolveLimit(max, this.type, 'max') : undefined;

		/**
		 * The regex of this possible
		 * @since 0.3.0
		 * @type {?RegExp}
		 */
		this.regex = regexTypes.includes(this.type) && regex ? new RegExp(regex, flags) : undefined;

		if (regexTypes.includes(this.type) && !this.regex) throw 'Regex types must include a regular expression';
	}

	/**
	 * Resolves a limit
	 * @since 0.2.1
	 * @param {string} limit The limit to evaluate
	 * @param {string} type The type of the usage Tag
	 * @param {string} limitType The type of limit
	 * @returns {number}
	 * @private
	 */
	static resolveLimit(limit, type, limitType) {
		if (isNaN(limit)) throw `${limitType} must be a number`;
		const tempLimit = parseFloat(limit);
		if (minMaxTypes.indexOf(type) <= 3 && tempLimit % 1 !== 0) throw `${limitType} must be an integer for this type.`;
		return tempLimit;
	}

}

module.exports = Possible;
<commit_msg>fix Possible docs<commit_after>const minMaxTypes = ['str', 'string', 'int', 'integer', 'num', 'number', 'float'];
const regexTypes = ['reg', 'regex', 'regexp'];

/**
 * Represents a possibility in a usage Tag
 */
class Possible {

	/**
	 * @param {string[]} regexResults The regex results from parsing the tag member
	 * @since 0.2.1
	 */
	constructor([, name, type = 'literal', min, max, regex, flags]) {
		/**
		 * The name of this possible
		 * @since 0.2.1
		 * @type {string}
		 */
		this.name = name;

		/**
		 * The type of this possible
		 * @since 0.2.1
		 * @type {string}
		 */
		this.type = type.toLowerCase();

		/**
		 * The min of this possible
		 * @since 0.2.1
		 * @type {?number}
		 */
		this.min = minMaxTypes.includes(this.type) && min ? this.constructor.resolveLimit(min, this.type, 'min') : undefined;

		/**
		 * The max of this possible
		 * @since 0.2.1
		 * @type {?number}
		 */
		this.max = minMaxTypes.includes(this.type) && max ? this.constructor.resolveLimit(max, this.type, 'max') : undefined;

		/**
		 * The regex of this possible
		 * @since 0.3.0
		 * @type {?RegExp}
		 */
		this.regex = regexTypes.includes(this.type) && regex ? new RegExp(regex, flags) : undefined;

		if (regexTypes.includes(this.type) && !this.regex) throw 'Regex types must include a regular expression';
	}

	/**
	 * Resolves a limit
	 * @since 0.2.1
	 * @param {string} limit The limit to evaluate
	 * @param {string} type The type of the usage Possible
	 * @param {string} limitType The type of limit
	 * @returns {number}
	 * @private
	 */
	static resolveLimit(limit, type, limitType) {
		if (isNaN(limit)) throw `${limitType} must be a number`;
		const tempLimit = parseFloat(limit);
		if (minMaxTypes.indexOf(type) <= 3 && tempLimit % 1 !== 0) throw `${limitType} must be an integer for this type.`;
		return tempLimit;
	}

}

module.exports = Possible;
<|endoftext|>


<commit_before>function daisyGame(numero){         // Exercício 1
    if(numero % 2 !== 0){
      return 'Love me';
    } else{
      return 'Love me not';
    }
}

function maiorTexto(arrayStrings){             // Exercício 2
var maiorPalavra = "";
for (var i = 0; i < arrayStrings.length; i++) {
  if(arrayStrings[i].length > maiorPalavra.length){
    maiorPalavra = arrayStrings[i];
  }
}
return maiorPalavra;
}

function forImprime(arrayStrings){                //Exercício 3
  for (var i = 0; i < arrayStrings.length; i++) {
    console.log('Olá querido instrutor: ' + arrayStrings[i]);
  }
}

function imprime(arrayStrings, fn){               //Exercício 3
  if (typeof fn === 'function') {
  fn(forImprime(arrayStrings));
} else {
  console.log(typeof fn + ' is not a function');
}
}

var somaDiferentona = function(numero1){          //Exercício 4
   return function(numero2){
     return numero1 + numero2;
   }
}

var fiboSum = function(n){                        //Exercício 5
  var arrayFibo = [n];
  if(n > 0){
  arrayFibo[0] = 1;
  if(n > 1){
  for (var i = 1; i < n; i++) {
    if(i === 1){
        arrayFibo[i] = 1;
    }else{
    arrayFibo[i] = arrayFibo[i-1] + arrayFibo[i-2];
  }
  }
}
var soma = 0;
for (var i = 0; i < arrayFibo.length; i++) {
  soma = soma + arrayFibo[i];
}
console.log(soma);
}else{
  console.log('Digite número maior que 0.');
}
}

function queroCafe(mascada, precos){              //Exercício 6
  precos.sort();
  var precosOrdenados = " ";
  for (var i = 0; i < precos.length; i++) {
    if(precos[i] <= mascada){
      precosOrdenados = precosOrdenados + precos[i] + " , "
    }
  }
  precosOrdenados = precosOrdenados.substring(0, (precosOrdenados.length - 2));
  return precosOrdenados;
}

function contarPorTipo(obj, tipoObj){               // Exercício 7
    var cont = 0;
    for(var i in obj){
      if(obj[i] === null){
        if(tipoObj === null){
        cont++;
      }
      }else if(obj[i].constructor === tipoObj){
        cont++;
      }
    }
return cont;
}

var gohan = 'gohan', goku = 'Goku';
function revelarSaiyaman() {
  // var gohan;
  console.log(gohan);
  goku = 'Son Goku'; //Como goku não vou redeclarado, foi reescrito.
  var gohan = 'Son ' + gohan;    // o JS puxa todas as declarações de variável para o início, ficando var gohan; Ele puxa apenas a declaração.
  // variavel local gohan vira 'Son + undefined'
  return gohan;
}
console.log(revelarSaiyaman()); // imprime a variavel local gohan
console.log(goku);              // imprime o novo valor da variavel goku
<commit_msg>refactor(lista-js-basico.js): Refazer o exercício 3 de uma maneira mais simples.<commit_after>function daisyGame(numero){         // Exercício 1
    if(numero % 2 !== 0){
      return 'Love me';
    } else{
      return 'Love me not';
    }
}

function maiorTexto(arrayStrings){             // Exercício 2
var maiorPalavra = "";
for (var i = 0; i < arrayStrings.length; i++) {
  if(arrayStrings[i].length > maiorPalavra.length){
    maiorPalavra = arrayStrings[i];
  }
}
return maiorPalavra;
}

function imprime(arrayStrings, fn) {
  arrayStrings.forEach(function(instrutor) { //Para cada instrutor do array
    if (typeof fn === 'function') fn(instrutor);  //Se fn for uma função, ele a usa. O ideal é que a função seja de impressão na tela.
  });
};

var somaDiferentona = function(numero1){          //Exercício 4
   return function(numero2){
     return numero1 + numero2;
   };
};

var fiboSum = function(n){                        //Exercício 5
  var arrayFibo = [n];
  if(n > 0){
  arrayFibo[0] = 1;
  if(n > 1){
  for (var i = 1; i < n; i++) {
    if(i === 1){
        arrayFibo[i] = 1;
    }else{
    arrayFibo[i] = arrayFibo[i-1] + arrayFibo[i-2];
  }
  }
}
var soma = 0;
for (var i = 0; i < arrayFibo.length; i++) {
  soma = soma + arrayFibo[i];
}
console.log(soma);
}else{
  console.log('Digite número maior que 0.');
}
};

function queroCafe(mascada, precos){              //Exercício 6
  precos.sort();
  var precosOrdenados = " ";
  for (var i = 0; i < precos.length; i++) {
    if(precos[i] <= mascada){
      precosOrdenados = precosOrdenados + precos[i] + " , ";
    }
  }
  precosOrdenados = precosOrdenados.substring(0, (precosOrdenados.length - 2));
  return precosOrdenados;
}

function contarPorTipo(obj, tipoObj){               // Exercício 7
    var cont = 0;
    for(var i in obj){
      if(obj[i] === null){
        if(tipoObj === null){
        cont++;
      }
    }else if(obj[i].constructor === tipoObj){
        cont++;
      }
    }
return cont;
}

var gohan = 'gohan', goku = 'Goku';
function revelarSaiyaman() {
  // var gohan;
  console.log(gohan);
  goku = 'Son Goku'; //Como goku não vou redeclarado, foi reescrito.
  var gohan = 'Son ' + gohan;    // o JS puxa todas as declarações de variável para o início, ficando var gohan; Ele puxa apenas a declaração.
  // variavel local gohan vira 'Son + undefined'
  return gohan;
}
console.log(revelarSaiyaman()); // imprime a variavel local gohan
console.log(goku);              // imprime o novo valor da variavel goku
<|endoftext|>


<commit_before>'use strict';

angular.module('atlasApp').controller('MainCtrl', function(
  $location,
  $routeParams,
  $scope,
  $http,
  $q,
  $analytics,
  cfpLoadingBar
) {

  $scope.searchResults = [];

  /**
   * Provides autocomplete suggestions as you type the query
   */
  $scope.autocomplete = function(query) {
    var places = Parse.Cloud.run("placeAutocomplete", {query: query});
    return places;
    // var courses = Parse.Cloud.run("courseAutocomplete", {query: query});
    // return places + courses
  };

  $scope.onAutocompleteSelect = function(item, model, label, from) {
    $analytics.eventTrack(
      'Click Autocomplete Suggestion from ' + from,
      { category: 'Search' }
    );
    $scope.search(model.id);
  }

  /**
   * Used to request a search with the provided query
   */
  $scope.search = function(query) {
    $location.url('/place/' + query);
  }

  /**
   * Performs the actual search and provides the results
   */
  $scope._search = function(query) {
    cfpLoadingBar.start();
    Parse.Cloud.run("placeSearch", {query: query}).then(function(res) {
      $scope.searchResults = res;
      cfpLoadingBar.complete();
    });
  };

  if ($routeParams.q) {   // If url contains search query, perform search
    $scope.query = $routeParams.q;
    $scope._search($routeParams.q);
  }

});
<commit_msg>Hello Deleted<commit_after>'use strict';
alert("Hello");
angular.module('atlasApp').controller('MainCtrl', function(
  $location,
  $routeParams,
  $scope,
  $http,
  $q,
  $analytics,
  cfpLoadingBar
) {

  $scope.searchResults = [];

  /**
   * Provides autocomplete suggestions as you type the query
   */
  $scope.autocomplete = function(query) {
    var places = Parse.Cloud.run("placeAutocomplete", {query: query});
    return places;
    // var courses = Parse.Cloud.run("courseAutocomplete", {query: query});
    // return places + courses
  };

  $scope.onAutocompleteSelect = function(item, model, label, from) {
    $analytics.eventTrack(
      'Click Autocomplete Suggestion from ' + from,
      { category: 'Search' }
    );
    $scope.search(model.id);
  }

  /**
   * Used to request a search with the provided query
   */
  $scope.search = function(query) {
    $location.url('/place/' + query);
  }

  /**
   * Performs the actual search and provides the results
   */
  $scope._search = function(query) {
    cfpLoadingBar.start();
    Parse.Cloud.run("placeSearch", {query: query}).then(function(res) {
      $scope.searchResults = res;
      cfpLoadingBar.complete();
    });
  };

  if ($routeParams.q) {   // If url contains search query, perform search
    $scope.query = $routeParams.q;
    $scope._search($routeParams.q);
  }

});
<|endoftext|>


<commit_before>import data from '../util/data';
import registry from '../polyfill/registry';
import walkTree from '../util/walk-tree';

function callDetachedOnDescendants (elem, opts) {
  walkTree(elem.childNodes, function (elem) {
    registry.getForElement(elem).forEach(Ctor => Ctor.prototype.createdCallback.call(elem));
  }, function (elem) {
    return !data(elem, opts.id).attached;
  });
}

function callDetached (elem, opts) {
  if (opts.detached) {
    opts.detached.call(elem);
  }
}

export default function (opts) {
  /* jshint expr: true */
  return function () {
    var info = data(this, opts.id);
    var isNative = this.detachedCallback;

    if (info.detached) {
      return;
    }

    isNative || callDetachedOnDescendants(this, opts);
    info.detached = true;
    callDetached(this, opts);
    info.attached = false;
  };
}
<commit_msg>Fix calling detached on descandants.<commit_after>import data from '../util/data';
import registry from '../polyfill/registry';
import walkTree from '../util/walk-tree';

function callDetachedOnDescendants (elem, opts) {
  walkTree(elem.childNodes, function (elem) {
    registry.getForElement(elem).forEach(Ctor => Ctor.prototype.createdCallback.call(elem));
  }, function (elem) {
    return !data(elem, opts.id).detached;
  });
}

function callDetached (elem, opts) {
  if (opts.detached) {
    opts.detached.call(elem);
  }
}

export default function (opts) {
  /* jshint expr: true */
  return function () {
    var info = data(this, opts.id);
    var isNative = this.detachedCallback;

    if (info.detached) {
      return;
    }

    isNative || callDetachedOnDescendants(this, opts);
    info.detached = true;
    callDetached(this, opts);
    info.attached = false;
  };
}
<|endoftext|>


<commit_before>/* @flow */

function shouldWrapKey(str: string): boolean {
  return str.indexOf("true") === 0 || str.indexOf("false") === 0 || /[:\s\n\\"]/g.test(str);
}

function maybeWrap(str: string): string {
  if (shouldWrapKey(str)) {
    return JSON.stringify(str);
  } else {
    return str;
  }
}

const priorities = {
  name: 1,
  version: 2,
  uid: 3,
  resolved: 4,
  registry: 5,
  dependencies: 6
};

function getKeyPriority(key: string): number {
  return priorities[key] || 100;
}

export default function stringify(obj: any, indent: string = ""): string {
  if (typeof obj !== "object") {
    throw new TypeError;
  }

  let lines = [];

  let keys = Object.keys(obj).sort(function (a, b) {
    // sort alphabetically
    return a.toLowerCase().localeCompare(b.toLowerCase());
  }).sort(function (a, b) {
    // prioritise certain fields
    return +(getKeyPriority(a) > getKeyPriority(b));
  });

  for (let key of keys) {
    let val = obj[key];
    if (val === undefined) continue;

    key = maybeWrap(key);

    if (typeof val === "string" || typeof val === "boolean") {
      lines.push(`${key} ${maybeWrap(val)}`);
    } else if (typeof val === "object") {
      lines.push(`${key}: \n${stringify(val, indent + "  ")}`);
    } else {
      throw new TypeError;
    }
  }

  return indent + lines.join(`\n${indent}`);
}
<commit_msg>check for booleans in lockfile.stringify<commit_after>/* @flow */

function shouldWrapKey(str: string): boolean {
  return str.indexOf("true") === 0 || str.indexOf("false") === 0 || /[:\s\n\\"]/g.test(str);
}

function maybeWrap(str: string): string {
  if (typeof str === "boolean" || shouldWrapKey(str)) {
    return JSON.stringify(str);
  } else {
    return str;
  }
}

const priorities = {
  name: 1,
  version: 2,
  uid: 3,
  resolved: 4,
  registry: 5,
  dependencies: 6
};

function getKeyPriority(key: string): number {
  return priorities[key] || 100;
}

export default function stringify(obj: any, indent: string = ""): string {
  if (typeof obj !== "object") {
    throw new TypeError;
  }

  let lines = [];

  let keys = Object.keys(obj).sort(function (a, b) {
    // sort alphabetically
    return a.toLowerCase().localeCompare(b.toLowerCase());
  }).sort(function (a, b) {
    // prioritise certain fields
    return +(getKeyPriority(a) > getKeyPriority(b));
  });

  for (let key of keys) {
    let val = obj[key];
    if (val === undefined) continue;

    key = maybeWrap(key);

    if (typeof val === "string" || typeof val === "boolean") {
      lines.push(`${key} ${maybeWrap(val)}`);
    } else if (typeof val === "object") {
      lines.push(`${key}: \n${stringify(val, indent + "  ")}`);
    } else {
      throw new TypeError;
    }
  }

  return indent + lines.join(`\n${indent}`);
}
<|endoftext|>