mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	Compare commits
	
		
			63 Commits
		
	
	
		
			v5.2.0
			...
			kivikakk/g
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					adfb438a42 | ||
| 
						 | 
					0ed1b821d7 | ||
| 
						 | 
					1a769c4665 | ||
| 
						 | 
					e7e64bf39a | ||
| 
						 | 
					e4b9430024 | ||
| 
						 | 
					a76805e40d | ||
| 
						 | 
					8d27845f8c | ||
| 
						 | 
					9a8ab45b6f | ||
| 
						 | 
					e335d48625 | ||
| 
						 | 
					4f46155c05 | ||
| 
						 | 
					38901d51d2 | ||
| 
						 | 
					ded0dc74e0 | ||
| 
						 | 
					c5d1bb5370 | ||
| 
						 | 
					c8ca48856b | ||
| 
						 | 
					7be6fb0138 | ||
| 
						 | 
					8c516655bc | ||
| 
						 | 
					9dceffce2f | ||
| 
						 | 
					33be70eb28 | ||
| 
						 | 
					9c4dc3047c | ||
| 
						 | 
					d8e5f3c965 | ||
| 
						 | 
					71bf640a47 | ||
| 
						 | 
					c9b3d19c6f | ||
| 
						 | 
					0f4955e5d5 | ||
| 
						 | 
					d968b0e9ee | ||
| 
						 | 
					1f5ed3b3fe | ||
| 
						 | 
					297be948d1 | ||
| 
						 | 
					b4492e7205 | ||
| 
						 | 
					c05bc99004 | ||
| 
						 | 
					99eaf5faf9 | ||
| 
						 | 
					21babbceb1 | ||
| 
						 | 
					15885701cd | ||
| 
						 | 
					9b942086f7 | ||
| 
						 | 
					93cd47822f | ||
| 
						 | 
					ea3e79a631 | ||
| 
						 | 
					0af9a35ff1 | ||
| 
						 | 
					44048c9ba8 | ||
| 
						 | 
					e51b5ec9b7 | ||
| 
						 | 
					a47008ea00 | ||
| 
						 | 
					a0b38e8207 | ||
| 
						 | 
					10dfe9f296 | ||
| 
						 | 
					0b9c05f989 | ||
| 
						 | 
					95dca67e2b | ||
| 
						 | 
					e98728595b | ||
| 
						 | 
					4cd558c374 | ||
| 
						 | 
					adf6206ef5 | ||
| 
						 | 
					c2d558b71d | ||
| 
						 | 
					78c58f956e | ||
| 
						 | 
					fc1404985a | ||
| 
						 | 
					5d48ccd757 | ||
| 
						 | 
					3530a18e46 | ||
| 
						 | 
					ae8f4f9228 | ||
| 
						 | 
					7c34d38786 | ||
| 
						 | 
					38bc5fd336 | ||
| 
						 | 
					6b06e47c67 | ||
| 
						 | 
					061712ff78 | ||
| 
						 | 
					7707585d5e | ||
| 
						 | 
					fa7d433886 | ||
| 
						 | 
					998e24cf36 | ||
| 
						 | 
					63ff51e2ed | ||
| 
						 | 
					b541b53b78 | ||
| 
						 | 
					a878620a8e | ||
| 
						 | 
					5633fd3668 | ||
| 
						 | 
					9d0af0da40 | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -8,3 +8,6 @@ lib/linguist/samples.json
 | 
			
		||||
/node_modules
 | 
			
		||||
test/fixtures/ace_modes.json
 | 
			
		||||
/vendor/gems/
 | 
			
		||||
/tmp
 | 
			
		||||
*.bundle
 | 
			
		||||
*.so
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										55
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										55
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -169,9 +169,6 @@
 | 
			
		||||
[submodule "vendor/grammars/Agda.tmbundle"]
 | 
			
		||||
	path = vendor/grammars/Agda.tmbundle
 | 
			
		||||
	url = https://github.com/mokus0/Agda.tmbundle
 | 
			
		||||
[submodule "vendor/grammars/Julia.tmbundle"]
 | 
			
		||||
	path = vendor/grammars/Julia.tmbundle
 | 
			
		||||
	url = https://github.com/JuliaEditorSupport/Julia.tmbundle
 | 
			
		||||
[submodule "vendor/grammars/ooc.tmbundle"]
 | 
			
		||||
	path = vendor/grammars/ooc.tmbundle
 | 
			
		||||
	url = https://github.com/nilium/ooc.tmbundle
 | 
			
		||||
@@ -400,10 +397,6 @@
 | 
			
		||||
[submodule "vendor/grammars/sublime_cobol"]
 | 
			
		||||
	path = vendor/grammars/sublime_cobol
 | 
			
		||||
	url = https://bitbucket.org/bitlang/sublime_cobol
 | 
			
		||||
[submodule "vendor/grammars/ruby.tmbundle"]
 | 
			
		||||
	path = vendor/grammars/ruby.tmbundle
 | 
			
		||||
	url = https://github.com/aroben/ruby.tmbundle
 | 
			
		||||
	branch = pl
 | 
			
		||||
[submodule "vendor/grammars/IDL-Syntax"]
 | 
			
		||||
	path = vendor/grammars/IDL-Syntax
 | 
			
		||||
	url = https://github.com/andik/IDL-Syntax
 | 
			
		||||
@@ -446,9 +439,6 @@
 | 
			
		||||
[submodule "vendor/grammars/sublime-golo"]
 | 
			
		||||
	path = vendor/grammars/sublime-golo
 | 
			
		||||
	url = https://github.com/TypeUnsafe/sublime-golo
 | 
			
		||||
[submodule "vendor/grammars/JSyntax"]
 | 
			
		||||
	path = vendor/grammars/JSyntax
 | 
			
		||||
	url = https://github.com/bcj/JSyntax
 | 
			
		||||
[submodule "vendor/grammars/TXL"]
 | 
			
		||||
	path = vendor/grammars/TXL
 | 
			
		||||
	url = https://github.com/MikeHoffert/Sublime-Text-TXL-syntax
 | 
			
		||||
@@ -569,9 +559,6 @@
 | 
			
		||||
[submodule "vendor/grammars/sublime-aspectj"]
 | 
			
		||||
	path = vendor/grammars/sublime-aspectj
 | 
			
		||||
	url = https://github.com/pchaigno/sublime-aspectj
 | 
			
		||||
[submodule "vendor/grammars/sublime-typescript"]
 | 
			
		||||
	path = vendor/grammars/sublime-typescript
 | 
			
		||||
	url = https://github.com/Microsoft/TypeScript-Sublime-Plugin
 | 
			
		||||
[submodule "vendor/grammars/sublime-pony"]
 | 
			
		||||
	path = vendor/grammars/sublime-pony
 | 
			
		||||
	url = https://github.com/CausalityLtd/sublime-pony
 | 
			
		||||
@@ -866,3 +853,45 @@
 | 
			
		||||
[submodule "vendor/grammars/language-reason"]
 | 
			
		||||
	path = vendor/grammars/language-reason
 | 
			
		||||
	url = https://github.com/reasonml-editor/language-reason
 | 
			
		||||
[submodule "vendor/grammars/sublime-nearley"]
 | 
			
		||||
	path = vendor/grammars/sublime-nearley
 | 
			
		||||
	url = https://github.com/Hardmath123/sublime-nearley
 | 
			
		||||
[submodule "vendor/grammars/data-weave-tmLanguage"]
 | 
			
		||||
	path = vendor/grammars/data-weave-tmLanguage
 | 
			
		||||
	url = https://github.com/mulesoft-labs/data-weave-tmLanguage
 | 
			
		||||
[submodule "vendor/grammars/squirrel-language"]
 | 
			
		||||
	path = vendor/grammars/squirrel-language
 | 
			
		||||
	url = https://github.com/mathewmariani/squirrel-language
 | 
			
		||||
[submodule "vendor/grammars/language-ballerina"]
 | 
			
		||||
	path = vendor/grammars/language-ballerina
 | 
			
		||||
	url = https://github.com/ballerinalang/plugin-vscode
 | 
			
		||||
[submodule "vendor/grammars/language-yara"]
 | 
			
		||||
	path = vendor/grammars/language-yara
 | 
			
		||||
	url = https://github.com/blacktop/language-yara
 | 
			
		||||
[submodule "vendor/grammars/language-ruby"]
 | 
			
		||||
	path = vendor/grammars/language-ruby
 | 
			
		||||
	url = https://github.com/atom/language-ruby
 | 
			
		||||
[submodule "vendor/grammars/sublime-angelscript"]
 | 
			
		||||
	path = vendor/grammars/sublime-angelscript
 | 
			
		||||
	url = https://github.com/wronex/sublime-angelscript
 | 
			
		||||
[submodule "vendor/grammars/TypeScript-TmLanguage"]
 | 
			
		||||
	path = vendor/grammars/TypeScript-TmLanguage
 | 
			
		||||
	url = https://github.com/Microsoft/TypeScript-TmLanguage
 | 
			
		||||
[submodule "vendor/grammars/wdl-sublime-syntax-highlighter"]
 | 
			
		||||
	path = vendor/grammars/wdl-sublime-syntax-highlighter
 | 
			
		||||
	url = https://github.com/broadinstitute/wdl-sublime-syntax-highlighter
 | 
			
		||||
[submodule "vendor/grammars/atom-language-julia"]
 | 
			
		||||
	path = vendor/grammars/atom-language-julia
 | 
			
		||||
	url = https://github.com/JuliaEditorSupport/atom-language-julia
 | 
			
		||||
[submodule "vendor/grammars/language-cwl"]
 | 
			
		||||
	path = vendor/grammars/language-cwl
 | 
			
		||||
	url = https://github.com/manabuishii/language-cwl
 | 
			
		||||
[submodule "vendor/grammars/Syntax-highlighting-for-PostCSS"]
 | 
			
		||||
	path = vendor/grammars/Syntax-highlighting-for-PostCSS
 | 
			
		||||
	url = https://github.com/hudochenkov/Syntax-highlighting-for-PostCSS
 | 
			
		||||
[submodule "vendor/grammars/javadoc.tmbundle"]
 | 
			
		||||
	path = vendor/grammars/javadoc.tmbundle
 | 
			
		||||
	url = https://github.com/textmate/javadoc.tmbundle
 | 
			
		||||
[submodule "vendor/grammars/JSyntax"]
 | 
			
		||||
	path = vendor/grammars/JSyntax
 | 
			
		||||
	url = https://github.com/tikkanz/JSyntax
 | 
			
		||||
 
 | 
			
		||||
@@ -19,10 +19,6 @@ rvm:
 | 
			
		||||
  - 2.3.3
 | 
			
		||||
  - 2.4.0
 | 
			
		||||
 | 
			
		||||
matrix:
 | 
			
		||||
  allow_failures:
 | 
			
		||||
  - rvm: 2.4.0
 | 
			
		||||
 | 
			
		||||
notifications:
 | 
			
		||||
  disabled: true
 | 
			
		||||
 | 
			
		||||
@@ -32,3 +28,5 @@ git:
 | 
			
		||||
 | 
			
		||||
cache: bundler
 | 
			
		||||
dist: precise
 | 
			
		||||
 | 
			
		||||
bundler_args: --without debug
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ To add support for a new extension:
 | 
			
		||||
In addition, if this extension is already listed in [`languages.yml`][languages] then sometimes a few more steps will need to be taken:
 | 
			
		||||
 | 
			
		||||
1. Make sure that example `.yourextension` files are present in the [samples directory][samples] for each language that uses `.yourextension`.
 | 
			
		||||
1. Test the performance of the Bayesian classifier with a relatively large number (1000s) of sample `.yourextension` files. (ping **@bkeepers** to help with this) to ensure we're not misclassifying files.
 | 
			
		||||
1. Test the performance of the Bayesian classifier with a relatively large number (1000s) of sample `.yourextension` files. (ping **@lildude** to help with this) to ensure we're not misclassifying files.
 | 
			
		||||
1. If the Bayesian classifier does a bad job with the sample `.yourextension` files then a [heuristic](https://github.com/github/linguist/blob/master/lib/linguist/heuristics.rb) may need to be written to help.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -36,7 +36,7 @@ To add support for a new language:
 | 
			
		||||
In addition, if your new language defines an extension that's already listed in [`languages.yml`][languages] (such as `.foo`) then sometimes a few more steps will need to be taken:
 | 
			
		||||
 | 
			
		||||
1. Make sure that example `.foo` files are present in the [samples directory][samples] for each language that uses `.foo`.
 | 
			
		||||
1. Test the performance of the Bayesian classifier with a relatively large number (1000s) of sample `.foo` files. (ping **@bkeepers** to help with this) to ensure we're not misclassifying files.
 | 
			
		||||
1. Test the performance of the Bayesian classifier with a relatively large number (1000s) of sample `.foo` files. (ping **@lildude** to help with this) to ensure we're not misclassifying files.
 | 
			
		||||
1. If the Bayesian classifier does a bad job with the sample `.foo` files then a [heuristic](https://github.com/github/linguist/blob/master/lib/linguist/heuristics.rb) may need to be written to help.
 | 
			
		||||
 | 
			
		||||
Remember, the goal here is to try and avoid false positives!
 | 
			
		||||
@@ -93,6 +93,7 @@ Linguist is maintained with :heart: by:
 | 
			
		||||
- **@BenEddy** (GitHub staff)
 | 
			
		||||
- **@Caged** (GitHub staff)
 | 
			
		||||
- **@grantr** (GitHub staff)
 | 
			
		||||
- **@kivikakk** (GitHub staff)
 | 
			
		||||
- **@larsbrinkhoff**
 | 
			
		||||
- **@lildude** (GitHub staff)
 | 
			
		||||
- **@pchaigno**
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Gemfile
									
									
									
									
									
								
							@@ -1,3 +1,6 @@
 | 
			
		||||
source 'https://rubygems.org'
 | 
			
		||||
gemspec :name => "github-linguist"
 | 
			
		||||
gem 'byebug' if RUBY_VERSION >= '2.0'
 | 
			
		||||
 | 
			
		||||
group :debug do
 | 
			
		||||
  gem 'byebug' if RUBY_VERSION >= '2.2'
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								Rakefile
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								Rakefile
									
									
									
									
									
								
							@@ -1,6 +1,7 @@
 | 
			
		||||
require 'bundler/setup'
 | 
			
		||||
require 'rake/clean'
 | 
			
		||||
require 'rake/testtask'
 | 
			
		||||
require 'rake/extensiontask'
 | 
			
		||||
require 'yaml'
 | 
			
		||||
require 'yajl'
 | 
			
		||||
require 'open-uri'
 | 
			
		||||
@@ -10,8 +11,14 @@ task :default => :test
 | 
			
		||||
 | 
			
		||||
Rake::TestTask.new
 | 
			
		||||
 | 
			
		||||
gem_spec = Gem::Specification.load('github-linguist.gemspec')
 | 
			
		||||
 | 
			
		||||
Rake::ExtensionTask.new('linguist', gem_spec) do |ext|
 | 
			
		||||
  ext.lib_dir = File.join('lib', 'linguist')
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
# Extend test task to check for samples and fetch latest Ace modes
 | 
			
		||||
task :test => [:check_samples, :fetch_ace_modes]
 | 
			
		||||
task :test => [:compile, :check_samples, :fetch_ace_modes]
 | 
			
		||||
 | 
			
		||||
desc "Check that we have samples.json generated"
 | 
			
		||||
task :check_samples do
 | 
			
		||||
@@ -34,15 +41,22 @@ task :fetch_ace_modes do
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
task :samples do
 | 
			
		||||
task :samples => :compile do
 | 
			
		||||
  require 'linguist/samples'
 | 
			
		||||
  json = Yajl.dump(Linguist::Samples.data, :pretty => true)
 | 
			
		||||
  File.write 'lib/linguist/samples.json', json
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
task :flex do
 | 
			
		||||
  if `flex -V` !~ /^flex \d+\.\d+\.\d+/
 | 
			
		||||
    fail "flex not detected"
 | 
			
		||||
  end
 | 
			
		||||
  system "cd ext/linguist && flex tokenizer.l"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
task :build_gem => :samples do
 | 
			
		||||
  rm_rf "grammars"
 | 
			
		||||
  sh "script/convert-grammars"
 | 
			
		||||
  sh "script/grammar-compiler compile -o grammars || true"
 | 
			
		||||
  languages = YAML.load_file("lib/linguist/languages.yml")
 | 
			
		||||
  File.write("lib/linguist/languages.json", Yajl.dump(languages))
 | 
			
		||||
  `gem build github-linguist.gemspec`
 | 
			
		||||
 
 | 
			
		||||
@@ -117,9 +117,8 @@ def git_linguist(args)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  parser.parse!(args)
 | 
			
		||||
 | 
			
		||||
  git_dir = `git rev-parse --git-dir`.strip
 | 
			
		||||
  raise "git-linguist must be run in a Git repository (#{Dir.pwd})" unless $?.success?
 | 
			
		||||
  raise "git-linguist must be run in a Git repository" unless $?.success?
 | 
			
		||||
  wrapper = GitLinguist.new(git_dir, commit, incremental)
 | 
			
		||||
 | 
			
		||||
  case args.pop
 | 
			
		||||
@@ -141,6 +140,10 @@ def git_linguist(args)
 | 
			
		||||
    $stderr.print(parser.help)
 | 
			
		||||
    exit 1
 | 
			
		||||
  end
 | 
			
		||||
rescue Exception => e
 | 
			
		||||
  $stderr.puts e.message
 | 
			
		||||
  $stderr.puts e.backtrace
 | 
			
		||||
  exit 1
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
git_linguist(ARGV)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								ext/linguist/extconf.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								ext/linguist/extconf.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
require 'mkmf'
 | 
			
		||||
dir_config('linguist')
 | 
			
		||||
create_makefile('linguist/linguist')
 | 
			
		||||
							
								
								
									
										2226
									
								
								ext/linguist/lex.linguist_yy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2226
									
								
								ext/linguist/lex.linguist_yy.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										336
									
								
								ext/linguist/lex.linguist_yy.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										336
									
								
								ext/linguist/lex.linguist_yy.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,336 @@
 | 
			
		||||
#ifndef linguist_yyHEADER_H
 | 
			
		||||
#define linguist_yyHEADER_H 1
 | 
			
		||||
#define linguist_yyIN_HEADER 1
 | 
			
		||||
 | 
			
		||||
#line 6 "lex.linguist_yy.h"
 | 
			
		||||
 | 
			
		||||
#define  YY_INT_ALIGNED short int
 | 
			
		||||
 | 
			
		||||
/* A lexical scanner generated by flex */
 | 
			
		||||
 | 
			
		||||
#define FLEX_SCANNER
 | 
			
		||||
#define YY_FLEX_MAJOR_VERSION 2
 | 
			
		||||
#define YY_FLEX_MINOR_VERSION 5
 | 
			
		||||
#define YY_FLEX_SUBMINOR_VERSION 35
 | 
			
		||||
#if YY_FLEX_SUBMINOR_VERSION > 0
 | 
			
		||||
#define FLEX_BETA
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* First, we deal with  platform-specific or compiler-specific issues. */
 | 
			
		||||
 | 
			
		||||
/* begin standard C headers. */
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
/* end standard C headers. */
 | 
			
		||||
 | 
			
		||||
/* flex integer type definitions */
 | 
			
		||||
 | 
			
		||||
#ifndef FLEXINT_H
 | 
			
		||||
#define FLEXINT_H
 | 
			
		||||
 | 
			
		||||
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
 | 
			
		||||
 | 
			
		||||
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
 | 
			
		||||
 | 
			
		||||
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
 | 
			
		||||
 * if you want the limit (max/min) macros for int types. 
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __STDC_LIMIT_MACROS
 | 
			
		||||
#define __STDC_LIMIT_MACROS 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
typedef int8_t flex_int8_t;
 | 
			
		||||
typedef uint8_t flex_uint8_t;
 | 
			
		||||
typedef int16_t flex_int16_t;
 | 
			
		||||
typedef uint16_t flex_uint16_t;
 | 
			
		||||
typedef int32_t flex_int32_t;
 | 
			
		||||
typedef uint32_t flex_uint32_t;
 | 
			
		||||
typedef uint64_t flex_uint64_t;
 | 
			
		||||
#else
 | 
			
		||||
typedef signed char flex_int8_t;
 | 
			
		||||
typedef short int flex_int16_t;
 | 
			
		||||
typedef int flex_int32_t;
 | 
			
		||||
typedef unsigned char flex_uint8_t; 
 | 
			
		||||
typedef unsigned short int flex_uint16_t;
 | 
			
		||||
typedef unsigned int flex_uint32_t;
 | 
			
		||||
#endif /* ! C99 */
 | 
			
		||||
 | 
			
		||||
/* Limits of integral types. */
 | 
			
		||||
#ifndef INT8_MIN
 | 
			
		||||
#define INT8_MIN               (-128)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef INT16_MIN
 | 
			
		||||
#define INT16_MIN              (-32767-1)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef INT32_MIN
 | 
			
		||||
#define INT32_MIN              (-2147483647-1)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef INT8_MAX
 | 
			
		||||
#define INT8_MAX               (127)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef INT16_MAX
 | 
			
		||||
#define INT16_MAX              (32767)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef INT32_MAX
 | 
			
		||||
#define INT32_MAX              (2147483647)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef UINT8_MAX
 | 
			
		||||
#define UINT8_MAX              (255U)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef UINT16_MAX
 | 
			
		||||
#define UINT16_MAX             (65535U)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef UINT32_MAX
 | 
			
		||||
#define UINT32_MAX             (4294967295U)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* ! FLEXINT_H */
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 | 
			
		||||
/* The "const" storage-class-modifier is valid. */
 | 
			
		||||
#define YY_USE_CONST
 | 
			
		||||
 | 
			
		||||
#else	/* ! __cplusplus */
 | 
			
		||||
 | 
			
		||||
/* C99 requires __STDC__ to be defined as 1. */
 | 
			
		||||
#if defined (__STDC__)
 | 
			
		||||
 | 
			
		||||
#define YY_USE_CONST
 | 
			
		||||
 | 
			
		||||
#endif	/* defined (__STDC__) */
 | 
			
		||||
#endif	/* ! __cplusplus */
 | 
			
		||||
 | 
			
		||||
#ifdef YY_USE_CONST
 | 
			
		||||
#define yyconst const
 | 
			
		||||
#else
 | 
			
		||||
#define yyconst
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* An opaque pointer. */
 | 
			
		||||
#ifndef YY_TYPEDEF_YY_SCANNER_T
 | 
			
		||||
#define YY_TYPEDEF_YY_SCANNER_T
 | 
			
		||||
typedef void* yyscan_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* For convenience, these vars (plus the bison vars far below)
 | 
			
		||||
   are macros in the reentrant scanner. */
 | 
			
		||||
#define yyin yyg->yyin_r
 | 
			
		||||
#define yyout yyg->yyout_r
 | 
			
		||||
#define yyextra yyg->yyextra_r
 | 
			
		||||
#define yyleng yyg->yyleng_r
 | 
			
		||||
#define yytext yyg->yytext_r
 | 
			
		||||
#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
 | 
			
		||||
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
 | 
			
		||||
#define yy_flex_debug yyg->yy_flex_debug_r
 | 
			
		||||
 | 
			
		||||
/* Size of default input buffer. */
 | 
			
		||||
#ifndef YY_BUF_SIZE
 | 
			
		||||
#define YY_BUF_SIZE 16384
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
 | 
			
		||||
#define YY_TYPEDEF_YY_BUFFER_STATE
 | 
			
		||||
typedef struct yy_buffer_state *YY_BUFFER_STATE;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef YY_TYPEDEF_YY_SIZE_T
 | 
			
		||||
#define YY_TYPEDEF_YY_SIZE_T
 | 
			
		||||
typedef size_t yy_size_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef YY_STRUCT_YY_BUFFER_STATE
 | 
			
		||||
#define YY_STRUCT_YY_BUFFER_STATE
 | 
			
		||||
struct yy_buffer_state
 | 
			
		||||
	{
 | 
			
		||||
	FILE *yy_input_file;
 | 
			
		||||
 | 
			
		||||
	char *yy_ch_buf;		/* input buffer */
 | 
			
		||||
	char *yy_buf_pos;		/* current position in input buffer */
 | 
			
		||||
 | 
			
		||||
	/* Size of input buffer in bytes, not including room for EOB
 | 
			
		||||
	 * characters.
 | 
			
		||||
	 */
 | 
			
		||||
	yy_size_t yy_buf_size;
 | 
			
		||||
 | 
			
		||||
	/* Number of characters read into yy_ch_buf, not including EOB
 | 
			
		||||
	 * characters.
 | 
			
		||||
	 */
 | 
			
		||||
	yy_size_t yy_n_chars;
 | 
			
		||||
 | 
			
		||||
	/* Whether we "own" the buffer - i.e., we know we created it,
 | 
			
		||||
	 * and can realloc() it to grow it, and should free() it to
 | 
			
		||||
	 * delete it.
 | 
			
		||||
	 */
 | 
			
		||||
	int yy_is_our_buffer;
 | 
			
		||||
 | 
			
		||||
	/* Whether this is an "interactive" input source; if so, and
 | 
			
		||||
	 * if we're using stdio for input, then we want to use getc()
 | 
			
		||||
	 * instead of fread(), to make sure we stop fetching input after
 | 
			
		||||
	 * each newline.
 | 
			
		||||
	 */
 | 
			
		||||
	int yy_is_interactive;
 | 
			
		||||
 | 
			
		||||
	/* Whether we're considered to be at the beginning of a line.
 | 
			
		||||
	 * If so, '^' rules will be active on the next match, otherwise
 | 
			
		||||
	 * not.
 | 
			
		||||
	 */
 | 
			
		||||
	int yy_at_bol;
 | 
			
		||||
 | 
			
		||||
    int yy_bs_lineno; /**< The line count. */
 | 
			
		||||
    int yy_bs_column; /**< The column count. */
 | 
			
		||||
    
 | 
			
		||||
	/* Whether to try to fill the input buffer when we reach the
 | 
			
		||||
	 * end of it.
 | 
			
		||||
	 */
 | 
			
		||||
	int yy_fill_buffer;
 | 
			
		||||
 | 
			
		||||
	int yy_buffer_status;
 | 
			
		||||
 | 
			
		||||
	};
 | 
			
		||||
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
 | 
			
		||||
 | 
			
		||||
void linguist_yyrestart (FILE *input_file ,yyscan_t yyscanner );
 | 
			
		||||
void linguist_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
 | 
			
		||||
YY_BUFFER_STATE linguist_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
 | 
			
		||||
void linguist_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
 | 
			
		||||
void linguist_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
 | 
			
		||||
void linguist_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
 | 
			
		||||
void linguist_yypop_buffer_state (yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
YY_BUFFER_STATE linguist_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
 | 
			
		||||
YY_BUFFER_STATE linguist_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
 | 
			
		||||
YY_BUFFER_STATE linguist_yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
void *linguist_yyalloc (yy_size_t ,yyscan_t yyscanner );
 | 
			
		||||
void *linguist_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
 | 
			
		||||
void linguist_yyfree (void * ,yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
/* Begin user sect3 */
 | 
			
		||||
 | 
			
		||||
#define yytext_ptr yytext_r
 | 
			
		||||
 | 
			
		||||
#ifdef YY_HEADER_EXPORT_START_CONDITIONS
 | 
			
		||||
#define INITIAL 0
 | 
			
		||||
#define sgml 1
 | 
			
		||||
#define c_comment 2
 | 
			
		||||
#define xml_comment 3
 | 
			
		||||
#define haskell_comment 4
 | 
			
		||||
#define ocaml_comment 5
 | 
			
		||||
#define python_dcomment 6
 | 
			
		||||
#define python_scomment 7
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef YY_NO_UNISTD_H
 | 
			
		||||
/* Special case for "unistd.h", since it is non-ANSI. We include it way
 | 
			
		||||
 * down here because we want the user's section 1 to have been scanned first.
 | 
			
		||||
 * The user has a chance to override it with an option.
 | 
			
		||||
 */
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define YY_EXTRA_TYPE struct tokenizer_extra *
 | 
			
		||||
 | 
			
		||||
int linguist_yylex_init (yyscan_t* scanner);
 | 
			
		||||
 | 
			
		||||
int linguist_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
 | 
			
		||||
 | 
			
		||||
/* Accessor methods to globals.
 | 
			
		||||
   These are made visible to non-reentrant scanners for convenience. */
 | 
			
		||||
 | 
			
		||||
int linguist_yylex_destroy (yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
int linguist_yyget_debug (yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
void linguist_yyset_debug (int debug_flag ,yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
YY_EXTRA_TYPE linguist_yyget_extra (yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
void linguist_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
FILE *linguist_yyget_in (yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
void linguist_yyset_in  (FILE * in_str ,yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
FILE *linguist_yyget_out (yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
void linguist_yyset_out  (FILE * out_str ,yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
yy_size_t linguist_yyget_leng (yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
char *linguist_yyget_text (yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
int linguist_yyget_lineno (yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
void linguist_yyset_lineno (int line_number ,yyscan_t yyscanner );
 | 
			
		||||
 | 
			
		||||
/* Macros after this point can all be overridden by user definitions in
 | 
			
		||||
 * section 1.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef YY_SKIP_YYWRAP
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" int linguist_yywrap (yyscan_t yyscanner );
 | 
			
		||||
#else
 | 
			
		||||
extern int linguist_yywrap (yyscan_t yyscanner );
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef yytext_ptr
 | 
			
		||||
static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef YY_NEED_STRLEN
 | 
			
		||||
static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef YY_NO_INPUT
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Amount of stuff to slurp up with each read. */
 | 
			
		||||
#ifndef YY_READ_BUF_SIZE
 | 
			
		||||
#define YY_READ_BUF_SIZE 8192
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Number of entries by which start-condition stack grows. */
 | 
			
		||||
#ifndef YY_START_STACK_INCR
 | 
			
		||||
#define YY_START_STACK_INCR 25
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Default declaration of generated scanner - a define so the user can
 | 
			
		||||
 * easily add parameters.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef YY_DECL
 | 
			
		||||
#define YY_DECL_IS_OURS 1
 | 
			
		||||
 | 
			
		||||
extern int linguist_yylex (yyscan_t yyscanner);
 | 
			
		||||
 | 
			
		||||
#define YY_DECL int linguist_yylex (yyscan_t yyscanner)
 | 
			
		||||
#endif /* !YY_DECL */
 | 
			
		||||
 | 
			
		||||
/* yy_get_previous_state - get the state just before the EOB char was reached */
 | 
			
		||||
 | 
			
		||||
#undef YY_NEW_FILE
 | 
			
		||||
#undef YY_FLUSH_BUFFER
 | 
			
		||||
#undef yy_set_bol
 | 
			
		||||
#undef yy_new_buffer
 | 
			
		||||
#undef yy_set_interactive
 | 
			
		||||
#undef YY_DO_BEFORE_ACTION
 | 
			
		||||
 | 
			
		||||
#ifdef YY_DECL_IS_OURS
 | 
			
		||||
#undef YY_DECL_IS_OURS
 | 
			
		||||
#undef YY_DECL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#line 118 "tokenizer.l"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#line 335 "lex.linguist_yy.h"
 | 
			
		||||
#undef linguist_yyIN_HEADER
 | 
			
		||||
#endif /* linguist_yyHEADER_H */
 | 
			
		||||
							
								
								
									
										75
									
								
								ext/linguist/linguist.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								ext/linguist/linguist.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
#include "ruby.h"
 | 
			
		||||
#include "linguist.h"
 | 
			
		||||
#include "lex.linguist_yy.h"
 | 
			
		||||
 | 
			
		||||
// Anything longer is unlikely to be useful.
 | 
			
		||||
#define MAX_TOKEN_LEN 32
 | 
			
		||||
 | 
			
		||||
int linguist_yywrap(yyscan_t yyscanner) {
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE rb_tokenizer_extract_tokens(VALUE self, VALUE rb_data) {
 | 
			
		||||
	YY_BUFFER_STATE buf;
 | 
			
		||||
	yyscan_t scanner;
 | 
			
		||||
	struct tokenizer_extra extra;
 | 
			
		||||
	VALUE ary, s;
 | 
			
		||||
	long len;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	Check_Type(rb_data, T_STRING);
 | 
			
		||||
 | 
			
		||||
	len = RSTRING_LEN(rb_data);
 | 
			
		||||
	if (len > 100000)
 | 
			
		||||
		len = 100000;
 | 
			
		||||
 | 
			
		||||
	linguist_yylex_init_extra(&extra, &scanner);
 | 
			
		||||
	buf = linguist_yy_scan_bytes(RSTRING_PTR(rb_data), (int) len, scanner);
 | 
			
		||||
 | 
			
		||||
	ary = rb_ary_new();
 | 
			
		||||
	do {
 | 
			
		||||
		extra.type = NO_ACTION;
 | 
			
		||||
		extra.token = NULL;
 | 
			
		||||
		r = linguist_yylex(scanner);
 | 
			
		||||
		switch (extra.type) {
 | 
			
		||||
		case NO_ACTION:
 | 
			
		||||
			break;
 | 
			
		||||
		case REGULAR_TOKEN:
 | 
			
		||||
			len = strlen(extra.token);
 | 
			
		||||
			if (len <= MAX_TOKEN_LEN)
 | 
			
		||||
				rb_ary_push(ary, rb_str_new(extra.token, len));
 | 
			
		||||
			free(extra.token);
 | 
			
		||||
			break;
 | 
			
		||||
		case SHEBANG_TOKEN:
 | 
			
		||||
			len = strlen(extra.token);
 | 
			
		||||
			if (len <= MAX_TOKEN_LEN) {
 | 
			
		||||
				s = rb_str_new2("SHEBANG#!");
 | 
			
		||||
				rb_str_cat(s, extra.token, len);
 | 
			
		||||
				rb_ary_push(ary, s);
 | 
			
		||||
			}
 | 
			
		||||
			free(extra.token);
 | 
			
		||||
			break;
 | 
			
		||||
		case SGML_TOKEN:
 | 
			
		||||
			len = strlen(extra.token);
 | 
			
		||||
			if (len <= MAX_TOKEN_LEN) {
 | 
			
		||||
				s = rb_str_new(extra.token, len);
 | 
			
		||||
				rb_str_cat2(s, ">");
 | 
			
		||||
				rb_ary_push(ary, s);
 | 
			
		||||
			}
 | 
			
		||||
			free(extra.token);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	} while (r);
 | 
			
		||||
 | 
			
		||||
	linguist_yy_delete_buffer(buf, scanner);
 | 
			
		||||
	linguist_yylex_destroy(scanner);
 | 
			
		||||
 | 
			
		||||
	return ary;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((visibility("default"))) void Init_linguist() {
 | 
			
		||||
	VALUE rb_mLinguist = rb_define_module("Linguist");
 | 
			
		||||
	VALUE rb_cTokenizer = rb_define_class_under(rb_mLinguist, "Tokenizer", rb_cObject);
 | 
			
		||||
 | 
			
		||||
	rb_define_method(rb_cTokenizer, "extract_tokens", rb_tokenizer_extract_tokens, 1);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								ext/linguist/linguist.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								ext/linguist/linguist.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
enum tokenizer_type {
 | 
			
		||||
  NO_ACTION,
 | 
			
		||||
  REGULAR_TOKEN,
 | 
			
		||||
  SHEBANG_TOKEN,
 | 
			
		||||
  SGML_TOKEN,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct tokenizer_extra {
 | 
			
		||||
  char *token;
 | 
			
		||||
  enum tokenizer_type type;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										119
									
								
								ext/linguist/tokenizer.l
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								ext/linguist/tokenizer.l
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
%{
 | 
			
		||||
 | 
			
		||||
#include "linguist.h"
 | 
			
		||||
 | 
			
		||||
#define feed_token(tok, typ) do { \
 | 
			
		||||
    yyextra->token = (tok); \
 | 
			
		||||
    yyextra->type = (typ); \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define eat_until_eol() do { \
 | 
			
		||||
    int c; \
 | 
			
		||||
    while ((c = input(yyscanner)) != '\n' && c != EOF && c); \
 | 
			
		||||
    if (c == EOF || !c) \
 | 
			
		||||
      return 0; \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define eat_until_unescaped(q) do { \
 | 
			
		||||
    int c; \
 | 
			
		||||
    while ((c = input(yyscanner)) != EOF && c) { \
 | 
			
		||||
      if (c == '\n') \
 | 
			
		||||
        break; \
 | 
			
		||||
      if (c == '\\') { \
 | 
			
		||||
        c = input(yyscanner); \
 | 
			
		||||
        if (c == EOF || !c) \
 | 
			
		||||
          return 0; \
 | 
			
		||||
      } else if (c == q) \
 | 
			
		||||
        break; \
 | 
			
		||||
    } \
 | 
			
		||||
    if (c == EOF || !c) \
 | 
			
		||||
      return 0; \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
%}
 | 
			
		||||
 | 
			
		||||
%option never-interactive yywrap reentrant nounput warn nodefault header-file="lex.linguist_yy.h" extra-type="struct tokenizer_extra *" prefix="linguist_yy"
 | 
			
		||||
%x sgml c_comment xml_comment haskell_comment ocaml_comment python_dcomment python_scomment
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
^#![ \t]*([[:alnum:]_\/]*\/)?env([ \t]+([^ \t=]*=[^ \t]*))*[ \t]+[[:alpha:]_]+ {
 | 
			
		||||
    const char *off = strrchr(yytext, ' ');
 | 
			
		||||
    if (!off)
 | 
			
		||||
      off = yytext;
 | 
			
		||||
    else
 | 
			
		||||
      ++off;
 | 
			
		||||
    feed_token(strdup(off), SHEBANG_TOKEN);
 | 
			
		||||
    eat_until_eol();
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
^#![ \t]*[[:alpha:]_\/]+ {
 | 
			
		||||
    const char *off = strrchr(yytext, '/');
 | 
			
		||||
    if (!off)
 | 
			
		||||
      off = yytext;
 | 
			
		||||
    else
 | 
			
		||||
      ++off;
 | 
			
		||||
    if (strcmp(off, "env") == 0) {
 | 
			
		||||
      eat_until_eol();
 | 
			
		||||
    } else {
 | 
			
		||||
      feed_token(strdup(off), SHEBANG_TOKEN);
 | 
			
		||||
      eat_until_eol();
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
^[ \t]*(\/\/|--|\#|%|\")" ".*   { /* nothing */ }
 | 
			
		||||
 | 
			
		||||
"/*"                              { BEGIN(c_comment); }
 | 
			
		||||
  /* See below for xml_comment start. */
 | 
			
		||||
"{-"                              { BEGIN(haskell_comment); }
 | 
			
		||||
"(*"                              { BEGIN(ocaml_comment); }
 | 
			
		||||
"\"\"\""                          { BEGIN(python_dcomment); }
 | 
			
		||||
"'''"                             { BEGIN(python_scomment); }
 | 
			
		||||
 | 
			
		||||
<c_comment,xml_comment,haskell_comment,ocaml_comment,python_dcomment,python_scomment>.|\n { /* nothing */ }
 | 
			
		||||
<c_comment>"*/"                   { BEGIN(INITIAL); }
 | 
			
		||||
<xml_comment>"-->"                { BEGIN(INITIAL); }
 | 
			
		||||
<haskell_comment>"-}"             { BEGIN(INITIAL); }
 | 
			
		||||
<ocaml_comment>"*)"               { BEGIN(INITIAL); }
 | 
			
		||||
<python_dcomment>"\"\"\""         { BEGIN(INITIAL); }
 | 
			
		||||
<python_scomment>"'''"            { BEGIN(INITIAL); }
 | 
			
		||||
 | 
			
		||||
\"\"|''                           { /* nothing */ }
 | 
			
		||||
\"                                { eat_until_unescaped('"'); }
 | 
			
		||||
'                                 { eat_until_unescaped('\''); }
 | 
			
		||||
(0x[0-9a-fA-F]([0-9a-fA-F]|\.)*|[0-9]([0-9]|\.)*)([uU][lL]{0,2}|([eE][-+][0-9]*)?[fFlL]*) { /* nothing */ }
 | 
			
		||||
\<[[:alnum:]_!./?-]+              {
 | 
			
		||||
    if (strcmp(yytext, "<!--") == 0) {
 | 
			
		||||
     BEGIN(xml_comment);
 | 
			
		||||
    } else {
 | 
			
		||||
      feed_token(strdup(yytext), SGML_TOKEN);
 | 
			
		||||
      BEGIN(sgml);
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
<sgml>[[:alnum:]_]+=\"            { feed_token(strndup(yytext, strlen(yytext) - 1), REGULAR_TOKEN); eat_until_unescaped('"'); return 1; }
 | 
			
		||||
<sgml>[[:alnum:]_]+='             { feed_token(strndup(yytext, strlen(yytext) - 1), REGULAR_TOKEN); eat_until_unescaped('\''); return 1; }
 | 
			
		||||
<sgml>[[:alnum:]_]+=[[:alnum:]_]* { feed_token(strdup(yytext), REGULAR_TOKEN); *(strchr(yyextra->token, '=') + 1) = 0; return 1; }
 | 
			
		||||
<sgml>[[:alnum:]_]+               { feed_token(strdup(yytext), REGULAR_TOKEN); return 1; }
 | 
			
		||||
<sgml>\>                          { BEGIN(INITIAL); }
 | 
			
		||||
<sgml>.|\n                        { /* nothing */ }
 | 
			
		||||
;|\{|\}|\(|\)|\[|\]               { feed_token(strdup(yytext), REGULAR_TOKEN); return 1; }
 | 
			
		||||
[[:alnum:]_.@#/*]+                {
 | 
			
		||||
    if (strncmp(yytext, "/*", 2) == 0) {
 | 
			
		||||
      if (strlen(yytext) >= 4 && strcmp(yytext + strlen(yytext) - 2, "*/") == 0) {
 | 
			
		||||
        /* nothing */
 | 
			
		||||
      } else {
 | 
			
		||||
        BEGIN(c_comment);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      feed_token(strdup(yytext), REGULAR_TOKEN);
 | 
			
		||||
      return 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
\<\<?|\+|\-|\*|\/|%|&&?|\|\|?     { feed_token(strdup(yytext), REGULAR_TOKEN); return 1; }
 | 
			
		||||
.|\n                              { /* nothing */ }
 | 
			
		||||
 | 
			
		||||
%%
 | 
			
		||||
 | 
			
		||||
@@ -10,15 +10,17 @@ Gem::Specification.new do |s|
 | 
			
		||||
  s.homepage = "https://github.com/github/linguist"
 | 
			
		||||
  s.license  = "MIT"
 | 
			
		||||
 | 
			
		||||
  s.files = Dir['lib/**/*'] + Dir['grammars/*'] + ['LICENSE']
 | 
			
		||||
  s.files = Dir['lib/**/*'] + Dir['ext/**/*'] + Dir['grammars/*'] + ['LICENSE']
 | 
			
		||||
  s.executables = ['linguist', 'git-linguist']
 | 
			
		||||
  s.extensions = ['ext/linguist/extconf.rb']
 | 
			
		||||
 | 
			
		||||
  s.add_dependency 'charlock_holmes', '~> 0.7.3'
 | 
			
		||||
  s.add_dependency 'charlock_holmes', '~> 0.7.5'
 | 
			
		||||
  s.add_dependency 'escape_utils',    '~> 1.1.0'
 | 
			
		||||
  s.add_dependency 'mime-types',      '>= 1.19'
 | 
			
		||||
  s.add_dependency 'rugged',          '>= 0.25.1'
 | 
			
		||||
 | 
			
		||||
  s.add_development_dependency 'minitest', '>= 5.0'
 | 
			
		||||
  s.add_development_dependency 'rake-compiler', '~> 0.9'
 | 
			
		||||
  s.add_development_dependency 'mocha'
 | 
			
		||||
  s.add_development_dependency 'plist', '~>3.1'
 | 
			
		||||
  s.add_development_dependency 'pry'
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								grammars.yml
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								grammars.yml
									
									
									
									
									
								
							@@ -1,4 +1,3 @@
 | 
			
		||||
---
 | 
			
		||||
https://bitbucket.org/Clams/sublimesystemverilog/get/default.tar.gz:
 | 
			
		||||
- source.systemverilog
 | 
			
		||||
- source.ucfconstraints
 | 
			
		||||
@@ -45,8 +44,6 @@ vendor/grammars/Isabelle.tmbundle:
 | 
			
		||||
- source.isabelle.theory
 | 
			
		||||
vendor/grammars/JSyntax:
 | 
			
		||||
- source.j
 | 
			
		||||
vendor/grammars/Julia.tmbundle:
 | 
			
		||||
- source.julia
 | 
			
		||||
vendor/grammars/Lean.tmbundle:
 | 
			
		||||
- source.lean
 | 
			
		||||
vendor/grammars/LiveScript.tmbundle:
 | 
			
		||||
@@ -130,6 +127,9 @@ vendor/grammars/SublimePuppet:
 | 
			
		||||
- source.puppet
 | 
			
		||||
vendor/grammars/SublimeXtend:
 | 
			
		||||
- source.xtend
 | 
			
		||||
vendor/grammars/Syntax-highlighting-for-PostCSS:
 | 
			
		||||
- source.css.postcss.sugarss
 | 
			
		||||
- source.postcss
 | 
			
		||||
vendor/grammars/TLA:
 | 
			
		||||
- source.tla
 | 
			
		||||
vendor/grammars/TXL:
 | 
			
		||||
@@ -138,6 +138,11 @@ vendor/grammars/Terraform.tmLanguage:
 | 
			
		||||
- source.terraform
 | 
			
		||||
vendor/grammars/Textmate-Gosu-Bundle:
 | 
			
		||||
- source.gosu.2
 | 
			
		||||
vendor/grammars/TypeScript-TmLanguage:
 | 
			
		||||
- source.ts
 | 
			
		||||
- source.tsx
 | 
			
		||||
- text.error-list
 | 
			
		||||
- text.find-refs
 | 
			
		||||
vendor/grammars/UrWeb-Language-Definition:
 | 
			
		||||
- source.ur
 | 
			
		||||
vendor/grammars/VBDotNetSyntax:
 | 
			
		||||
@@ -187,6 +192,9 @@ vendor/grammars/atom-language-1c-bsl:
 | 
			
		||||
vendor/grammars/atom-language-clean:
 | 
			
		||||
- source.clean
 | 
			
		||||
- text.restructuredtext.clean
 | 
			
		||||
vendor/grammars/atom-language-julia:
 | 
			
		||||
- source.julia
 | 
			
		||||
- source.julia.console
 | 
			
		||||
vendor/grammars/atom-language-p4:
 | 
			
		||||
- source.p4
 | 
			
		||||
vendor/grammars/atom-language-perl6:
 | 
			
		||||
@@ -252,6 +260,8 @@ vendor/grammars/d.tmbundle:
 | 
			
		||||
vendor/grammars/dartlang:
 | 
			
		||||
- source.dart
 | 
			
		||||
- source.yaml-ext
 | 
			
		||||
vendor/grammars/data-weave-tmLanguage:
 | 
			
		||||
- source.data-weave
 | 
			
		||||
vendor/grammars/desktop.tmbundle:
 | 
			
		||||
- source.desktop
 | 
			
		||||
vendor/grammars/diff.tmbundle:
 | 
			
		||||
@@ -333,6 +343,8 @@ vendor/grammars/java.tmbundle:
 | 
			
		||||
- source.java-properties
 | 
			
		||||
- text.html.jsp
 | 
			
		||||
- text.junit-test-report
 | 
			
		||||
vendor/grammars/javadoc.tmbundle:
 | 
			
		||||
- text.html.javadoc
 | 
			
		||||
vendor/grammars/javascript-objective-j.tmbundle:
 | 
			
		||||
- source.js.objj
 | 
			
		||||
vendor/grammars/jflex.tmbundle:
 | 
			
		||||
@@ -350,6 +362,8 @@ vendor/grammars/language-asn1:
 | 
			
		||||
vendor/grammars/language-babel:
 | 
			
		||||
- source.js.jsx
 | 
			
		||||
- source.regexp.babel
 | 
			
		||||
vendor/grammars/language-ballerina:
 | 
			
		||||
- source.ballerina
 | 
			
		||||
vendor/grammars/language-batchfile:
 | 
			
		||||
- source.batchfile
 | 
			
		||||
vendor/grammars/language-blade:
 | 
			
		||||
@@ -377,6 +391,8 @@ vendor/grammars/language-csound:
 | 
			
		||||
- source.csound-score
 | 
			
		||||
vendor/grammars/language-css:
 | 
			
		||||
- source.css
 | 
			
		||||
vendor/grammars/language-cwl:
 | 
			
		||||
- source.cwl
 | 
			
		||||
vendor/grammars/language-emacs-lisp:
 | 
			
		||||
- source.emacs.lisp
 | 
			
		||||
vendor/grammars/language-fontforge:
 | 
			
		||||
@@ -394,6 +410,7 @@ vendor/grammars/language-haml:
 | 
			
		||||
- text.haml
 | 
			
		||||
- text.hamlc
 | 
			
		||||
vendor/grammars/language-haskell:
 | 
			
		||||
- annotation.liquidhaskell.haskell
 | 
			
		||||
- hint.haskell
 | 
			
		||||
- hint.message.haskell
 | 
			
		||||
- hint.type.haskell
 | 
			
		||||
@@ -401,6 +418,7 @@ vendor/grammars/language-haskell:
 | 
			
		||||
- source.cabal
 | 
			
		||||
- source.haskell
 | 
			
		||||
- source.hsc2hs
 | 
			
		||||
- source.hsig
 | 
			
		||||
- text.tex.latex.haskell
 | 
			
		||||
vendor/grammars/language-inform7:
 | 
			
		||||
- source.inform7
 | 
			
		||||
@@ -459,6 +477,10 @@ vendor/grammars/language-roff:
 | 
			
		||||
vendor/grammars/language-rpm-spec:
 | 
			
		||||
- source.changelogs.rpm-spec
 | 
			
		||||
- source.rpm-spec
 | 
			
		||||
vendor/grammars/language-ruby:
 | 
			
		||||
- source.ruby
 | 
			
		||||
- source.ruby.gemfile
 | 
			
		||||
- text.html.erb
 | 
			
		||||
vendor/grammars/language-shellscript:
 | 
			
		||||
- source.shell
 | 
			
		||||
- text.shell-session
 | 
			
		||||
@@ -485,6 +507,8 @@ vendor/grammars/language-yaml:
 | 
			
		||||
- source.yaml
 | 
			
		||||
vendor/grammars/language-yang:
 | 
			
		||||
- source.yang
 | 
			
		||||
vendor/grammars/language-yara:
 | 
			
		||||
- source.yara
 | 
			
		||||
vendor/grammars/latex.tmbundle:
 | 
			
		||||
- text.bibtex
 | 
			
		||||
- text.log.latex
 | 
			
		||||
@@ -551,7 +575,7 @@ vendor/grammars/opa.tmbundle:
 | 
			
		||||
- source.opa
 | 
			
		||||
vendor/grammars/openscad.tmbundle:
 | 
			
		||||
- source.scad
 | 
			
		||||
vendor/grammars/oz-tmbundle/Syntaxes/Oz.tmLanguage:
 | 
			
		||||
vendor/grammars/oz-tmbundle:
 | 
			
		||||
- source.oz
 | 
			
		||||
vendor/grammars/parrot:
 | 
			
		||||
- source.parrot.pir
 | 
			
		||||
@@ -588,9 +612,6 @@ vendor/grammars/rascal-syntax-highlighting:
 | 
			
		||||
- source.rascal
 | 
			
		||||
vendor/grammars/ruby-slim.tmbundle:
 | 
			
		||||
- text.slim
 | 
			
		||||
vendor/grammars/ruby.tmbundle:
 | 
			
		||||
- source.ruby
 | 
			
		||||
- text.html.erb
 | 
			
		||||
vendor/grammars/sas.tmbundle:
 | 
			
		||||
- source.SASLog
 | 
			
		||||
- source.sas
 | 
			
		||||
@@ -616,6 +637,8 @@ vendor/grammars/sourcepawn:
 | 
			
		||||
- source.sp
 | 
			
		||||
vendor/grammars/sql.tmbundle:
 | 
			
		||||
- source.sql
 | 
			
		||||
vendor/grammars/squirrel-language:
 | 
			
		||||
- source.nut
 | 
			
		||||
vendor/grammars/st2-zonefile:
 | 
			
		||||
- text.zone_file
 | 
			
		||||
vendor/grammars/standard-ml.tmbundle:
 | 
			
		||||
@@ -623,6 +646,8 @@ vendor/grammars/standard-ml.tmbundle:
 | 
			
		||||
- source.ml
 | 
			
		||||
vendor/grammars/sublime-MuPAD:
 | 
			
		||||
- source.mupad
 | 
			
		||||
vendor/grammars/sublime-angelscript:
 | 
			
		||||
- source.angelscript
 | 
			
		||||
vendor/grammars/sublime-aspectj:
 | 
			
		||||
- source.aspectj
 | 
			
		||||
vendor/grammars/sublime-autoit:
 | 
			
		||||
@@ -644,6 +669,8 @@ vendor/grammars/sublime-golo:
 | 
			
		||||
- source.golo
 | 
			
		||||
vendor/grammars/sublime-mask:
 | 
			
		||||
- source.mask
 | 
			
		||||
vendor/grammars/sublime-nearley:
 | 
			
		||||
- source.ne
 | 
			
		||||
vendor/grammars/sublime-netlinx:
 | 
			
		||||
- source.netlinx
 | 
			
		||||
- source.netlinx.erb
 | 
			
		||||
@@ -669,11 +696,6 @@ vendor/grammars/sublime-terra:
 | 
			
		||||
- source.terra
 | 
			
		||||
vendor/grammars/sublime-text-ox:
 | 
			
		||||
- source.ox
 | 
			
		||||
vendor/grammars/sublime-typescript:
 | 
			
		||||
- source.ts
 | 
			
		||||
- source.tsx
 | 
			
		||||
- text.error-list
 | 
			
		||||
- text.find-refs
 | 
			
		||||
vendor/grammars/sublime-varnish:
 | 
			
		||||
- source.varnish.vcl
 | 
			
		||||
vendor/grammars/sublime_cobol:
 | 
			
		||||
@@ -706,6 +728,8 @@ vendor/grammars/vhdl:
 | 
			
		||||
- source.vhdl
 | 
			
		||||
vendor/grammars/vue-syntax-highlight:
 | 
			
		||||
- text.html.vue
 | 
			
		||||
vendor/grammars/wdl-sublime-syntax-highlighter:
 | 
			
		||||
- source.wdl
 | 
			
		||||
vendor/grammars/xc.tmbundle:
 | 
			
		||||
- source.xc
 | 
			
		||||
vendor/grammars/xml.tmbundle:
 | 
			
		||||
 
 | 
			
		||||
@@ -275,10 +275,8 @@ module Linguist
 | 
			
		||||
          # also--importantly--without having to duplicate many (potentially
 | 
			
		||||
          # large) strings.
 | 
			
		||||
          begin
 | 
			
		||||
            encoded_newlines = ["\r\n", "\r", "\n"].
 | 
			
		||||
              map { |nl| nl.encode(ruby_encoding, "ASCII-8BIT").force_encoding(data.encoding) }
 | 
			
		||||
 | 
			
		||||
            data.split(Regexp.union(encoded_newlines), -1)
 | 
			
		||||
            
 | 
			
		||||
            data.split(encoded_newlines_re, -1)
 | 
			
		||||
          rescue Encoding::ConverterNotFoundError
 | 
			
		||||
            # The data is not splittable in the detected encoding.  Assume it's
 | 
			
		||||
            # one big line.
 | 
			
		||||
@@ -289,6 +287,51 @@ module Linguist
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def encoded_newlines_re
 | 
			
		||||
      @encoded_newlines_re ||= Regexp.union(["\r\n", "\r", "\n"].
 | 
			
		||||
                                              map { |nl| nl.encode(ruby_encoding, "ASCII-8BIT").force_encoding(data.encoding) })
 | 
			
		||||
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def first_lines(n)
 | 
			
		||||
      return lines[0...n] if defined? @lines
 | 
			
		||||
      return [] unless viewable? && data
 | 
			
		||||
 | 
			
		||||
      i, c = 0, 0
 | 
			
		||||
      while c < n && j = data.index(encoded_newlines_re, i)
 | 
			
		||||
        i = j + $&.length
 | 
			
		||||
        c += 1
 | 
			
		||||
      end
 | 
			
		||||
      data[0...i].split(encoded_newlines_re, -1)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def last_lines(n)
 | 
			
		||||
      if defined? @lines
 | 
			
		||||
        if n >= @lines.length
 | 
			
		||||
          @lines
 | 
			
		||||
        else
 | 
			
		||||
          lines[-n..-1]
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
      return [] unless viewable? && data
 | 
			
		||||
 | 
			
		||||
      no_eol = true
 | 
			
		||||
      i, c = data.length, 0
 | 
			
		||||
      k = i
 | 
			
		||||
      while c < n && j = data.rindex(encoded_newlines_re, i - 1)
 | 
			
		||||
        if c == 0 && j + $&.length == i
 | 
			
		||||
          no_eol = false
 | 
			
		||||
          n += 1
 | 
			
		||||
        end
 | 
			
		||||
        i = j
 | 
			
		||||
        k = j + $&.length
 | 
			
		||||
        c += 1
 | 
			
		||||
      end
 | 
			
		||||
      r = data[k..-1].split(encoded_newlines_re, -1)
 | 
			
		||||
      r.pop if !no_eol
 | 
			
		||||
      r
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Public: Get number of lines of code
 | 
			
		||||
    #
 | 
			
		||||
    # Requires Blob#data
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,8 @@ require 'linguist/tokenizer'
 | 
			
		||||
module Linguist
 | 
			
		||||
  # Language bayesian classifier.
 | 
			
		||||
  class Classifier
 | 
			
		||||
    CLASSIFIER_CONSIDER_BYTES = 50 * 1024
 | 
			
		||||
 | 
			
		||||
    # Public: Use the classifier to detect language of the blob.
 | 
			
		||||
    #
 | 
			
		||||
    # blob               - An object that quacks like a blob.
 | 
			
		||||
@@ -17,7 +19,7 @@ module Linguist
 | 
			
		||||
    # Returns an Array of Language objects, most probable first.
 | 
			
		||||
    def self.call(blob, possible_languages)
 | 
			
		||||
      language_names = possible_languages.map(&:name)
 | 
			
		||||
      classify(Samples.cache, blob.data, language_names).map do |name, _|
 | 
			
		||||
      classify(Samples.cache, blob.data[0...CLASSIFIER_CONSIDER_BYTES], language_names).map do |name, _|
 | 
			
		||||
        Language[name] # Return the actual Language objects
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 
 | 
			
		||||
@@ -23,21 +23,21 @@ module Linguist
 | 
			
		||||
    #
 | 
			
		||||
    # Returns a String like '100644'
 | 
			
		||||
    def mode
 | 
			
		||||
      File.stat(@fullpath).mode.to_s(8)
 | 
			
		||||
      @mode ||= File.stat(@fullpath).mode.to_s(8)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Public: Read file contents.
 | 
			
		||||
    #
 | 
			
		||||
    # Returns a String.
 | 
			
		||||
    def data
 | 
			
		||||
      File.read(@fullpath)
 | 
			
		||||
      @data ||= File.read(@fullpath)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Public: Get byte size
 | 
			
		||||
    #
 | 
			
		||||
    # Returns an Integer.
 | 
			
		||||
    def size
 | 
			
		||||
      File.size(@fullpath)
 | 
			
		||||
      @size ||= File.size(@fullpath)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -52,6 +52,8 @@ module Linguist
 | 
			
		||||
    # Return true or false
 | 
			
		||||
    def generated?
 | 
			
		||||
      xcode_file? ||
 | 
			
		||||
      cocoapods? ||
 | 
			
		||||
      carthage_build? ||
 | 
			
		||||
      generated_net_designer_file? ||
 | 
			
		||||
      generated_net_specflow_feature_file? ||
 | 
			
		||||
      composer_lock? ||
 | 
			
		||||
@@ -95,6 +97,20 @@ module Linguist
 | 
			
		||||
      ['.nib', '.xcworkspacedata', '.xcuserstate'].include?(extname)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Internal: Is the blob part of Pods/, which contains dependencies not meant for humans in pull requests.
 | 
			
		||||
    #
 | 
			
		||||
    # Returns true or false.
 | 
			
		||||
    def cocoapods?
 | 
			
		||||
      !!name.match(/(^Pods|\/Pods)\//)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Internal: Is the blob part of Carthage/Build/, which contains dependencies not meant for humans in pull requests.
 | 
			
		||||
    #
 | 
			
		||||
    # Returns true or false.
 | 
			
		||||
    def carthage_build?
 | 
			
		||||
      !!name.match(/(^|\/)Carthage\/Build\//)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Internal: Is the blob minified files?
 | 
			
		||||
    #
 | 
			
		||||
    # Consider a file minified if the average line length is
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
module Linguist
 | 
			
		||||
  # A collection of simple heuristics that can be used to better analyze languages.
 | 
			
		||||
  class Heuristics
 | 
			
		||||
    HEURISTICS_CONSIDER_BYTES = 50 * 1024
 | 
			
		||||
 | 
			
		||||
    # Public: Use heuristics to detect language of the blob.
 | 
			
		||||
    #
 | 
			
		||||
    # blob               - An object that quacks like a blob.
 | 
			
		||||
@@ -14,7 +16,7 @@ module Linguist
 | 
			
		||||
    #
 | 
			
		||||
    # Returns an Array of languages, or empty if none matched or were inconclusive.
 | 
			
		||||
    def self.call(blob, candidates)
 | 
			
		||||
      data = blob.data
 | 
			
		||||
      data = blob.data[0...HEURISTICS_CONSIDER_BYTES]
 | 
			
		||||
 | 
			
		||||
      @heuristics.each do |heuristic|
 | 
			
		||||
        if heuristic.matches?(blob.name, candidates)
 | 
			
		||||
@@ -71,7 +73,25 @@ module Linguist
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Common heuristics
 | 
			
		||||
    CPlusPlusRegex = Regexp.union(
 | 
			
		||||
        /^\s*#\s*include <(cstdint|string|vector|map|list|array|bitset|queue|stack|forward_list|unordered_map|unordered_set|(i|o|io)stream)>/,
 | 
			
		||||
        /^\s*template\s*</,
 | 
			
		||||
        /^[ \t]*try/,
 | 
			
		||||
        /^[ \t]*catch\s*\(/,
 | 
			
		||||
        /^[ \t]*(class|(using[ \t]+)?namespace)\s+\w+/,
 | 
			
		||||
        /^[ \t]*(private|public|protected):$/,
 | 
			
		||||
        /std::\w+/)
 | 
			
		||||
    ObjectiveCRegex = /^\s*(@(interface|class|protocol|property|end|synchronised|selector|implementation)\b|#import\s+.+\.h[">])/
 | 
			
		||||
    Perl5Regex = /\buse\s+(?:strict\b|v?5\.)/
 | 
			
		||||
    Perl6Regex = /^\s*(?:use\s+v6\b|\bmodule\b|\b(?:my\s+)?class\b)/
 | 
			
		||||
 | 
			
		||||
    disambiguate ".as" do |data|
 | 
			
		||||
      if /^\s*(package\s+[a-z0-9_\.]+|import\s+[a-zA-Z0-9_\.]+;|class\s+[A-Za-z0-9_]+\s+extends\s+[A-Za-z0-9_]+)/.match(data)
 | 
			
		||||
        Language["ActionScript"]
 | 
			
		||||
      else
 | 
			
		||||
        Language["AngelScript"]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    disambiguate ".asc" do |data|
 | 
			
		||||
      if /^(----[- ]BEGIN|ssh-(rsa|dss)) /.match(data)
 | 
			
		||||
@@ -211,8 +231,7 @@ module Linguist
 | 
			
		||||
    disambiguate ".h" do |data|
 | 
			
		||||
      if ObjectiveCRegex.match(data)
 | 
			
		||||
        Language["Objective-C"]
 | 
			
		||||
      elsif (/^\s*#\s*include <(cstdint|string|vector|map|list|array|bitset|queue|stack|forward_list|unordered_map|unordered_set|(i|o|io)stream)>/.match(data) ||
 | 
			
		||||
        /^\s*template\s*</.match(data) || /^[ \t]*try/.match(data) || /^[ \t]*catch\s*\(/.match(data) || /^[ \t]*(class|(using[ \t]+)?namespace)\s+\w+/.match(data) || /^[ \t]*(private|public|protected):$/.match(data) || /std::\w+/.match(data))
 | 
			
		||||
      elsif CPlusPlusRegex.match(data)
 | 
			
		||||
        Language["C++"]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
@@ -342,33 +361,25 @@ module Linguist
 | 
			
		||||
    disambiguate ".pl" do |data|
 | 
			
		||||
      if /^[^#]*:-/.match(data)
 | 
			
		||||
        Language["Prolog"]
 | 
			
		||||
      elsif /use strict|use\s+v?5\./.match(data)
 | 
			
		||||
      elsif Perl5Regex.match(data)
 | 
			
		||||
        Language["Perl"]
 | 
			
		||||
      elsif /^(use v6|(my )?class|module)/.match(data)
 | 
			
		||||
      elsif Perl6Regex.match(data)
 | 
			
		||||
        Language["Perl 6"]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    disambiguate ".pm" do |data|
 | 
			
		||||
      if /^\s*(?:use\s+v6\s*;|(?:\bmy\s+)?class|module)\b/.match(data)
 | 
			
		||||
        Language["Perl 6"]
 | 
			
		||||
      elsif /\buse\s+(?:strict\b|v?5\.)/.match(data)
 | 
			
		||||
      if Perl5Regex.match(data)
 | 
			
		||||
        Language["Perl"]
 | 
			
		||||
      elsif Perl6Regex.match(data)
 | 
			
		||||
        Language["Perl 6"]
 | 
			
		||||
      elsif /^\s*\/\* XPM \*\//.match(data)
 | 
			
		||||
        Language["XPM"]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    disambiguate ".pod", "Pod", "Perl" do |data|
 | 
			
		||||
      if /^=\w+\b/.match(data)
 | 
			
		||||
        Language["Pod"]
 | 
			
		||||
      else
 | 
			
		||||
        Language["Perl"]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    disambiguate ".pro" do |data|
 | 
			
		||||
      if /^[^#]+:-/.match(data)
 | 
			
		||||
      if /^[^\[#]+:-/.match(data)
 | 
			
		||||
        Language["Prolog"]
 | 
			
		||||
      elsif data.include?("last_client=")
 | 
			
		||||
        Language["INI"]
 | 
			
		||||
@@ -450,12 +461,12 @@ module Linguist
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    disambiguate ".t" do |data|
 | 
			
		||||
      if /^\s*%[ \t]+|^\s*var\s+\w+\s*:=\s*\w+/.match(data)
 | 
			
		||||
        Language["Turing"]
 | 
			
		||||
      elsif /^\s*(?:use\s+v6\s*;|\bmodule\b|\b(?:my\s+)?class\b)/.match(data)
 | 
			
		||||
        Language["Perl 6"]
 | 
			
		||||
      elsif /\buse\s+(?:strict\b|v?5\.)/.match(data)
 | 
			
		||||
      if Perl5Regex.match(data)
 | 
			
		||||
        Language["Perl"]
 | 
			
		||||
      elsif Perl6Regex.match(data)
 | 
			
		||||
        Language["Perl 6"]
 | 
			
		||||
      elsif /^\s*%[ \t]+|^\s*var\s+\w+\s*:=\s*\w+/.match(data)
 | 
			
		||||
        Language["Turing"]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
@@ -468,7 +479,7 @@ module Linguist
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    disambiguate ".ts" do |data|
 | 
			
		||||
      if data.include?("<TS")
 | 
			
		||||
      if /<TS\b/.match(data)
 | 
			
		||||
        Language["XML"]
 | 
			
		||||
      else
 | 
			
		||||
        Language["TypeScript"]
 | 
			
		||||
@@ -491,5 +502,14 @@ module Linguist
 | 
			
		||||
        Language["XML"]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  
 | 
			
		||||
    disambiguate ".w" do |data|
 | 
			
		||||
      if (data.include?("&ANALYZE-SUSPEND _UIB-CODE-BLOCK _CUSTOM _DEFINITIONS"))
 | 
			
		||||
        Language["OpenEdge ABL"]
 | 
			
		||||
      elsif /^@(<|\w+\.)/.match(data)
 | 
			
		||||
        Language["CWeb"]
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -110,7 +110,7 @@ module Linguist
 | 
			
		||||
    # Returns the Language or nil if none was found.
 | 
			
		||||
    def self.find_by_name(name)
 | 
			
		||||
      return nil if !name.is_a?(String) || name.to_s.empty?
 | 
			
		||||
      name && (@name_index[name.downcase] || @name_index[name.split(',').first.downcase])
 | 
			
		||||
      name && (@name_index[name.downcase] || @name_index[name.split(',', 2).first.downcase])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Public: Look up Language by one of its aliases.
 | 
			
		||||
@@ -125,7 +125,7 @@ module Linguist
 | 
			
		||||
    # Returns the Language or nil if none was found.
 | 
			
		||||
    def self.find_by_alias(name)
 | 
			
		||||
      return nil if !name.is_a?(String) || name.to_s.empty?
 | 
			
		||||
      name && (@alias_index[name.downcase] || @alias_index[name.split(',').first.downcase])
 | 
			
		||||
      name && (@alias_index[name.downcase] || @alias_index[name.split(',', 2).first.downcase])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Public: Look up Languages by filename.
 | 
			
		||||
@@ -219,10 +219,7 @@ module Linguist
 | 
			
		||||
      lang = @index[name.downcase]
 | 
			
		||||
      return lang if lang
 | 
			
		||||
 | 
			
		||||
      name = name.split(',').first
 | 
			
		||||
      return nil if name.to_s.empty?
 | 
			
		||||
 | 
			
		||||
      @index[name.downcase]
 | 
			
		||||
      @index[name.split(',', 2).first.downcase]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Public: A List of popular languages
 | 
			
		||||
 
 | 
			
		||||
@@ -210,6 +210,17 @@ Alpine Abuild:
 | 
			
		||||
  codemirror_mode: shell
 | 
			
		||||
  codemirror_mime_type: text/x-sh
 | 
			
		||||
  language_id: 14
 | 
			
		||||
AngelScript:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#C7D7DC"
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".as"
 | 
			
		||||
  - ".angelscript"
 | 
			
		||||
  tm_scope: source.angelscript
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  codemirror_mode: clike
 | 
			
		||||
  codemirror_mime_type: text/x-c++src
 | 
			
		||||
  language_id: 389477596
 | 
			
		||||
Ant Build System:
 | 
			
		||||
  type: data
 | 
			
		||||
  tm_scope: text.xml.ant
 | 
			
		||||
@@ -221,7 +232,7 @@ Ant Build System:
 | 
			
		||||
  codemirror_mime_type: application/xml
 | 
			
		||||
  language_id: 15
 | 
			
		||||
ApacheConf:
 | 
			
		||||
  type: markup
 | 
			
		||||
  type: data
 | 
			
		||||
  aliases:
 | 
			
		||||
  - aconf
 | 
			
		||||
  - apache
 | 
			
		||||
@@ -354,6 +365,14 @@ Awk:
 | 
			
		||||
  - nawk
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 28
 | 
			
		||||
Ballerina:
 | 
			
		||||
  type: programming
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".bal"
 | 
			
		||||
  tm_scope: source.ballerina
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  color: "#FF5000"
 | 
			
		||||
  language_id: 720859680
 | 
			
		||||
Batchfile:
 | 
			
		||||
  type: programming
 | 
			
		||||
  aliases:
 | 
			
		||||
@@ -625,8 +644,10 @@ CartoCSS:
 | 
			
		||||
  language_id: 53
 | 
			
		||||
Ceylon:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#dfa535"
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".ceylon"
 | 
			
		||||
  tm_scope: source.ceylon
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 54
 | 
			
		||||
Chapel:
 | 
			
		||||
@@ -786,6 +807,19 @@ Common Lisp:
 | 
			
		||||
  codemirror_mode: commonlisp
 | 
			
		||||
  codemirror_mime_type: text/x-common-lisp
 | 
			
		||||
  language_id: 66
 | 
			
		||||
Common Workflow Language:
 | 
			
		||||
  alias: cwl
 | 
			
		||||
  type: programming
 | 
			
		||||
  ace_mode: yaml
 | 
			
		||||
  codemirror_mode: yaml
 | 
			
		||||
  codemirror_mime_type: text/x-yaml
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".cwl"
 | 
			
		||||
  interpreters:
 | 
			
		||||
  - cwl-runner
 | 
			
		||||
  color: "#B5314C"
 | 
			
		||||
  tm_scope: source.cwl
 | 
			
		||||
  language_id: 988547172
 | 
			
		||||
Component Pascal:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#B0CE4E"
 | 
			
		||||
@@ -855,7 +889,7 @@ Csound:
 | 
			
		||||
  - ".orc"
 | 
			
		||||
  - ".udo"
 | 
			
		||||
  tm_scope: source.csound
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  ace_mode: csound_orchestra
 | 
			
		||||
  language_id: 73
 | 
			
		||||
Csound Document:
 | 
			
		||||
  type: programming
 | 
			
		||||
@@ -864,7 +898,7 @@ Csound Document:
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".csd"
 | 
			
		||||
  tm_scope: source.csound-document
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  ace_mode: csound_document
 | 
			
		||||
  language_id: 74
 | 
			
		||||
Csound Score:
 | 
			
		||||
  type: programming
 | 
			
		||||
@@ -873,7 +907,7 @@ Csound Score:
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".sco"
 | 
			
		||||
  tm_scope: source.csound-score
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  ace_mode: csound_score
 | 
			
		||||
  language_id: 75
 | 
			
		||||
Cuda:
 | 
			
		||||
  type: programming
 | 
			
		||||
@@ -986,6 +1020,14 @@ Dart:
 | 
			
		||||
  codemirror_mode: dart
 | 
			
		||||
  codemirror_mime_type: application/dart
 | 
			
		||||
  language_id: 87
 | 
			
		||||
DataWeave:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#003a52"
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".dwl"
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  tm_scope: source.data-weave
 | 
			
		||||
  language_id: 974514097
 | 
			
		||||
Diff:
 | 
			
		||||
  type: data
 | 
			
		||||
  extensions:
 | 
			
		||||
@@ -1086,8 +1128,7 @@ EQ:
 | 
			
		||||
  codemirror_mime_type: text/x-csharp
 | 
			
		||||
  language_id: 96
 | 
			
		||||
Eagle:
 | 
			
		||||
  type: markup
 | 
			
		||||
  color: "#814C05"
 | 
			
		||||
  type: data
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".sch"
 | 
			
		||||
  - ".brd"
 | 
			
		||||
@@ -1116,6 +1157,15 @@ Ecere Projects:
 | 
			
		||||
  codemirror_mode: javascript
 | 
			
		||||
  codemirror_mime_type: application/json
 | 
			
		||||
  language_id: 98
 | 
			
		||||
Edje Data Collection:
 | 
			
		||||
  type: data
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".edc"
 | 
			
		||||
  tm_scope: source.json
 | 
			
		||||
  ace_mode: json
 | 
			
		||||
  codemirror_mode: javascript
 | 
			
		||||
  codemirror_mime_type: application/json
 | 
			
		||||
  language_id: 342840478
 | 
			
		||||
Eiffel:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#946d57"
 | 
			
		||||
@@ -1487,8 +1537,8 @@ Gerber Image:
 | 
			
		||||
  - ".gtp"
 | 
			
		||||
  - ".gts"
 | 
			
		||||
  interpreters:
 | 
			
		||||
  - "gerbv"
 | 
			
		||||
  - "gerbview"
 | 
			
		||||
  - gerbv
 | 
			
		||||
  - gerbview
 | 
			
		||||
  tm_scope: source.gerber
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 404627610
 | 
			
		||||
@@ -1605,6 +1655,7 @@ GraphQL:
 | 
			
		||||
  type: data
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".graphql"
 | 
			
		||||
  - ".gql"
 | 
			
		||||
  tm_scope: source.graphql
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 139
 | 
			
		||||
@@ -1868,6 +1919,8 @@ INI:
 | 
			
		||||
  - ".prefs"
 | 
			
		||||
  - ".pro"
 | 
			
		||||
  - ".properties"
 | 
			
		||||
  filenames:
 | 
			
		||||
  - buildozer.spec
 | 
			
		||||
  tm_scope: source.ini
 | 
			
		||||
  aliases:
 | 
			
		||||
  - dosini
 | 
			
		||||
@@ -1890,6 +1943,7 @@ IRC log:
 | 
			
		||||
  language_id: 164
 | 
			
		||||
Idris:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#b30000"
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".idr"
 | 
			
		||||
  - ".lidr"
 | 
			
		||||
@@ -2078,6 +2132,7 @@ JavaScript:
 | 
			
		||||
  - ".jsfl"
 | 
			
		||||
  - ".jsm"
 | 
			
		||||
  - ".jss"
 | 
			
		||||
  - ".mjs"
 | 
			
		||||
  - ".njs"
 | 
			
		||||
  - ".pac"
 | 
			
		||||
  - ".sjs"
 | 
			
		||||
@@ -2149,13 +2204,6 @@ KRL:
 | 
			
		||||
  tm_scope: none
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 186
 | 
			
		||||
KiCad Board:
 | 
			
		||||
  type: data
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".brd"
 | 
			
		||||
  tm_scope: source.pcb.board
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 140848857
 | 
			
		||||
KiCad Layout:
 | 
			
		||||
  type: data
 | 
			
		||||
  aliases:
 | 
			
		||||
@@ -2171,6 +2219,13 @@ KiCad Layout:
 | 
			
		||||
  codemirror_mode: commonlisp
 | 
			
		||||
  codemirror_mime_type: text/x-common-lisp
 | 
			
		||||
  language_id: 187
 | 
			
		||||
KiCad Legacy Layout:
 | 
			
		||||
  type: data
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".brd"
 | 
			
		||||
  tm_scope: source.pcb.board
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 140848857
 | 
			
		||||
KiCad Schematic:
 | 
			
		||||
  type: data
 | 
			
		||||
  aliases:
 | 
			
		||||
@@ -2203,9 +2258,9 @@ Kotlin:
 | 
			
		||||
  language_id: 189
 | 
			
		||||
LFE:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#4C3023"
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".lfe"
 | 
			
		||||
  group: Erlang
 | 
			
		||||
  tm_scope: source.lisp
 | 
			
		||||
  ace_mode: lisp
 | 
			
		||||
  codemirror_mode: commonlisp
 | 
			
		||||
@@ -2614,7 +2669,7 @@ Mathematica:
 | 
			
		||||
  language_id: 224
 | 
			
		||||
Matlab:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#bb92ac"
 | 
			
		||||
  color: "#e16737"
 | 
			
		||||
  aliases:
 | 
			
		||||
  - octave
 | 
			
		||||
  extensions:
 | 
			
		||||
@@ -2741,6 +2796,7 @@ Monkey:
 | 
			
		||||
  type: programming
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".monkey"
 | 
			
		||||
  - ".monkey2"
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  tm_scope: source.monkey
 | 
			
		||||
  language_id: 236
 | 
			
		||||
@@ -2790,6 +2846,15 @@ NSIS:
 | 
			
		||||
  codemirror_mode: nsis
 | 
			
		||||
  codemirror_mime_type: text/x-nsis
 | 
			
		||||
  language_id: 242
 | 
			
		||||
Nearley:
 | 
			
		||||
  type: programming
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  color: "#990000"
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".ne"
 | 
			
		||||
  - ".nearley"
 | 
			
		||||
  tm_scope: source.ne
 | 
			
		||||
  language_id: 521429430
 | 
			
		||||
Nemerle:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#3d3c6e"
 | 
			
		||||
@@ -2841,7 +2906,7 @@ NewLisp:
 | 
			
		||||
  codemirror_mime_type: text/x-common-lisp
 | 
			
		||||
  language_id: 247
 | 
			
		||||
Nginx:
 | 
			
		||||
  type: markup
 | 
			
		||||
  type: data
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".nginxconf"
 | 
			
		||||
  - ".vhost"
 | 
			
		||||
@@ -2853,7 +2918,6 @@ Nginx:
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  codemirror_mode: nginx
 | 
			
		||||
  codemirror_mime_type: text/x-nginx-conf
 | 
			
		||||
  color: "#9469E9"
 | 
			
		||||
  language_id: 248
 | 
			
		||||
Nim:
 | 
			
		||||
  type: programming
 | 
			
		||||
@@ -3028,6 +3092,7 @@ OpenEdge ABL:
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".p"
 | 
			
		||||
  - ".cls"
 | 
			
		||||
  - ".w"
 | 
			
		||||
  tm_scope: source.abl
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 264
 | 
			
		||||
@@ -3271,7 +3336,6 @@ Perl:
 | 
			
		||||
  - ".ph"
 | 
			
		||||
  - ".plx"
 | 
			
		||||
  - ".pm"
 | 
			
		||||
  - ".pod"
 | 
			
		||||
  - ".psgi"
 | 
			
		||||
  - ".t"
 | 
			
		||||
  filenames:
 | 
			
		||||
@@ -3376,6 +3440,14 @@ Pony:
 | 
			
		||||
  tm_scope: source.pony
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 290
 | 
			
		||||
PostCSS:
 | 
			
		||||
  type: markup
 | 
			
		||||
  tm_scope: source.postcss
 | 
			
		||||
  group: CSS
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".pcss"
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 262764437
 | 
			
		||||
PostScript:
 | 
			
		||||
  type: markup
 | 
			
		||||
  color: "#da291c"
 | 
			
		||||
@@ -3442,7 +3514,7 @@ Propeller Spin:
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 296
 | 
			
		||||
Protocol Buffer:
 | 
			
		||||
  type: markup
 | 
			
		||||
  type: data
 | 
			
		||||
  aliases:
 | 
			
		||||
  - protobuf
 | 
			
		||||
  - Protocol Buffers
 | 
			
		||||
@@ -3487,8 +3559,7 @@ Puppet:
 | 
			
		||||
  tm_scope: source.puppet
 | 
			
		||||
  language_id: 299
 | 
			
		||||
Pure Data:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#91de79"
 | 
			
		||||
  type: data
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".pd"
 | 
			
		||||
  tm_scope: none
 | 
			
		||||
@@ -3542,6 +3613,7 @@ Python:
 | 
			
		||||
  - ".gclient"
 | 
			
		||||
  - BUCK
 | 
			
		||||
  - BUILD
 | 
			
		||||
  - BUILD.bazel
 | 
			
		||||
  - SConscript
 | 
			
		||||
  - SConstruct
 | 
			
		||||
  - Snakefile
 | 
			
		||||
@@ -4363,6 +4435,14 @@ Sublime Text Config:
 | 
			
		||||
  - ".sublime_metrics"
 | 
			
		||||
  - ".sublime_session"
 | 
			
		||||
  language_id: 423
 | 
			
		||||
SugarSS:
 | 
			
		||||
  type: markup
 | 
			
		||||
  tm_scope: source.css.postcss.sugarss
 | 
			
		||||
  group: CSS
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".sss"
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 826404698
 | 
			
		||||
SuperCollider:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#46390b"
 | 
			
		||||
@@ -4660,8 +4740,8 @@ UrWeb:
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 383
 | 
			
		||||
VCL:
 | 
			
		||||
  group: Perl
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#0298c3"
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".vcl"
 | 
			
		||||
  tm_scope: source.varnish.vcl
 | 
			
		||||
@@ -4773,8 +4853,7 @@ Wavefront Object:
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 393
 | 
			
		||||
Web Ontology Language:
 | 
			
		||||
  type: markup
 | 
			
		||||
  color: "#9cc9dd"
 | 
			
		||||
  type: data
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".owl"
 | 
			
		||||
  tm_scope: text.xml
 | 
			
		||||
@@ -4855,12 +4934,16 @@ XML:
 | 
			
		||||
  - ".ant"
 | 
			
		||||
  - ".axml"
 | 
			
		||||
  - ".builds"
 | 
			
		||||
  - ".ccproj"
 | 
			
		||||
  - ".ccxml"
 | 
			
		||||
  - ".clixml"
 | 
			
		||||
  - ".cproject"
 | 
			
		||||
  - ".cscfg"
 | 
			
		||||
  - ".csdef"
 | 
			
		||||
  - ".csl"
 | 
			
		||||
  - ".csproj"
 | 
			
		||||
  - ".ct"
 | 
			
		||||
  - ".depproj"
 | 
			
		||||
  - ".dita"
 | 
			
		||||
  - ".ditamap"
 | 
			
		||||
  - ".ditaval"
 | 
			
		||||
@@ -4883,6 +4966,8 @@ XML:
 | 
			
		||||
  - ".mm"
 | 
			
		||||
  - ".mod"
 | 
			
		||||
  - ".mxml"
 | 
			
		||||
  - ".natvis"
 | 
			
		||||
  - ".ndproj"
 | 
			
		||||
  - ".nproj"
 | 
			
		||||
  - ".nuspec"
 | 
			
		||||
  - ".odd"
 | 
			
		||||
@@ -4890,6 +4975,7 @@ XML:
 | 
			
		||||
  - ".pkgproj"
 | 
			
		||||
  - ".plist"
 | 
			
		||||
  - ".pluginspec"
 | 
			
		||||
  - ".proj"
 | 
			
		||||
  - ".props"
 | 
			
		||||
  - ".ps1xml"
 | 
			
		||||
  - ".psc1"
 | 
			
		||||
@@ -4900,6 +4986,7 @@ XML:
 | 
			
		||||
  - ".sch"
 | 
			
		||||
  - ".scxml"
 | 
			
		||||
  - ".sfproj"
 | 
			
		||||
  - ".shproj"
 | 
			
		||||
  - ".srdf"
 | 
			
		||||
  - ".storyboard"
 | 
			
		||||
  - ".stTheme"
 | 
			
		||||
@@ -4961,11 +5048,11 @@ XPM:
 | 
			
		||||
  tm_scope: source.c
 | 
			
		||||
  language_id: 781846279
 | 
			
		||||
XPages:
 | 
			
		||||
  type: programming
 | 
			
		||||
  type: data
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".xsp-config"
 | 
			
		||||
  - ".xsp.metadata"
 | 
			
		||||
  tm_scope: none
 | 
			
		||||
  tm_scope: text.xml
 | 
			
		||||
  ace_mode: xml
 | 
			
		||||
  codemirror_mode: xml
 | 
			
		||||
  codemirror_mime_type: text/xml
 | 
			
		||||
@@ -5050,6 +5137,7 @@ YAML:
 | 
			
		||||
  - ".yml.mysql"
 | 
			
		||||
  filenames:
 | 
			
		||||
  - ".clang-format"
 | 
			
		||||
  - ".clang-tidy"
 | 
			
		||||
  ace_mode: yaml
 | 
			
		||||
  codemirror_mode: yaml
 | 
			
		||||
  codemirror_mime_type: text/x-yaml
 | 
			
		||||
@@ -5061,6 +5149,14 @@ YANG:
 | 
			
		||||
  tm_scope: source.yang
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 408
 | 
			
		||||
YARA:
 | 
			
		||||
  type: data
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".yar"
 | 
			
		||||
  - ".yara"
 | 
			
		||||
  tm_scope: source.yara
 | 
			
		||||
  language_id: 805122868
 | 
			
		||||
Yacc:
 | 
			
		||||
  type: programming
 | 
			
		||||
  extensions:
 | 
			
		||||
@@ -5159,6 +5255,14 @@ reStructuredText:
 | 
			
		||||
  codemirror_mode: rst
 | 
			
		||||
  codemirror_mime_type: text/x-rst
 | 
			
		||||
  language_id: 419
 | 
			
		||||
wdl:
 | 
			
		||||
  type: programming
 | 
			
		||||
  color: "#42f1f4"
 | 
			
		||||
  extensions:
 | 
			
		||||
  - ".wdl"
 | 
			
		||||
  tm_scope: source.wdl
 | 
			
		||||
  ace_mode: text
 | 
			
		||||
  language_id: 374521672
 | 
			
		||||
wisp:
 | 
			
		||||
  type: programming
 | 
			
		||||
  ace_mode: clojure
 | 
			
		||||
 
 | 
			
		||||
@@ -109,8 +109,8 @@ module Linguist
 | 
			
		||||
      # Returns an Array with one Language if the blob has a Vim or Emacs modeline
 | 
			
		||||
      # that matches a Language name or alias. Returns an empty array if no match.
 | 
			
		||||
      def self.call(blob, _ = nil)
 | 
			
		||||
        header = blob.lines.first(SEARCH_SCOPE).join("\n")
 | 
			
		||||
        footer = blob.lines.last(SEARCH_SCOPE).join("\n")
 | 
			
		||||
        header = blob.first_lines(SEARCH_SCOPE).join("\n")
 | 
			
		||||
        footer = blob.last_lines(SEARCH_SCOPE).join("\n")
 | 
			
		||||
        Array(Language.find_by_alias(modeline(header + footer)))
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
require 'strscan'
 | 
			
		||||
require 'linguist/linguist'
 | 
			
		||||
 | 
			
		||||
module Linguist
 | 
			
		||||
  # Generic programming language tokenizer.
 | 
			
		||||
@@ -15,191 +16,5 @@ module Linguist
 | 
			
		||||
    def self.tokenize(data)
 | 
			
		||||
      new.extract_tokens(data)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Read up to 100KB
 | 
			
		||||
    BYTE_LIMIT = 100_000
 | 
			
		||||
 | 
			
		||||
    # Start state on token, ignore anything till the next newline
 | 
			
		||||
    SINGLE_LINE_COMMENTS = [
 | 
			
		||||
      '//', # C
 | 
			
		||||
      '--', # Ada, Haskell, AppleScript
 | 
			
		||||
      '#',  # Ruby
 | 
			
		||||
      '%',  # Tex
 | 
			
		||||
      '"',  # Vim
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    # Start state on opening token, ignore anything until the closing
 | 
			
		||||
    # token is reached.
 | 
			
		||||
    MULTI_LINE_COMMENTS = [
 | 
			
		||||
      ['/*', '*/'],    # C
 | 
			
		||||
      ['<!--', '-->'], # XML
 | 
			
		||||
      ['{-', '-}'],    # Haskell
 | 
			
		||||
      ['(*', '*)'],    # Coq
 | 
			
		||||
      ['"""', '"""'],  # Python
 | 
			
		||||
      ["'''", "'''"]   # Python
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    START_SINGLE_LINE_COMMENT =  Regexp.compile(SINGLE_LINE_COMMENTS.map { |c|
 | 
			
		||||
      "\s*#{Regexp.escape(c)} "
 | 
			
		||||
    }.join("|"))
 | 
			
		||||
 | 
			
		||||
    START_MULTI_LINE_COMMENT =  Regexp.compile(MULTI_LINE_COMMENTS.map { |c|
 | 
			
		||||
      Regexp.escape(c[0])
 | 
			
		||||
    }.join("|"))
 | 
			
		||||
 | 
			
		||||
    # Internal: Extract generic tokens from data.
 | 
			
		||||
    #
 | 
			
		||||
    # data - String to scan.
 | 
			
		||||
    #
 | 
			
		||||
    # Examples
 | 
			
		||||
    #
 | 
			
		||||
    #   extract_tokens("printf('Hello')")
 | 
			
		||||
    #   # => ['printf', '(', ')']
 | 
			
		||||
    #
 | 
			
		||||
    # Returns Array of token Strings.
 | 
			
		||||
    def extract_tokens(data)
 | 
			
		||||
      s = StringScanner.new(data)
 | 
			
		||||
 | 
			
		||||
      tokens = []
 | 
			
		||||
      until s.eos?
 | 
			
		||||
        break if s.pos >= BYTE_LIMIT
 | 
			
		||||
 | 
			
		||||
        if token = s.scan(/^#!.+$/)
 | 
			
		||||
          if name = extract_shebang(token)
 | 
			
		||||
            tokens << "SHEBANG#!#{name}"
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
        # Single line comment
 | 
			
		||||
        elsif s.beginning_of_line? && token = s.scan(START_SINGLE_LINE_COMMENT)
 | 
			
		||||
          # tokens << token.strip
 | 
			
		||||
          s.skip_until(/\n|\Z/)
 | 
			
		||||
 | 
			
		||||
        # Multiline comments
 | 
			
		||||
        elsif token = s.scan(START_MULTI_LINE_COMMENT)
 | 
			
		||||
          # tokens << token
 | 
			
		||||
          close_token = MULTI_LINE_COMMENTS.assoc(token)[1]
 | 
			
		||||
          s.skip_until(Regexp.compile(Regexp.escape(close_token)))
 | 
			
		||||
          # tokens << close_token
 | 
			
		||||
 | 
			
		||||
        # Skip single or double quoted strings
 | 
			
		||||
        elsif s.scan(/"/)
 | 
			
		||||
          if s.peek(1) == "\""
 | 
			
		||||
            s.getch
 | 
			
		||||
          else
 | 
			
		||||
            s.skip_until(/(?<!\\)"/)
 | 
			
		||||
          end
 | 
			
		||||
        elsif s.scan(/'/)
 | 
			
		||||
          if s.peek(1) == "'"
 | 
			
		||||
            s.getch
 | 
			
		||||
          else
 | 
			
		||||
            s.skip_until(/(?<!\\)'/)
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
        # Skip number literals
 | 
			
		||||
        elsif s.scan(/(0x\h(\h|\.)*|\d(\d|\.)*)([uU][lL]{0,2}|([eE][-+]\d*)?[fFlL]*)/)
 | 
			
		||||
 | 
			
		||||
        # SGML style brackets
 | 
			
		||||
        elsif token = s.scan(/<[^\s<>][^<>]*>/)
 | 
			
		||||
          extract_sgml_tokens(token).each { |t| tokens << t }
 | 
			
		||||
 | 
			
		||||
        # Common programming punctuation
 | 
			
		||||
        elsif token = s.scan(/;|\{|\}|\(|\)|\[|\]/)
 | 
			
		||||
          tokens << token
 | 
			
		||||
 | 
			
		||||
        # Regular token
 | 
			
		||||
        elsif token = s.scan(/[\w\.@#\/\*]+/)
 | 
			
		||||
          tokens << token
 | 
			
		||||
 | 
			
		||||
        # Common operators
 | 
			
		||||
        elsif token = s.scan(/<<?|\+|\-|\*|\/|%|&&?|\|\|?/)
 | 
			
		||||
          tokens << token
 | 
			
		||||
 | 
			
		||||
        else
 | 
			
		||||
          s.getch
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      tokens
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Internal: Extract normalized shebang command token.
 | 
			
		||||
    #
 | 
			
		||||
    # Examples
 | 
			
		||||
    #
 | 
			
		||||
    #   extract_shebang("#!/usr/bin/ruby")
 | 
			
		||||
    #   # => "ruby"
 | 
			
		||||
    #
 | 
			
		||||
    #   extract_shebang("#!/usr/bin/env node")
 | 
			
		||||
    #   # => "node"
 | 
			
		||||
    #
 | 
			
		||||
    #   extract_shebang("#!/usr/bin/env A=B foo=bar awk -f")
 | 
			
		||||
    #   # => "awk"
 | 
			
		||||
    #
 | 
			
		||||
    # Returns String token or nil it couldn't be parsed.
 | 
			
		||||
    def extract_shebang(data)
 | 
			
		||||
      s = StringScanner.new(data)
 | 
			
		||||
 | 
			
		||||
      if path = s.scan(/^#!\s*\S+/)
 | 
			
		||||
        script = path.split('/').last
 | 
			
		||||
        if script == 'env'
 | 
			
		||||
          s.scan(/\s+/)
 | 
			
		||||
          s.scan(/.*=[^\s]+\s+/)
 | 
			
		||||
          script = s.scan(/\S+/)
 | 
			
		||||
        end
 | 
			
		||||
        script = script[/[^\d]+/, 0] if script
 | 
			
		||||
        return script
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Internal: Extract tokens from inside SGML tag.
 | 
			
		||||
    #
 | 
			
		||||
    # data - SGML tag String.
 | 
			
		||||
    #
 | 
			
		||||
    # Examples
 | 
			
		||||
    #
 | 
			
		||||
    #   extract_sgml_tokens("<a href='' class=foo>")
 | 
			
		||||
    #   # => ["<a>", "href="]
 | 
			
		||||
    #
 | 
			
		||||
    # Returns Array of token Strings.
 | 
			
		||||
    def extract_sgml_tokens(data)
 | 
			
		||||
      s = StringScanner.new(data)
 | 
			
		||||
 | 
			
		||||
      tokens = []
 | 
			
		||||
 | 
			
		||||
      until s.eos?
 | 
			
		||||
        # Emit start token
 | 
			
		||||
        if token = s.scan(/<\/?[^\s>]+/)
 | 
			
		||||
          tokens << "#{token}>"
 | 
			
		||||
 | 
			
		||||
        # Emit attributes with trailing =
 | 
			
		||||
        elsif token = s.scan(/\w+=/)
 | 
			
		||||
          tokens << token
 | 
			
		||||
 | 
			
		||||
          # Then skip over attribute value
 | 
			
		||||
          if s.scan(/"/)
 | 
			
		||||
            s.skip_until(/[^\\]"/)
 | 
			
		||||
          elsif s.scan(/'/)
 | 
			
		||||
            s.skip_until(/[^\\]'/)
 | 
			
		||||
          else
 | 
			
		||||
            s.skip_until(/\w+/)
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
        # Emit lone attributes
 | 
			
		||||
        elsif token = s.scan(/\w+/)
 | 
			
		||||
          tokens << token
 | 
			
		||||
 | 
			
		||||
        # Stop at the end of the tag
 | 
			
		||||
        elsif s.scan(/>/)
 | 
			
		||||
          s.terminate
 | 
			
		||||
 | 
			
		||||
        else
 | 
			
		||||
          s.getch
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      tokens
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -19,9 +19,7 @@
 | 
			
		||||
- (^|/)dist/
 | 
			
		||||
 | 
			
		||||
# C deps
 | 
			
		||||
#  https://github.com/joyent/node
 | 
			
		||||
- ^deps/
 | 
			
		||||
- ^tools/
 | 
			
		||||
- (^|/)configure$
 | 
			
		||||
- (^|/)config.guess$
 | 
			
		||||
- (^|/)config.sub$
 | 
			
		||||
@@ -65,6 +63,7 @@
 | 
			
		||||
 | 
			
		||||
# Font Awesome
 | 
			
		||||
- (^|/)font-awesome\.(css|less|scss|styl)$
 | 
			
		||||
- (^|/)font-awesome/.*\.(css|less|scss|styl)$
 | 
			
		||||
 | 
			
		||||
# Foundation css
 | 
			
		||||
- (^|/)foundation\.(css|less|scss|styl)$
 | 
			
		||||
@@ -81,6 +80,9 @@
 | 
			
		||||
# Animate.css
 | 
			
		||||
- (^|/)animate\.(css|less|scss|styl)$
 | 
			
		||||
 | 
			
		||||
# Select2
 | 
			
		||||
- (^|/)select2/.*\.(css|scss|js)$
 | 
			
		||||
 | 
			
		||||
# Vendored dependencies
 | 
			
		||||
- third[-_]?party/
 | 
			
		||||
- 3rd[-_]?party/
 | 
			
		||||
@@ -119,6 +121,15 @@
 | 
			
		||||
# jQuery File Upload
 | 
			
		||||
- (^|/)jquery\.fileupload(-\w+)?\.js$
 | 
			
		||||
 | 
			
		||||
# jQuery dataTables
 | 
			
		||||
- jquery.dataTables.js
 | 
			
		||||
 | 
			
		||||
# bootboxjs
 | 
			
		||||
- bootbox.js
 | 
			
		||||
 | 
			
		||||
# pdf-worker
 | 
			
		||||
- pdf.worker.js
 | 
			
		||||
 | 
			
		||||
# Slick
 | 
			
		||||
- (^|/)slick\.\w+.js$
 | 
			
		||||
 | 
			
		||||
@@ -135,6 +146,9 @@
 | 
			
		||||
- .sublime-project
 | 
			
		||||
- .sublime-workspace
 | 
			
		||||
 | 
			
		||||
# VS Code workspace files
 | 
			
		||||
- .vscode
 | 
			
		||||
 | 
			
		||||
# Prototype
 | 
			
		||||
- (^|/)prototype(.*)\.js$
 | 
			
		||||
- (^|/)effects\.js$
 | 
			
		||||
@@ -227,10 +241,7 @@
 | 
			
		||||
- \.imageset/
 | 
			
		||||
 | 
			
		||||
# Carthage
 | 
			
		||||
- ^Carthage/
 | 
			
		||||
 | 
			
		||||
# Cocoapods
 | 
			
		||||
- ^Pods/
 | 
			
		||||
- (^|/)Carthage/
 | 
			
		||||
 | 
			
		||||
# Sparkle
 | 
			
		||||
- (^|/)Sparkle/
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
module Linguist
 | 
			
		||||
  VERSION = "5.2.0"
 | 
			
		||||
  VERSION = "5.3.3"
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "repository": "https://github.com/github/linguist",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "season": "~>5.4"
 | 
			
		||||
  },
 | 
			
		||||
  "license": "MIT"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								samples/ActionScript/FooBar.as
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								samples/ActionScript/FooBar.as
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
// A sample for Actionscript.
 | 
			
		||||
 | 
			
		||||
package foobar
 | 
			
		||||
{
 | 
			
		||||
	import flash.display.MovieClip;
 | 
			
		||||
 | 
			
		||||
	class Bar
 | 
			
		||||
	{
 | 
			
		||||
		public function getNumber():Number
 | 
			
		||||
		{
 | 
			
		||||
			return 10;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	class Foo extends Bar
 | 
			
		||||
	{
 | 
			
		||||
		private var ourNumber:Number = 25;
 | 
			
		||||
 | 
			
		||||
		override public function getNumber():Number
 | 
			
		||||
		{
 | 
			
		||||
			return ourNumber;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	class Main extends MovieClip
 | 
			
		||||
	{
 | 
			
		||||
		public function Main()
 | 
			
		||||
		{
 | 
			
		||||
			var x:Bar = new Bar();
 | 
			
		||||
			var y:Foo = new Foo();
 | 
			
		||||
			trace(x.getNumber());
 | 
			
		||||
			trace(y.getNumber());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								samples/ActionScript/HelloWorld.as
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								samples/ActionScript/HelloWorld.as
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
package mypackage
 | 
			
		||||
{
 | 
			
		||||
	public class Hello
 | 
			
		||||
	{
 | 
			
		||||
		/* Let's say hello!
 | 
			
		||||
		 * This is just a test script for Linguist's Actionscript detection.
 | 
			
		||||
		 */
 | 
			
		||||
		public function sayHello():void
 | 
			
		||||
		{
 | 
			
		||||
			trace("Hello, world");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								samples/AngelScript/botmanager.as
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								samples/AngelScript/botmanager.as
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
/*
 | 
			
		||||
*	This is a sample script.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "BotManagerInterface.acs"
 | 
			
		||||
 | 
			
		||||
BotManager::BotManager g_BotManager( @CreateDumbBot );
 | 
			
		||||
 | 
			
		||||
CConCommand@ m_pAddBot;
 | 
			
		||||
 | 
			
		||||
void PluginInit()
 | 
			
		||||
{
 | 
			
		||||
	g_BotManager.PluginInit();
 | 
			
		||||
	
 | 
			
		||||
	@m_pAddBot = @CConCommand( "addbot", "Adds a new bot with the given name", @AddBotCallback );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AddBotCallback( const CCommand@ args )
 | 
			
		||||
{
 | 
			
		||||
	if( args.ArgC() < 2 )
 | 
			
		||||
	{
 | 
			
		||||
		g_Game.AlertMessage( at_console, "Usage: addbot <name>" );
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	BotManager::BaseBot@ pBot = g_BotManager.CreateBot( args[ 1 ] );
 | 
			
		||||
	
 | 
			
		||||
	if( pBot !is null )
 | 
			
		||||
	{
 | 
			
		||||
		g_Game.AlertMessage( at_console, "Created bot " + args[ 1 ] + "\n" );
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		g_Game.AlertMessage( at_console, "Could not create bot\n" );
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
final class DumbBot : BotManager::BaseBot
 | 
			
		||||
{	
 | 
			
		||||
	DumbBot( CBasePlayer@ pPlayer )
 | 
			
		||||
	{
 | 
			
		||||
		super( pPlayer );
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	void Think()
 | 
			
		||||
	{
 | 
			
		||||
		BotManager::BaseBot::Think();
 | 
			
		||||
		
 | 
			
		||||
		// If the bot is dead and can be respawned, send a button press
 | 
			
		||||
		if( Player.pev.deadflag >= DEAD_RESPAWNABLE )
 | 
			
		||||
		{
 | 
			
		||||
			Player.pev.button |= IN_ATTACK;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			Player.pev.button &= ~IN_ATTACK;
 | 
			
		||||
		
 | 
			
		||||
		KeyValueBuffer@ pInfoBuffer = g_EngineFuncs.GetInfoKeyBuffer( Player.edict() );
 | 
			
		||||
		
 | 
			
		||||
		pInfoBuffer.SetValue( "topcolor", Math.RandomLong( 0, 255 ) );
 | 
			
		||||
		pInfoBuffer.SetValue( "bottomcolor", Math.RandomLong( 0, 255 ) );
 | 
			
		||||
		
 | 
			
		||||
		if( Math.RandomLong( 0, 100 ) > 10 )
 | 
			
		||||
			Player.pev.button |= IN_ATTACK;
 | 
			
		||||
		else
 | 
			
		||||
			Player.pev.button &= ~IN_ATTACK;
 | 
			
		||||
			
 | 
			
		||||
		for( uint uiIndex = 0; uiIndex < 3; ++uiIndex )
 | 
			
		||||
		{
 | 
			
		||||
			m_vecVelocity[ uiIndex ] = Math.RandomLong( -50, 50 );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BotManager::BaseBot@ CreateDumbBot( CBasePlayer@ pPlayer )
 | 
			
		||||
{
 | 
			
		||||
	return @DumbBot( pPlayer );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										396
									
								
								samples/AngelScript/payload.as
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										396
									
								
								samples/AngelScript/payload.as
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,396 @@
 | 
			
		||||
// Sample script.
 | 
			
		||||
// Source: https://github.com/codecat/ssbd-payload
 | 
			
		||||
 | 
			
		||||
array<WorldScript::PayloadBeginTrigger@> g_payloadBeginTriggers;
 | 
			
		||||
array<WorldScript::PayloadTeamForcefield@> g_teamForceFields;
 | 
			
		||||
 | 
			
		||||
[GameMode]
 | 
			
		||||
class Payload : TeamVersusGameMode
 | 
			
		||||
{
 | 
			
		||||
	[Editable]
 | 
			
		||||
	UnitFeed PayloadUnit;
 | 
			
		||||
 | 
			
		||||
	[Editable]
 | 
			
		||||
	UnitFeed FirstNode;
 | 
			
		||||
 | 
			
		||||
	[Editable default=10]
 | 
			
		||||
	int PrepareTime;
 | 
			
		||||
 | 
			
		||||
	[Editable default=300]
 | 
			
		||||
	int TimeLimit;
 | 
			
		||||
 | 
			
		||||
	[Editable default=90]
 | 
			
		||||
	int TimeAddCheckpoint;
 | 
			
		||||
 | 
			
		||||
	[Editable default=2]
 | 
			
		||||
	float TimeOvertime;
 | 
			
		||||
 | 
			
		||||
	[Editable default=1000]
 | 
			
		||||
	int TimePayloadHeal;
 | 
			
		||||
 | 
			
		||||
	[Editable default=1]
 | 
			
		||||
	int PayloadHeal;
 | 
			
		||||
 | 
			
		||||
	PayloadBehavior@ m_payload;
 | 
			
		||||
 | 
			
		||||
	int m_tmStarting;
 | 
			
		||||
	int m_tmStarted;
 | 
			
		||||
	int m_tmLimitCustom;
 | 
			
		||||
	int m_tmOvertime;
 | 
			
		||||
	int m_tmInOvertime;
 | 
			
		||||
 | 
			
		||||
	PayloadHUD@ m_payloadHUD;
 | 
			
		||||
	PayloadClassSwitchWindow@ m_switchClass;
 | 
			
		||||
 | 
			
		||||
	array<SValue@>@ m_switchedSidesData;
 | 
			
		||||
 | 
			
		||||
	Payload(Scene@ scene)
 | 
			
		||||
	{
 | 
			
		||||
		super(scene);
 | 
			
		||||
 | 
			
		||||
		m_tmRespawnCountdown = 5000;
 | 
			
		||||
 | 
			
		||||
		@m_payloadHUD = PayloadHUD(m_guiBuilder);
 | 
			
		||||
		@m_switchTeam = PayloadTeamSwitchWindow(m_guiBuilder);
 | 
			
		||||
		@m_switchClass = PayloadClassSwitchWindow(m_guiBuilder);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void UpdateFrame(int ms, GameInput& gameInput, MenuInput& menuInput) override
 | 
			
		||||
	{
 | 
			
		||||
		TeamVersusGameMode::UpdateFrame(ms, gameInput, menuInput);
 | 
			
		||||
 | 
			
		||||
		m_payloadHUD.Update(ms);
 | 
			
		||||
 | 
			
		||||
		if (Network::IsServer())
 | 
			
		||||
		{
 | 
			
		||||
			uint64 tmNow = CurrPlaytimeLevel();
 | 
			
		||||
 | 
			
		||||
			if (m_tmStarting == 0)
 | 
			
		||||
			{
 | 
			
		||||
				if (GetPlayersInTeam(0) > 0 && GetPlayersInTeam(1) > 0)
 | 
			
		||||
				{
 | 
			
		||||
					m_tmStarting = tmNow;
 | 
			
		||||
					(Network::Message("GameStarting") << m_tmStarting).SendToAll();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (m_tmStarting > 0 && m_tmStarted == 0 && tmNow - m_tmStarting > PrepareTime * 1000)
 | 
			
		||||
			{
 | 
			
		||||
				m_tmStarted = tmNow;
 | 
			
		||||
				(Network::Message("GameStarted") << m_tmStarted).SendToAll();
 | 
			
		||||
 | 
			
		||||
				for (uint i = 0; i < g_payloadBeginTriggers.length(); i++)
 | 
			
		||||
				{
 | 
			
		||||
					WorldScript@ ws = WorldScript::GetWorldScript(g_scene, g_payloadBeginTriggers[i]);
 | 
			
		||||
					ws.Execute();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!m_ended && m_tmStarted > 0)
 | 
			
		||||
			CheckTimeReached(ms);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	string NameForTeam(int index) override
 | 
			
		||||
	{
 | 
			
		||||
		if (index == 0)
 | 
			
		||||
			return "Defenders";
 | 
			
		||||
		else if (index == 1)
 | 
			
		||||
			return "Attackers";
 | 
			
		||||
 | 
			
		||||
		return "Unknown";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void CheckTimeReached(int dt)
 | 
			
		||||
	{
 | 
			
		||||
		// Check if time limit is not reached yet
 | 
			
		||||
		if (m_tmLimitCustom - (CurrPlaytimeLevel() - m_tmStarted) > 0)
 | 
			
		||||
		{
 | 
			
		||||
			// Don't need to continue checking
 | 
			
		||||
			m_tmOvertime = 0;
 | 
			
		||||
			m_tmInOvertime = 0;
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Count how long we're in overtime for later time limit fixing when we reach a checkpoint
 | 
			
		||||
		if (m_tmOvertime > 0)
 | 
			
		||||
			m_tmInOvertime += dt;
 | 
			
		||||
 | 
			
		||||
		// Check if there are any attackers still inside
 | 
			
		||||
		if (m_payload.AttackersInside() > 0)
 | 
			
		||||
		{
 | 
			
		||||
			// We have overtime
 | 
			
		||||
			m_tmOvertime = int(TimeOvertime * 1000);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// If we have overtime
 | 
			
		||||
		if (m_tmOvertime > 0)
 | 
			
		||||
		{
 | 
			
		||||
			// Decrease timer
 | 
			
		||||
			m_tmOvertime -= dt;
 | 
			
		||||
			if (m_tmOvertime <= 0)
 | 
			
		||||
			{
 | 
			
		||||
				// Overtime countdown reached, time limit reached
 | 
			
		||||
				TimeReached();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			// No overtime, so time limit is reached
 | 
			
		||||
			TimeReached();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void TimeReached()
 | 
			
		||||
	{
 | 
			
		||||
		if (!Network::IsServer())
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		(Network::Message("TimeReached")).SendToAll();
 | 
			
		||||
		SetWinner(false);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool ShouldFreezeControls() override
 | 
			
		||||
	{
 | 
			
		||||
		return m_switchClass.m_visible
 | 
			
		||||
		    || TeamVersusGameMode::ShouldFreezeControls();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool ShouldDisplayCursor() override
 | 
			
		||||
	{
 | 
			
		||||
		return m_switchClass.m_visible
 | 
			
		||||
		    || TeamVersusGameMode::ShouldDisplayCursor();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool CanSwitchTeams() override
 | 
			
		||||
	{
 | 
			
		||||
		return m_tmStarted == 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	PlayerRecord@ CreatePlayerRecord() override
 | 
			
		||||
	{
 | 
			
		||||
		return PayloadPlayerRecord();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int GetPlayerClassCount(PlayerClass playerClass, TeamVersusScore@ team)
 | 
			
		||||
	{
 | 
			
		||||
		if (team is null)
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		int ret = 0;
 | 
			
		||||
		for (uint i = 0; i < team.m_players.length(); i++)
 | 
			
		||||
		{
 | 
			
		||||
			if (team.m_players[i].peer == 255)
 | 
			
		||||
				continue;
 | 
			
		||||
			auto record = cast<PayloadPlayerRecord>(team.m_players[i]);
 | 
			
		||||
			if (record.playerClass == playerClass)
 | 
			
		||||
				ret++;
 | 
			
		||||
		}
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void PlayerClassesUpdated()
 | 
			
		||||
	{
 | 
			
		||||
		m_switchClass.PlayerClassesUpdated();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void SetWinner(bool attackers)
 | 
			
		||||
	{
 | 
			
		||||
		if (attackers)
 | 
			
		||||
			print("Attackers win!");
 | 
			
		||||
		else
 | 
			
		||||
			print("Defenders win!");
 | 
			
		||||
 | 
			
		||||
		m_payloadHUD.Winner(attackers);
 | 
			
		||||
		EndMatch();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void DisplayPlayerName(int idt, SpriteBatch& sb, PlayerRecord@ record, PlayerHusk@ plr, vec2 pos) override
 | 
			
		||||
	{
 | 
			
		||||
		TeamVersusGameMode::DisplayPlayerName(idt, sb, record, plr, pos);
 | 
			
		||||
 | 
			
		||||
		m_payloadHUD.DisplayPlayerName(idt, sb, cast<PayloadPlayerRecord>(record), plr, pos);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void RenderFrame(int idt, SpriteBatch& sb) override
 | 
			
		||||
	{
 | 
			
		||||
		Player@ player = GetLocalPlayer();
 | 
			
		||||
		if (player !is null)
 | 
			
		||||
		{
 | 
			
		||||
			PlayerHealgun@ healgun = cast<PlayerHealgun>(player.m_currWeapon);
 | 
			
		||||
			if (healgun !is null)
 | 
			
		||||
				healgun.RenderMarkers(idt, sb);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		TeamVersusGameMode::RenderFrame(idt, sb);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void RenderWidgets(PlayerRecord@ player, int idt, SpriteBatch& sb) override
 | 
			
		||||
	{
 | 
			
		||||
		m_payloadHUD.Draw(sb, idt);
 | 
			
		||||
 | 
			
		||||
		TeamVersusGameMode::RenderWidgets(player, idt, sb);
 | 
			
		||||
 | 
			
		||||
		m_switchClass.Draw(sb, idt);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void GoNextMap() override
 | 
			
		||||
	{
 | 
			
		||||
		if (m_switchedSidesData !is null)
 | 
			
		||||
		{
 | 
			
		||||
			TeamVersusGameMode::GoNextMap();
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ChangeLevel(GetCurrentLevelFilename());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void SpawnPlayers() override
 | 
			
		||||
	{
 | 
			
		||||
		if (m_switchedSidesData is null)
 | 
			
		||||
		{
 | 
			
		||||
			TeamVersusGameMode::SpawnPlayers();
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (Network::IsServer())
 | 
			
		||||
		{
 | 
			
		||||
			for (uint i = 0; i < m_switchedSidesData.length(); i += 2)
 | 
			
		||||
			{
 | 
			
		||||
				uint peer = uint(m_switchedSidesData[i].GetInteger());
 | 
			
		||||
				uint team = uint(m_switchedSidesData[i + 1].GetInteger());
 | 
			
		||||
 | 
			
		||||
				TeamVersusScore@ joinScore = FindTeamScore(team);
 | 
			
		||||
				if (joinScore is m_teamScores[0])
 | 
			
		||||
					@joinScore = m_teamScores[1];
 | 
			
		||||
				else
 | 
			
		||||
					@joinScore = m_teamScores[0];
 | 
			
		||||
 | 
			
		||||
				for (uint j = 0; j < g_players.length(); j++)
 | 
			
		||||
				{
 | 
			
		||||
					if (g_players[j].peer != peer)
 | 
			
		||||
						continue;
 | 
			
		||||
					SpawnPlayer(j, vec2(), 0, joinScore.m_team);
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Save(SValueBuilder& builder) override
 | 
			
		||||
	{
 | 
			
		||||
		if (m_switchedSidesData is null)
 | 
			
		||||
		{
 | 
			
		||||
			builder.PushArray("teams");
 | 
			
		||||
			for (uint i = 0; i < g_players.length(); i++)
 | 
			
		||||
			{
 | 
			
		||||
				if (g_players[i].peer == 255)
 | 
			
		||||
					continue;
 | 
			
		||||
				builder.PushInteger(g_players[i].peer);
 | 
			
		||||
				builder.PushInteger(g_players[i].team);
 | 
			
		||||
			}
 | 
			
		||||
			builder.PopArray();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		TeamVersusGameMode::Save(builder);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void Start(uint8 peer, SValue@ save, StartMode sMode) override
 | 
			
		||||
	{
 | 
			
		||||
		if (save !is null)
 | 
			
		||||
			@m_switchedSidesData = GetParamArray(UnitPtr(), save, "teams", false);
 | 
			
		||||
 | 
			
		||||
		TeamVersusGameMode::Start(peer, save, sMode);
 | 
			
		||||
 | 
			
		||||
		m_tmLimit = 0; // infinite time limit as far as VersusGameMode is concerned
 | 
			
		||||
		m_tmLimitCustom = TimeLimit * 1000; // 5 minutes by default
 | 
			
		||||
 | 
			
		||||
		@m_payload = cast<PayloadBehavior>(PayloadUnit.FetchFirst().GetScriptBehavior());
 | 
			
		||||
 | 
			
		||||
		if (m_payload is null)
 | 
			
		||||
			PrintError("PayloadUnit is not a PayloadBehavior!");
 | 
			
		||||
 | 
			
		||||
		UnitPtr unitFirstNode = FirstNode.FetchFirst();
 | 
			
		||||
		if (unitFirstNode.IsValid())
 | 
			
		||||
		{
 | 
			
		||||
			auto node = cast<WorldScript::PayloadNode>(unitFirstNode.GetScriptBehavior());
 | 
			
		||||
			if (node !is null)
 | 
			
		||||
				@m_payload.m_targetNode = node;
 | 
			
		||||
			else
 | 
			
		||||
				PrintError("First target node is not a PayloadNode script!");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			PrintError("First target node was not set!");
 | 
			
		||||
 | 
			
		||||
		WorldScript::PayloadNode@ prevNode;
 | 
			
		||||
 | 
			
		||||
		float totalDistance = 0.0f;
 | 
			
		||||
 | 
			
		||||
		UnitPtr unitNode = unitFirstNode;
 | 
			
		||||
		while (unitNode.IsValid())
 | 
			
		||||
		{
 | 
			
		||||
			auto node = cast<WorldScript::PayloadNode>(unitNode.GetScriptBehavior());
 | 
			
		||||
			if (node is null)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			unitNode = node.NextNode.FetchFirst();
 | 
			
		||||
 | 
			
		||||
			@node.m_prevNode = prevNode;
 | 
			
		||||
			@node.m_nextNode = cast<WorldScript::PayloadNode>(unitNode.GetScriptBehavior());
 | 
			
		||||
 | 
			
		||||
			if (prevNode !is null)
 | 
			
		||||
				totalDistance += dist(prevNode.Position, node.Position);
 | 
			
		||||
 | 
			
		||||
			@prevNode = node;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		float currDistance = 0.0f;
 | 
			
		||||
 | 
			
		||||
		auto distNode = cast<WorldScript::PayloadNode>(unitFirstNode.GetScriptBehavior());
 | 
			
		||||
		while (distNode !is null)
 | 
			
		||||
		{
 | 
			
		||||
			if (distNode.m_prevNode is null)
 | 
			
		||||
				distNode.m_locationFactor = 0.0f;
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				currDistance += dist(distNode.m_prevNode.Position, distNode.Position);
 | 
			
		||||
				distNode.m_locationFactor = currDistance / totalDistance;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			@distNode = distNode.m_nextNode;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_payloadHUD.AddCheckpoints();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void SpawnPlayer(int i, vec2 pos = vec2(), int unitId = 0, uint team = 0) override
 | 
			
		||||
	{
 | 
			
		||||
		TeamVersusGameMode::SpawnPlayer(i, pos, unitId, team);
 | 
			
		||||
 | 
			
		||||
		PayloadPlayerRecord@ record = cast<PayloadPlayerRecord>(g_players[i]);
 | 
			
		||||
		record.HandlePlayerClass();
 | 
			
		||||
 | 
			
		||||
		if (g_players[i].local)
 | 
			
		||||
		{
 | 
			
		||||
			//TODO: This doesn't work well
 | 
			
		||||
			bool localAttackers = (team == HashString("player_1"));
 | 
			
		||||
			for (uint j = 0; j < g_teamForceFields.length(); j++)
 | 
			
		||||
			{
 | 
			
		||||
				bool hasCollision = (localAttackers != g_teamForceFields[j].Attackers);
 | 
			
		||||
 | 
			
		||||
				auto units = g_teamForceFields[j].Units.FetchAll();
 | 
			
		||||
				for (uint k = 0; k < units.length(); k++)
 | 
			
		||||
				{
 | 
			
		||||
					PhysicsBody@ body = units[k].GetPhysicsBody();
 | 
			
		||||
					if (body is null)
 | 
			
		||||
					{
 | 
			
		||||
						PrintError("PhysicsBody for unit " + units[k].GetDebugName() + "is null");
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
					body.SetActive(hasCollision);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								samples/Ballerina/hello-world-service.bal
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								samples/Ballerina/hello-world-service.bal
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
import ballerina.lang.messages;
 | 
			
		||||
import ballerina.net.http;
 | 
			
		||||
import ballerina.doc;
 | 
			
		||||
 | 
			
		||||
@doc:Description {value:"By default Ballerina assumes that the service is to be exposed via HTTP/1.1 using the system default port and that all requests coming to the HTTP server will be delivered to this service."}
 | 
			
		||||
service<http> helloWorld {
 | 
			
		||||
    @doc:Description {value:"All resources are invoked with an argument of type message, the built-in reference type representing a network invocation."}
 | 
			
		||||
    resource sayHello (message m) {
 | 
			
		||||
        // Creates an empty message.
 | 
			
		||||
        message response = {};
 | 
			
		||||
        // A util method that can be used to set string payload.
 | 
			
		||||
        messages:setStringPayload(response, "Hello, World!");
 | 
			
		||||
        // Reply keyword sends the response back to the client.
 | 
			
		||||
        reply response;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								samples/Ballerina/hello-world.bal
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								samples/Ballerina/hello-world.bal
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
import ballerina.lang.system;
 | 
			
		||||
 | 
			
		||||
function main (string[] args) {
 | 
			
		||||
    system:println("Hello, World!");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										31
									
								
								samples/Ballerina/json.bal
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								samples/Ballerina/json.bal
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
import ballerina.lang.system;
 | 
			
		||||
 | 
			
		||||
function main (string[] args) {
 | 
			
		||||
    // JSON string value.
 | 
			
		||||
    json j1 = "Apple";
 | 
			
		||||
    system:println(j1);
 | 
			
		||||
 | 
			
		||||
    // JSON number value.
 | 
			
		||||
    json j2 = 5.36;
 | 
			
		||||
    system:println(j2);
 | 
			
		||||
 | 
			
		||||
    // JSON true value.
 | 
			
		||||
    json j3 = true;
 | 
			
		||||
    system:println(j3);
 | 
			
		||||
 | 
			
		||||
    // JSON false value.
 | 
			
		||||
    json j4 = false;
 | 
			
		||||
    system:println(j4);
 | 
			
		||||
 | 
			
		||||
    // JSON null value.
 | 
			
		||||
    json j5 = null;
 | 
			
		||||
 | 
			
		||||
    //JSON Objects.
 | 
			
		||||
    json j6 = {name:"apple", color:"red", price:j2};
 | 
			
		||||
    system:println(j6);
 | 
			
		||||
 | 
			
		||||
    //JSON Arrays. They are arrays of any JSON value.
 | 
			
		||||
    json j7 = [1, false, null, "foo",
 | 
			
		||||
               {first:"John", last:"Pala"}];
 | 
			
		||||
    system:println(j7);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								samples/Ballerina/var.bal
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								samples/Ballerina/var.bal
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
import ballerina.lang.system;
 | 
			
		||||
 | 
			
		||||
function divideBy10 (int d) (int, int) {
 | 
			
		||||
    return d / 10, d % 10;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function main (string[] args) {
 | 
			
		||||
    //Here the variable type is inferred type from the initial value. This is same as "int k = 5";
 | 
			
		||||
    var k = 5;
 | 
			
		||||
    system:println(10 + k);
 | 
			
		||||
 | 
			
		||||
    //Here the type of the 'strVar' is 'string'.
 | 
			
		||||
    var strVar = "Hello!";
 | 
			
		||||
    system:println(strVar);
 | 
			
		||||
 | 
			
		||||
    //Multiple assignment with 'var' allows you to define the variable then and there.
 | 
			
		||||
    //Variable type is inferred from the right-hand side.
 | 
			
		||||
    var q, r = divideBy10(6);
 | 
			
		||||
    system:println("06/10: " + "quotient=" + q + " " +
 | 
			
		||||
                   "remainder=" + r);
 | 
			
		||||
 | 
			
		||||
    //To ignore a particular return value in a multiple assignment statement, use '_'.
 | 
			
		||||
    var q1, _ = divideBy10(57);
 | 
			
		||||
    system:println("57/10: " + "quotient=" + q1);
 | 
			
		||||
 | 
			
		||||
    var _, r1 = divideBy10(9);
 | 
			
		||||
    system:println("09/10: " + "remainder=" + r1);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								samples/Ballerina/xml.bal
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								samples/Ballerina/xml.bal
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
import ballerina.lang.system;
 | 
			
		||||
 | 
			
		||||
function main (string[] args) {
 | 
			
		||||
 | 
			
		||||
	// XML element. Can only have one root element.
 | 
			
		||||
    xml x1 = xml `<book>The Lost World</book>`;
 | 
			
		||||
    system:println(x1);
 | 
			
		||||
 | 
			
		||||
    // XML text
 | 
			
		||||
    xml x2 = xml `Hello, world!`;
 | 
			
		||||
    system:println(x2);
 | 
			
		||||
 | 
			
		||||
    // XML comment
 | 
			
		||||
    xml x3 = xml `<!--I am a comment-->`;
 | 
			
		||||
    system:println(x3);
 | 
			
		||||
 | 
			
		||||
    // XML processing instruction
 | 
			
		||||
    xml x4 = xml `<?target data?>`;
 | 
			
		||||
    system:println(x4);
 | 
			
		||||
 | 
			
		||||
    // Multiple XML items can be combined to form a sequence of XML. The resulting sequence is again an XML on its own.
 | 
			
		||||
    xml x5 = x1 + x2 + x3 + x4;
 | 
			
		||||
    system:println("\nResulting XML sequence:");
 | 
			
		||||
    system:println(x5);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								samples/Common Workflow Language/trunk-peak-score.cwl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								samples/Common Workflow Language/trunk-peak-score.cwl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
#!/usr/bin/env cwl-runner
 | 
			
		||||
# Originally from
 | 
			
		||||
# https://github.com/Duke-GCB/GGR-cwl/blob/54e897263a702ff1074c8ac814b4bf7205d140dd/utils/trunk-peak-score.cwl
 | 
			
		||||
# Released under the MIT License:
 | 
			
		||||
# https://github.com/Duke-GCB/GGR-cwl/blob/54e897263a702ff1074c8ac814b4bf7205d140dd/LICENSE
 | 
			
		||||
# Converted to CWL v1.0 syntax using
 | 
			
		||||
# https://github.com/common-workflow-language/cwl-upgrader
 | 
			
		||||
# and polished by Michael R. Crusoe <mrc@commonwl.org>
 | 
			
		||||
# All modifications also released under the MIT License
 | 
			
		||||
cwlVersion: v1.0
 | 
			
		||||
class: CommandLineTool
 | 
			
		||||
doc: Trunk scores in ENCODE bed6+4 files
 | 
			
		||||
 | 
			
		||||
hints:
 | 
			
		||||
  DockerRequirement:
 | 
			
		||||
    dockerPull: dukegcb/workflow-utils
 | 
			
		||||
 | 
			
		||||
inputs:
 | 
			
		||||
  peaks:
 | 
			
		||||
    type: File
 | 
			
		||||
  sep:
 | 
			
		||||
    type: string
 | 
			
		||||
    default: \t
 | 
			
		||||
 | 
			
		||||
outputs:
 | 
			
		||||
  trunked_scores_peaks:
 | 
			
		||||
    type: stdout
 | 
			
		||||
 | 
			
		||||
baseCommand: awk
 | 
			
		||||
 | 
			
		||||
arguments:
 | 
			
		||||
- -F $(inputs.sep)
 | 
			
		||||
- BEGIN{OFS=FS}$5>1000{$5=1000}{print}
 | 
			
		||||
- $(inputs.peaks.path)
 | 
			
		||||
 | 
			
		||||
stdout: $(inputs.peaks.nameroot).trunked_scores$(inputs.peaks.nameext)
 | 
			
		||||
							
								
								
									
										12
									
								
								samples/DataWeave/customInterpolator.dwl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								samples/DataWeave/customInterpolator.dwl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
fun SQL(literals, parts) = ''
 | 
			
		||||
---
 | 
			
		||||
[
 | 
			
		||||
  SQL `SELECT * FROM table WHERE id = $(1) AND name = $('a')`,
 | 
			
		||||
  SQL `$('p')`,
 | 
			
		||||
  SQL `$('a')$('b')`,
 | 
			
		||||
  SQL `$('a')---$('b')`,
 | 
			
		||||
  SQL `---$('a')---$('b')---`,
 | 
			
		||||
  SQL `$('p')bbb`,
 | 
			
		||||
  SQL `aaa$('p')`,
 | 
			
		||||
  SQL `aaa$('p')bbb`
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										9
									
								
								samples/DataWeave/directives.dwl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								samples/DataWeave/directives.dwl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
%dw 2.0
 | 
			
		||||
var number = 1234
 | 
			
		||||
fun foo(func,name="Mariano") = func(name)
 | 
			
		||||
input payload application/test arg="value"
 | 
			
		||||
output application/json
 | 
			
		||||
---
 | 
			
		||||
{
 | 
			
		||||
  foo: "bar"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								samples/DataWeave/functions.dwl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								samples/DataWeave/functions.dwl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
%dw 2.0
 | 
			
		||||
var x=(param1, param2) -> { "$param1": param2 }
 | 
			
		||||
var y=(param1, param2 = "c") -> { "$param1": param2 }
 | 
			
		||||
var toUser = (user) -> { name: user.name,	lastName: user.lastName }
 | 
			
		||||
fun z(param1, param2) = { "$param1": param2 }
 | 
			
		||||
var a = { name: "Mariano" , toUser: ((param1, param2) -> { "$param1": param2 }) }
 | 
			
		||||
var applyFirst =  (array, func) -> (func(array[0]) ++  array[1 to -1])
 | 
			
		||||
 | 
			
		||||
var nested =  (array, func) -> (a) -> (b) -> (c) -> array map func(a ++ b ++ c)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fun f2(a1, a2) = ""
 | 
			
		||||
fun f3(a1:String, a2:Number):String = a1
 | 
			
		||||
fun f4(a1:String, a2:(a:Number) -> Number):String = a1
 | 
			
		||||
---
 | 
			
		||||
result: {
 | 
			
		||||
  a: x("a", "b"),
 | 
			
		||||
  b: y("a"),
 | 
			
		||||
  c: y("a", "b"),
 | 
			
		||||
  users: { (in1 map ((user) -> { user: (toUser(user) ++ user) })) },
 | 
			
		||||
  d: z("a", "b"),
 | 
			
		||||
  e: a.toUser("name","Mariano"),
 | 
			
		||||
  f: a.toUser("name","Mariano").name,
 | 
			
		||||
  f: applyFirst("mariano", (s) -> upper(s) ),
 | 
			
		||||
  g: [] map (s) -> upper(s),
 | 
			
		||||
  h: 1 f2 2
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								samples/DataWeave/literals.dwl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								samples/DataWeave/literals.dwl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
%dw 2.0
 | 
			
		||||
---
 | 
			
		||||
{
 | 
			
		||||
  "boolean":{
 | 
			
		||||
    "true" : true,
 | 
			
		||||
    "false": false
 | 
			
		||||
  },
 | 
			
		||||
  "Number": {
 | 
			
		||||
    "int": 123,
 | 
			
		||||
    "decimal": 123.23
 | 
			
		||||
  },
 | 
			
		||||
  "string": {
 | 
			
		||||
    "singleQuote" : 'A String',
 | 
			
		||||
    "doubleQuote" : "A String"
 | 
			
		||||
  },
 | 
			
		||||
  "regex": /foo/,
 | 
			
		||||
  "date": {
 | 
			
		||||
    a: |2003-10-01|,
 | 
			
		||||
    b: |2005-045|,
 | 
			
		||||
    c: |2003-W14-3|,
 | 
			
		||||
    d: |23:57:59|,
 | 
			
		||||
    e: |23:57:30.700|,
 | 
			
		||||
    f: |23:50:30Z|,
 | 
			
		||||
    g: |+13:00|,
 | 
			
		||||
    h: |Z|,
 | 
			
		||||
    i: |-02:00|,
 | 
			
		||||
    j: |2005-06-02T15:10:16|,
 | 
			
		||||
    k: |2005-06-02T15:10:16Z|,
 | 
			
		||||
    l: |2005-06-02T15:10:16+03:00|,
 | 
			
		||||
    m: |P12Y7M11D|,
 | 
			
		||||
    n: |P12Y5M|,
 | 
			
		||||
    o: |P45DT9H20M8S|,
 | 
			
		||||
    p: |PT9H20M8S|
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								samples/DataWeave/match.dwl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								samples/DataWeave/match.dwl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
{
 | 
			
		||||
  // Regex Pattern Matching (Can be named or unnamed)
 | 
			
		||||
  a: in0.phones map $ match {
 | 
			
		||||
    case matches /\+(\d+)\s\((\d+)\)\s(\d+\-\d+)/ -> { country: $[0], area: $[1], number: $[2] }
 | 
			
		||||
    case matches /\((\d+)\)\s(\d+\-\d+)/ -> { area: $[1], number: $[2] }
 | 
			
		||||
    case phone matches /\((\d+)\)\s(\d+\-\d+)/ -> { area: phone[1], number: phone[2] }
 | 
			
		||||
  },
 | 
			
		||||
  // Type Pattern Matching (Can be named or unnamed)
 | 
			
		||||
  b: in0.object match {
 | 
			
		||||
    case is Object -> { object: $ }
 | 
			
		||||
    case is Number -> { number: $ }
 | 
			
		||||
    // This is how you name variables if needed
 | 
			
		||||
    case y is Boolean -> { boolean: y }
 | 
			
		||||
  },
 | 
			
		||||
  // Literal Pattern Matching (Can be named or unnamed)
 | 
			
		||||
  c: in0.value match {
 | 
			
		||||
    case "Emiliano" -> { string: $ }
 | 
			
		||||
    case 123 -> { number: $ }
 | 
			
		||||
    // This is how you name variables if needed
 | 
			
		||||
    case value: "Mariano" -> { name: value }
 | 
			
		||||
  },
 | 
			
		||||
  // Boolean Expression Pattern Matching (Always named)
 | 
			
		||||
  d: in0.value match {
 | 
			
		||||
    case x if x > 30 -> { biggerThan30: x }
 | 
			
		||||
    case x if x == 9 -> { nine: x }
 | 
			
		||||
  },
 | 
			
		||||
  // Default matches
 | 
			
		||||
  e: in0.value match {
 | 
			
		||||
    case "Emiliano" -> "string"
 | 
			
		||||
    case 3.14 -> number
 | 
			
		||||
    else -> "1234"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2061
									
								
								samples/Edje Data Collection/mild.edc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2061
									
								
								samples/Edje Data Collection/mild.edc
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										227
									
								
								samples/INI/filenames/buildozer.spec
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								samples/INI/filenames/buildozer.spec
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,227 @@
 | 
			
		||||
[app]
 | 
			
		||||
 | 
			
		||||
# (str) Title of your application
 | 
			
		||||
title = Kivy Kazam
 | 
			
		||||
 | 
			
		||||
# (str) Package name
 | 
			
		||||
package.name = kivykazam
 | 
			
		||||
 | 
			
		||||
# (str) Package domain (needed for android/ios packaging)
 | 
			
		||||
package.domain = org.test
 | 
			
		||||
 | 
			
		||||
# (str) Source code where the main.py live
 | 
			
		||||
source.dir = .
 | 
			
		||||
 | 
			
		||||
# (list) Source files to include (let empty to include all the files)
 | 
			
		||||
source.include_exts = py,png,jpg,kv,atlas
 | 
			
		||||
 | 
			
		||||
# (list) List of inclusions using pattern matching
 | 
			
		||||
#source.include_patterns = assets/*,images/*.png
 | 
			
		||||
 | 
			
		||||
# (list) Source files to exclude (let empty to not exclude anything)
 | 
			
		||||
#source.exclude_exts = spec
 | 
			
		||||
 | 
			
		||||
# (list) List of directory to exclude (let empty to not exclude anything)
 | 
			
		||||
#source.exclude_dirs = tests, bin
 | 
			
		||||
 | 
			
		||||
# (list) List of exclusions using pattern matching
 | 
			
		||||
#source.exclude_patterns = license,images/*/*.jpg
 | 
			
		||||
 | 
			
		||||
# (str) Application versioning (method 1)
 | 
			
		||||
version = 0.1
 | 
			
		||||
 | 
			
		||||
# (str) Application versioning (method 2)
 | 
			
		||||
# version.regex = __version__ = ['"](.*)['"]
 | 
			
		||||
# version.filename = %(source.dir)s/main.py
 | 
			
		||||
 | 
			
		||||
# (list) Application requirements
 | 
			
		||||
# comma seperated e.g. requirements = sqlite3,kivy
 | 
			
		||||
requirements = kivy
 | 
			
		||||
 | 
			
		||||
# (str) Custom source folders for requirements
 | 
			
		||||
# Sets custom source for any requirements with recipes
 | 
			
		||||
# requirements.source.kivy = ../../kivy
 | 
			
		||||
 | 
			
		||||
# (list) Garden requirements
 | 
			
		||||
#garden_requirements =
 | 
			
		||||
 | 
			
		||||
# (str) Presplash of the application
 | 
			
		||||
#presplash.filename = %(source.dir)s/data/presplash.png
 | 
			
		||||
 | 
			
		||||
# (str) Icon of the application
 | 
			
		||||
#icon.filename = %(source.dir)s/data/icon.png
 | 
			
		||||
 | 
			
		||||
# (str) Supported orientation (one of landscape, portrait or all)
 | 
			
		||||
orientation = all
 | 
			
		||||
 | 
			
		||||
# (list) List of service to declare
 | 
			
		||||
#services = NAME:ENTRYPOINT_TO_PY,NAME2:ENTRYPOINT2_TO_PY
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# OSX Specific
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# author = © Copyright Info
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Android specific
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# (bool) Indicate if the application should be fullscreen or not
 | 
			
		||||
fullscreen = 1
 | 
			
		||||
 | 
			
		||||
# (list) Permissions
 | 
			
		||||
#android.permissions = INTERNET
 | 
			
		||||
 | 
			
		||||
# (int) Android API to use
 | 
			
		||||
#android.api = 19
 | 
			
		||||
 | 
			
		||||
# (int) Minimum API required
 | 
			
		||||
android.minapi = 13
 | 
			
		||||
 | 
			
		||||
# (int) Android SDK version to use
 | 
			
		||||
#android.sdk = 20
 | 
			
		||||
 | 
			
		||||
# (str) Android NDK version to use
 | 
			
		||||
#android.ndk = 9c
 | 
			
		||||
 | 
			
		||||
# (bool) Use --private data storage (True) or --dir public storage (False)
 | 
			
		||||
#android.private_storage = True
 | 
			
		||||
 | 
			
		||||
# (str) Android NDK directory (if empty, it will be automatically downloaded.)
 | 
			
		||||
#android.ndk_path =
 | 
			
		||||
 | 
			
		||||
# (str) Android SDK directory (if empty, it will be automatically downloaded.)
 | 
			
		||||
#android.sdk_path =
 | 
			
		||||
 | 
			
		||||
# (str) ANT directory (if empty, it will be automatically downloaded.)
 | 
			
		||||
#android.ant_path =
 | 
			
		||||
 | 
			
		||||
# (str) python-for-android git clone directory (if empty, it will be automatically cloned from github)
 | 
			
		||||
#android.p4a_dir =
 | 
			
		||||
 | 
			
		||||
# (list) python-for-android whitelist
 | 
			
		||||
#android.p4a_whitelist =
 | 
			
		||||
 | 
			
		||||
# (bool) If True, then skip trying to update the Android sdk
 | 
			
		||||
# This can be useful to avoid excess Internet downloads or save time
 | 
			
		||||
# when an update is due and you just want to test/build your package
 | 
			
		||||
# android.skip_update = False
 | 
			
		||||
 | 
			
		||||
# (str) Android entry point, default is ok for Kivy-based app
 | 
			
		||||
#android.entrypoint = org.renpy.android.PythonActivity
 | 
			
		||||
 | 
			
		||||
# (list) List of Java .jar files to add to the libs so that pyjnius can access
 | 
			
		||||
# their classes. Don't add jars that you do not need, since extra jars can slow
 | 
			
		||||
# down the build process. Allows wildcards matching, for example:
 | 
			
		||||
# OUYA-ODK/libs/*.jar
 | 
			
		||||
#android.add_jars = foo.jar,bar.jar,path/to/more/*.jar
 | 
			
		||||
 | 
			
		||||
# (list) List of Java files to add to the android project (can be java or a
 | 
			
		||||
# directory containing the files)
 | 
			
		||||
#android.add_src =
 | 
			
		||||
 | 
			
		||||
# (str) python-for-android branch to use, if not master, useful to try
 | 
			
		||||
# not yet merged features.
 | 
			
		||||
#android.branch = master
 | 
			
		||||
 | 
			
		||||
# (str) OUYA Console category. Should be one of GAME or APP
 | 
			
		||||
# If you leave this blank, OUYA support will not be enabled
 | 
			
		||||
#android.ouya.category = GAME
 | 
			
		||||
 | 
			
		||||
# (str) Filename of OUYA Console icon. It must be a 732x412 png image.
 | 
			
		||||
#android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png
 | 
			
		||||
 | 
			
		||||
# (str) XML file to include as an intent filters in <activity> tag
 | 
			
		||||
#android.manifest.intent_filters =
 | 
			
		||||
 | 
			
		||||
# (list) Android additionnal libraries to copy into libs/armeabi
 | 
			
		||||
#android.add_libs_armeabi = libs/android/*.so
 | 
			
		||||
#android.add_libs_armeabi_v7a = libs/android-v7/*.so
 | 
			
		||||
#android.add_libs_x86 = libs/android-x86/*.so
 | 
			
		||||
#android.add_libs_mips = libs/android-mips/*.so
 | 
			
		||||
 | 
			
		||||
# (bool) Indicate whether the screen should stay on
 | 
			
		||||
# Don't forget to add the WAKE_LOCK permission if you set this to True
 | 
			
		||||
#android.wakelock = False
 | 
			
		||||
 | 
			
		||||
# (list) Android application meta-data to set (key=value format)
 | 
			
		||||
#android.meta_data =
 | 
			
		||||
 | 
			
		||||
# (list) Android library project to add (will be added in the
 | 
			
		||||
# project.properties automatically.)
 | 
			
		||||
#android.library_references =
 | 
			
		||||
 | 
			
		||||
# (str) Android logcat filters to use
 | 
			
		||||
#android.logcat_filters = *:S python:D
 | 
			
		||||
 | 
			
		||||
# (bool) Copy library instead of making a libpymodules.so
 | 
			
		||||
#android.copy_libs = 1
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# iOS specific
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# (str) Path to a custom kivy-ios folder
 | 
			
		||||
#ios.kivy_ios_dir = ../kivy-ios
 | 
			
		||||
 | 
			
		||||
# (str) Name of the certificate to use for signing the debug version
 | 
			
		||||
# Get a list of available identities: buildozer ios list_identities
 | 
			
		||||
#ios.codesign.debug = "iPhone Developer: <lastname> <firstname> (<hexstring>)"
 | 
			
		||||
 | 
			
		||||
# (str) Name of the certificate to use for signing the release version
 | 
			
		||||
#ios.codesign.release = %(ios.codesign.debug)s
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[buildozer]
 | 
			
		||||
 | 
			
		||||
# (int) Log level (0 = error only, 1 = info, 2 = debug (with command output))
 | 
			
		||||
log_level = 1
 | 
			
		||||
 | 
			
		||||
# (int) Display warning if buildozer is run as root (0 = False, 1 = True)
 | 
			
		||||
warn_on_root = 1
 | 
			
		||||
 | 
			
		||||
# (str) Path to build artifact storage, absolute or relative to spec file
 | 
			
		||||
# build_dir = ./.buildozer
 | 
			
		||||
 | 
			
		||||
# (str) Path to build output (i.e. .apk, .ipa) storage
 | 
			
		||||
# bin_dir = ./bin
 | 
			
		||||
 | 
			
		||||
#    -----------------------------------------------------------------------------
 | 
			
		||||
#    List as sections
 | 
			
		||||
#
 | 
			
		||||
#    You can define all the "list" as [section:key].
 | 
			
		||||
#    Each line will be considered as a option to the list.
 | 
			
		||||
#    Let's take [app] / source.exclude_patterns.
 | 
			
		||||
#    Instead of doing:
 | 
			
		||||
#
 | 
			
		||||
#[app]
 | 
			
		||||
#source.exclude_patterns = license,data/audio/*.wav,data/images/original/*
 | 
			
		||||
#
 | 
			
		||||
#    This can be translated into:
 | 
			
		||||
#
 | 
			
		||||
#[app:source.exclude_patterns]
 | 
			
		||||
#license
 | 
			
		||||
#data/audio/*.wav
 | 
			
		||||
#data/images/original/*
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#    -----------------------------------------------------------------------------
 | 
			
		||||
#    Profiles
 | 
			
		||||
#
 | 
			
		||||
#    You can extend section / key with a profile
 | 
			
		||||
#    For example, you want to deploy a demo version of your application without
 | 
			
		||||
#    HD content. You could first change the title to add "(demo)" in the name
 | 
			
		||||
#    and extend the excluded directories to remove the HD content.
 | 
			
		||||
#
 | 
			
		||||
#[app@demo]
 | 
			
		||||
#title = My Application (demo)
 | 
			
		||||
#
 | 
			
		||||
#[app:source.exclude_patterns@demo]
 | 
			
		||||
#images/hd/*
 | 
			
		||||
#
 | 
			
		||||
#    Then, invoke the command line with the "demo" profile:
 | 
			
		||||
#
 | 
			
		||||
#buildozer --profile demo android debug
 | 
			
		||||
							
								
								
									
										955
									
								
								samples/JavaScript/constant_fold.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										955
									
								
								samples/JavaScript/constant_fold.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,955 @@
 | 
			
		||||
// consumes <stdin> and performs constant folding
 | 
			
		||||
// echo '"use strict";"_"[0],1+2;' | node constant_fold.js
 | 
			
		||||
import _NodePath from '../NodePath';
 | 
			
		||||
const {NodePath} = _NodePath;
 | 
			
		||||
import _WalkCombinator from '../WalkCombinator';
 | 
			
		||||
const {WalkCombinator} = _WalkCombinator;
 | 
			
		||||
 | 
			
		||||
const $CONSTEXPR = Symbol.for('$CONSTEXTR');
 | 
			
		||||
const $CONSTVALUE = Symbol.for('$CONSTVALUE');
 | 
			
		||||
const IS_EMPTY = path => {
 | 
			
		||||
  return (path.node.type === 'BlockStatement' && path.node.body.length === 0) ||
 | 
			
		||||
    path.node.type === 'EmptyStatement';
 | 
			
		||||
};
 | 
			
		||||
const IN_PRAGMA_POS = path => {
 | 
			
		||||
  if (path.parent && Array.isArray(path.parent.node)) {
 | 
			
		||||
    const siblings = path.parent.node;
 | 
			
		||||
    for (let i = 0; i < path.key; i++) {
 | 
			
		||||
      // preceded by non-pragma
 | 
			
		||||
      if (
 | 
			
		||||
        siblings[i].type !== 'ExpressionStatement' ||
 | 
			
		||||
        !IS_CONSTEXPR(siblings[i].expression) ||
 | 
			
		||||
        typeof CONSTVALUE(siblings[i].expression) !== 'string'
 | 
			
		||||
      ) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
};
 | 
			
		||||
const IS_PRAGMA = path => {
 | 
			
		||||
  if (path.parent && Array.isArray(path.parent.node)) {
 | 
			
		||||
    const siblings = path.parent.node;
 | 
			
		||||
    for (let i = 0; i < path.key + 1; i++) {
 | 
			
		||||
      // preceded by non-pragma
 | 
			
		||||
      if (
 | 
			
		||||
        siblings[i].type !== 'ExpressionStatement' ||
 | 
			
		||||
        !IS_CONSTEXPR(siblings[i].expression) ||
 | 
			
		||||
        typeof CONSTVALUE(siblings[i].expression) !== 'string'
 | 
			
		||||
      ) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
};
 | 
			
		||||
// worst case is the completion value
 | 
			
		||||
const IS_NOT_COMPLETION = path => {
 | 
			
		||||
  while (true) {
 | 
			
		||||
    if (!path.parent) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    if (
 | 
			
		||||
      Array.isArray(path.parent.node) &&
 | 
			
		||||
      path.key !== path.parent.node.length - 1
 | 
			
		||||
    ) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    path = path.parent;
 | 
			
		||||
    while (Array.isArray(path.node)) {
 | 
			
		||||
      path = path.parent;
 | 
			
		||||
    }
 | 
			
		||||
    if (/Function/.test(path.node.type)) {
 | 
			
		||||
      return true;
 | 
			
		||||
    } else if (path.node.type === 'Program') {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
const REMOVE_IF_EMPTY = path => {
 | 
			
		||||
  if (IS_EMPTY(path)) REMOVE(path);
 | 
			
		||||
  return null;
 | 
			
		||||
};
 | 
			
		||||
const REPLACE_IF_EMPTY = (path, folded) => {
 | 
			
		||||
  if (IS_EMPTY(path)) return REPLACE(path, folded);
 | 
			
		||||
  return path;
 | 
			
		||||
};
 | 
			
		||||
const REMOVE = path => {
 | 
			
		||||
  if (Array.isArray(path.parent.node)) {
 | 
			
		||||
    path.parent.node.splice(path.key, 1);
 | 
			
		||||
  } else {
 | 
			
		||||
    path.parent.node[path.key] = null;
 | 
			
		||||
  }
 | 
			
		||||
  return null;
 | 
			
		||||
};
 | 
			
		||||
const REPLACE = (path, folded) => {
 | 
			
		||||
  const replacement = new NodePath(path.parent, folded, path.key);
 | 
			
		||||
  path.parent.node[path.key] = folded;
 | 
			
		||||
  return replacement;
 | 
			
		||||
};
 | 
			
		||||
// no mutation, this is an atomic value
 | 
			
		||||
const NEG_ZERO = Object.freeze({
 | 
			
		||||
  [$CONSTEXPR]: true,
 | 
			
		||||
  type: 'UnaryExpression',
 | 
			
		||||
  operator: '-',
 | 
			
		||||
  argument: Object.freeze({
 | 
			
		||||
    [$CONSTEXPR]: true,
 | 
			
		||||
    type: 'Literal',
 | 
			
		||||
    value: 0,
 | 
			
		||||
  }),
 | 
			
		||||
});
 | 
			
		||||
const INFINITY = Object.freeze({
 | 
			
		||||
  [$CONSTEXPR]: true,
 | 
			
		||||
  type: 'BinaryExpression',
 | 
			
		||||
  operator: '/',
 | 
			
		||||
  left: Object.freeze({
 | 
			
		||||
    [$CONSTEXPR]: true,
 | 
			
		||||
    type: 'Literal',
 | 
			
		||||
    value: 1,
 | 
			
		||||
  }),
 | 
			
		||||
  right: Object.freeze({
 | 
			
		||||
    [$CONSTEXPR]: true,
 | 
			
		||||
    type: 'Literal',
 | 
			
		||||
    value: 0,
 | 
			
		||||
  }),
 | 
			
		||||
});
 | 
			
		||||
const NEG_INFINITY = Object.freeze({
 | 
			
		||||
  [$CONSTEXPR]: true,
 | 
			
		||||
  type: 'BinaryExpression',
 | 
			
		||||
  operator: '/',
 | 
			
		||||
  left: Object.freeze({
 | 
			
		||||
    [$CONSTEXPR]: true,
 | 
			
		||||
    type: 'Literal',
 | 
			
		||||
    value: 1,
 | 
			
		||||
  }),
 | 
			
		||||
  right: NEG_ZERO,
 | 
			
		||||
});
 | 
			
		||||
const EMPTY = Object.freeze({
 | 
			
		||||
  [$CONSTEXPR]: true,
 | 
			
		||||
  type: 'EmptyStatement',
 | 
			
		||||
});
 | 
			
		||||
const NULL = Object.freeze({
 | 
			
		||||
  [$CONSTEXPR]: true,
 | 
			
		||||
  type: 'Literal',
 | 
			
		||||
  value: null,
 | 
			
		||||
});
 | 
			
		||||
const NAN = Object.freeze({
 | 
			
		||||
  [$CONSTEXPR]: true,
 | 
			
		||||
  type: 'BinaryExpression',
 | 
			
		||||
  operator: '/',
 | 
			
		||||
  left: Object.freeze({
 | 
			
		||||
    [$CONSTEXPR]: true,
 | 
			
		||||
    type: 'Literal',
 | 
			
		||||
    value: 0,
 | 
			
		||||
  }),
 | 
			
		||||
  right: Object.freeze({
 | 
			
		||||
    [$CONSTEXPR]: true,
 | 
			
		||||
    type: 'Literal',
 | 
			
		||||
    value: 0,
 | 
			
		||||
  }),
 | 
			
		||||
});
 | 
			
		||||
const UNDEFINED = Object.freeze({
 | 
			
		||||
  [$CONSTEXPR]: true,
 | 
			
		||||
  type: 'UnaryExpression',
 | 
			
		||||
  operator: 'void',
 | 
			
		||||
  argument: Object.freeze({
 | 
			
		||||
    [$CONSTEXPR]: true,
 | 
			
		||||
    type: 'Literal',
 | 
			
		||||
    value: 0,
 | 
			
		||||
  }),
 | 
			
		||||
});
 | 
			
		||||
// ESTree doesn't like negative numeric literals
 | 
			
		||||
// this also preserves -0
 | 
			
		||||
const IS_UNARY_NEGATIVE = node => {
 | 
			
		||||
  if (
 | 
			
		||||
    node.type === 'UnaryExpression' &&
 | 
			
		||||
    node.operator === '-' &&
 | 
			
		||||
    typeof node.argument.value === 'number' &&
 | 
			
		||||
    node.argument.value === node.argument.value &&
 | 
			
		||||
    node.argument.type === 'Literal'
 | 
			
		||||
  ) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
};
 | 
			
		||||
const IS_CONSTEXPR = node => {
 | 
			
		||||
  if (typeof node !== 'object' || node === null) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  // DONT CALCULATE THINGS MULTIPLE TIMES!!@!@#
 | 
			
		||||
  if (node[$CONSTEXPR]) return true;
 | 
			
		||||
  if (node.type === 'ArrayExpression') {
 | 
			
		||||
    for (let i = 0; i < node.elements.length; i++) {
 | 
			
		||||
      const element = node.elements[i];
 | 
			
		||||
      // hole == null
 | 
			
		||||
      if (element !== null && !IS_CONSTEXPR(element)) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  if (node.type === 'ObjectExpression') {
 | 
			
		||||
    for (let i = 0; i < node.properties.length; i++) {
 | 
			
		||||
      const element = node.properties[i];
 | 
			
		||||
      if (element.kind !== 'init') return false;
 | 
			
		||||
      if (element.method) return false;
 | 
			
		||||
      let key;
 | 
			
		||||
      if (element.computed) {
 | 
			
		||||
        // be sure {["y"]:1} works
 | 
			
		||||
        if (!IS_CONSTEXPR(element.key)) {
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (!IS_CONSTEXPR(element.value)) return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  if (node.type === 'Literal' || IS_UNDEFINED(node) || IS_NAN(node)) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  if (IS_UNARY_NEGATIVE(node)) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
};
 | 
			
		||||
const IS_NAN = node => {
 | 
			
		||||
  return node === NAN;
 | 
			
		||||
};
 | 
			
		||||
const IS_UNDEFINED = node => {
 | 
			
		||||
  return node === UNDEFINED;
 | 
			
		||||
};
 | 
			
		||||
const CONSTVALUE = node => {
 | 
			
		||||
  if (node[$CONSTVALUE]) {
 | 
			
		||||
    return node[$CONSTVALUE];
 | 
			
		||||
  }
 | 
			
		||||
  if (IS_UNDEFINED(node)) return void 0;
 | 
			
		||||
  if (IS_NAN(node)) return +'_';
 | 
			
		||||
  if (!IS_CONSTEXPR(node)) throw new Error('Not a CONSTEXPR');
 | 
			
		||||
  if (node.type === 'ArrayExpression') {
 | 
			
		||||
    let ret = [];
 | 
			
		||||
    ret.length = node.elements.length;
 | 
			
		||||
    for (let i = 0; i < node.elements.length; i++) {
 | 
			
		||||
      if (node.elements[i] !== null) {
 | 
			
		||||
        ret[i] = CONSTVALUE(node.elements[i]);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
  }
 | 
			
		||||
  if (node.type === 'ObjectExpression') {
 | 
			
		||||
    let ret = Object.create(null);
 | 
			
		||||
    for (let i = 0; i < node.properties.length; i++) {
 | 
			
		||||
      const element = node.properties[i];
 | 
			
		||||
      let key;
 | 
			
		||||
      if (element.computed) {
 | 
			
		||||
        key = `${CONSTVALUE(element.key)}`;
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        key = element.key.name;
 | 
			
		||||
      }
 | 
			
		||||
      Object.defineProperty(ret, key, {
 | 
			
		||||
        // duplicate keys...
 | 
			
		||||
        configurable: true,
 | 
			
		||||
        writable: true,
 | 
			
		||||
        value: CONSTVALUE(element.value),
 | 
			
		||||
        enumerable: true
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    Object.freeze(ret);
 | 
			
		||||
    return ret;
 | 
			
		||||
  }
 | 
			
		||||
  if (IS_UNARY_NEGATIVE(node)) {
 | 
			
		||||
    return -node.argument.value;
 | 
			
		||||
  }
 | 
			
		||||
  if (node.regex !== void 0) {
 | 
			
		||||
    return new RegExp(node.regex.pattern, node.regex.flags);
 | 
			
		||||
  }
 | 
			
		||||
  return node.value;
 | 
			
		||||
};
 | 
			
		||||
const CONSTEXPRS = new Map();
 | 
			
		||||
CONSTEXPRS.set(void 0, UNDEFINED);
 | 
			
		||||
CONSTEXPRS.set(+'_', NAN);
 | 
			
		||||
CONSTEXPRS.set(null, NULL);
 | 
			
		||||
const TO_CONSTEXPR = value => {
 | 
			
		||||
  if (value === -Infinity) {
 | 
			
		||||
    return NEG_INFINITY;
 | 
			
		||||
  }
 | 
			
		||||
  if (value === Infinity) {
 | 
			
		||||
    return INFINITY;
 | 
			
		||||
  }
 | 
			
		||||
  let is_neg_zero = 1 / value === -Infinity;
 | 
			
		||||
  if (is_neg_zero) return NEG_ZERO;
 | 
			
		||||
  if (CONSTEXPRS.has(value)) {
 | 
			
		||||
    return CONSTEXPRS.get(value);
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof value === 'number') {
 | 
			
		||||
    if (value < 0) {
 | 
			
		||||
      const CONSTEXPR = Object.freeze({
 | 
			
		||||
        [$CONSTEXPR]: true,
 | 
			
		||||
        [$CONSTVALUE]: value,
 | 
			
		||||
        type: 'UnaryExpression',
 | 
			
		||||
        operator: '-',
 | 
			
		||||
        argument: Object.freeze({ type: 'Literal', value: -value }),
 | 
			
		||||
      });
 | 
			
		||||
      CONSTEXPRS.set(value, CONSTEXPR);
 | 
			
		||||
      return CONSTEXPR;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (
 | 
			
		||||
    value === null ||
 | 
			
		||||
    typeof value === 'number' ||
 | 
			
		||||
    typeof value === 'boolean' ||
 | 
			
		||||
    typeof value === 'string'
 | 
			
		||||
  ) {
 | 
			
		||||
    const CONSTEXPR = Object.freeze({
 | 
			
		||||
      [$CONSTEXPR]: true,
 | 
			
		||||
      [$CONSTVALUE]: value,
 | 
			
		||||
      type: 'Literal',
 | 
			
		||||
      value,
 | 
			
		||||
    });
 | 
			
		||||
    CONSTEXPRS.set(value, CONSTEXPR);
 | 
			
		||||
    return CONSTEXPR;
 | 
			
		||||
  }
 | 
			
		||||
  // have to generate new one every time :-/
 | 
			
		||||
  if (Array.isArray(value)) {
 | 
			
		||||
    return Object.freeze({
 | 
			
		||||
      [$CONSTEXPR]: true,
 | 
			
		||||
      type: 'ArrayExpression',
 | 
			
		||||
      elements: Object.freeze(value.map(TO_CONSTEXPR)),
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof value === 'object' && Object.getPrototypeOf(value) === Object.getPrototypeOf({}) && [...Object.getOwnPropertySymbols(value)].length === 0) {
 | 
			
		||||
    return Object.freeze({
 | 
			
		||||
      [$CONSTEXPR]: true,
 | 
			
		||||
      type: 'ObjectExpression',
 | 
			
		||||
      properties: Object.freeze(
 | 
			
		||||
        [...Object.getOwnPropertyKeys(value)].map(key => {
 | 
			
		||||
          if (!('value' in Object.getOwnProperty(value, key))) {
 | 
			
		||||
            throw Error('Not a CONSTVALUE (found a setter or getter?)');
 | 
			
		||||
          }
 | 
			
		||||
          return {
 | 
			
		||||
            type: 'Property',
 | 
			
		||||
            kind: 'init',
 | 
			
		||||
            method: false,
 | 
			
		||||
            shorthand: false,
 | 
			
		||||
            computed: true,
 | 
			
		||||
            key: {
 | 
			
		||||
              type: 'Literal',
 | 
			
		||||
              value: key
 | 
			
		||||
            },
 | 
			
		||||
            value: TO_CONSTEXPR(value[key])
 | 
			
		||||
          }
 | 
			
		||||
        })),
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
  throw Error('Not a CONSTVALUE (did you pass a RegExp?)');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// THIS DOES NOT HANDLE NODE SPECIFIC CASES LIKE IfStatement
 | 
			
		||||
const FOLD_EMPTY = function*(path) {
 | 
			
		||||
  if (
 | 
			
		||||
    path &&
 | 
			
		||||
    path.node &&
 | 
			
		||||
    path.parent &&
 | 
			
		||||
    Array.isArray(path.parent.node) &&
 | 
			
		||||
    IS_EMPTY(path)
 | 
			
		||||
  ) {
 | 
			
		||||
    REMOVE(path);
 | 
			
		||||
    return yield;
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// THIS DOES NOT HANDLE NODE SPECIFIC CASES LIKE IfStatement
 | 
			
		||||
const FOLD_TEMPLATE = function*(path) {
 | 
			
		||||
  if (
 | 
			
		||||
    path &&
 | 
			
		||||
    path.node &&
 | 
			
		||||
    path.type === 'TemplateLiteral'
 | 
			
		||||
  ) {
 | 
			
		||||
    let updated = false;
 | 
			
		||||
    for (let i = 0; i < path.node.exressions.length; i++) {
 | 
			
		||||
      if (IS_CONSTEXPR(path.node.expressions[i])) {
 | 
			
		||||
        //let 
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
const FOLD_EXPR_STMT = function*(path) {
 | 
			
		||||
  // TODO: enforce completion value checking
 | 
			
		||||
  if (path && path.node && path.node.type === 'ExpressionStatement') {
 | 
			
		||||
    // merge all the adjacent expression statements into sequences
 | 
			
		||||
    if (Array.isArray(path.parent.node)) {
 | 
			
		||||
      // could have nodes after it
 | 
			
		||||
      const siblings = path.parent.node;
 | 
			
		||||
      if (!IS_PRAGMA(path)) {
 | 
			
		||||
        if (path.key < siblings.length - 1) {
 | 
			
		||||
          const mergeable = [path.node];
 | 
			
		||||
          for (let needle = path.key + 1; needle < siblings.length; needle++) {
 | 
			
		||||
            if (siblings[needle].type !== 'ExpressionStatement') {
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            mergeable.push(siblings[needle]);
 | 
			
		||||
          }
 | 
			
		||||
          if (mergeable.length > 1) {
 | 
			
		||||
            siblings.splice(path.key, mergeable.length, {
 | 
			
		||||
              type: 'ExpressionStatement',
 | 
			
		||||
              expression: {
 | 
			
		||||
                type: 'SequenceExpression',
 | 
			
		||||
                expressions: mergeable.reduce(
 | 
			
		||||
                  (acc, es) => {
 | 
			
		||||
                    if (es.expression.type == 'SequenceExpression') {
 | 
			
		||||
                      return [...acc, ...es.expression.expressions];
 | 
			
		||||
                    } else {
 | 
			
		||||
                      return [...acc, es.expression];
 | 
			
		||||
                    }
 | 
			
		||||
                  },
 | 
			
		||||
                  []
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
            });
 | 
			
		||||
            return path;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (IS_NOT_COMPLETION(path) && IS_CONSTEXPR(path.node.expression)) {
 | 
			
		||||
      return REPLACE(path, EMPTY);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
const FOLD_WHILE = function*(path) {
 | 
			
		||||
  if (path && path.node) {
 | 
			
		||||
    if (path.node.type === 'DoWhileStatement') {
 | 
			
		||||
      console.error('FOLD_DOWHILE');
 | 
			
		||||
      REPLACE_IF_EMPTY(path.get(['body']), EMPTY);
 | 
			
		||||
    }
 | 
			
		||||
    if (path.node.type === 'WhileStatement') {
 | 
			
		||||
      console.error('FOLD_WHILE');
 | 
			
		||||
      let { test, consequent, alternate } = path.node;
 | 
			
		||||
      if (IS_CONSTEXPR(test)) {
 | 
			
		||||
        test = CONSTVALUE(test);
 | 
			
		||||
        if (!test) {
 | 
			
		||||
          return REPLACE(path, EMPTY);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      REPLACE_IF_EMPTY(path.get(['body']), EMPTY);
 | 
			
		||||
    }
 | 
			
		||||
    if (path.node.type === 'ForStatement') {
 | 
			
		||||
      console.error('FOLD_FOR');
 | 
			
		||||
      REPLACE_IF_EMPTY(path.get(['body']), EMPTY);
 | 
			
		||||
      let { init, test, update } = path.node;
 | 
			
		||||
      let updated = false;
 | 
			
		||||
      if (init && IS_CONSTEXPR(init)) {
 | 
			
		||||
        updated = true;
 | 
			
		||||
        REPLACE(path.get(['init']), null);
 | 
			
		||||
      }
 | 
			
		||||
      if (test && IS_CONSTEXPR(test)) {
 | 
			
		||||
        let current = CONSTVALUE(test);
 | 
			
		||||
        let coerced = Boolean(current);
 | 
			
		||||
        // remove the test if it is always true
 | 
			
		||||
        if (coerced === true) {
 | 
			
		||||
          updated = true;
 | 
			
		||||
          REPLACE(path.get(['test']), null);
 | 
			
		||||
        } else if (coerced !== current) {
 | 
			
		||||
          updated = true;
 | 
			
		||||
          REPLACE(path.get(['test']), TO_CONSTEXPR(coerced));
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (update && IS_CONSTEXPR(update)) {
 | 
			
		||||
        updated = true;
 | 
			
		||||
        REPLACE(path.get(['update']), null);
 | 
			
		||||
      }
 | 
			
		||||
      if (updated) {
 | 
			
		||||
        return path;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
const FOLD_IF = function*(path) {
 | 
			
		||||
  if (path && path.node && path.node.type === 'IfStatement') {
 | 
			
		||||
    let { test, consequent, alternate } = path.node;
 | 
			
		||||
    const is_not_completion = IS_NOT_COMPLETION(path);
 | 
			
		||||
    if (is_not_completion && !alternate) {
 | 
			
		||||
      if (IS_EMPTY(path.get(['consequent']))) {
 | 
			
		||||
        console.error('FOLD_IF_EMPTY_CONSEQUENT');
 | 
			
		||||
        REPLACE(path, {
 | 
			
		||||
          type: 'ExpressionStatement',
 | 
			
		||||
          expression: test,
 | 
			
		||||
        });
 | 
			
		||||
        return path.parent;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (alternate) {
 | 
			
		||||
      if (alternate.type === consequent.type) {
 | 
			
		||||
        if (consequent.type === 'ExpressionStatement') {
 | 
			
		||||
          console.error('FOLD_IF_BOTH_EXPRSTMT');
 | 
			
		||||
          REPLACE(path, {
 | 
			
		||||
          type: 'ExpressionStatement', expression:
 | 
			
		||||
          {
 | 
			
		||||
            type: 'ConditionalExpression',
 | 
			
		||||
            test: test,
 | 
			
		||||
            consequent: consequent.expression,
 | 
			
		||||
            alternate: alternate.expression,
 | 
			
		||||
          }});
 | 
			
		||||
          return path.parent;
 | 
			
		||||
        }
 | 
			
		||||
        else if (consequent.type === 'ReturnStatement' ||
 | 
			
		||||
          consequent.type === 'ThrowStatement') {
 | 
			
		||||
          console.error('FOLD_IF_BOTH_COMPLETIONS');
 | 
			
		||||
          REPLACE(path, {
 | 
			
		||||
          type: 'ExpressionStatement', expression:{
 | 
			
		||||
            type: consequent.type,
 | 
			
		||||
            argument: {
 | 
			
		||||
              type: 'ConditionalExpression',
 | 
			
		||||
              test: test,
 | 
			
		||||
              consequent: consequent.argument,
 | 
			
		||||
              alternate: alternate.argument,
 | 
			
		||||
            }}
 | 
			
		||||
          });
 | 
			
		||||
          return path.parent;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else if (is_not_completion && consequent.type === 'ExpressionStatement') {
 | 
			
		||||
      console.error('FOLD_IF_NON_COMPLETION_TO_&&');
 | 
			
		||||
      REPLACE(path, {
 | 
			
		||||
        type: 'ExpressionStatement',
 | 
			
		||||
        expression: {
 | 
			
		||||
          type: 'BinaryExpression',
 | 
			
		||||
          operator: '&&',
 | 
			
		||||
          left: test,
 | 
			
		||||
          right: consequent.expression,
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      return path.parent;
 | 
			
		||||
    }
 | 
			
		||||
    if (IS_CONSTEXPR(test)) {
 | 
			
		||||
      test = CONSTVALUE(test);
 | 
			
		||||
      if (test) {
 | 
			
		||||
        return REPLACE(path, consequent);
 | 
			
		||||
      }
 | 
			
		||||
      if (alternate) {
 | 
			
		||||
        return REPLACE(path, alternate);
 | 
			
		||||
      }
 | 
			
		||||
      return REPLACE(path, EMPTY);
 | 
			
		||||
    }
 | 
			
		||||
    consequent = path.get(['consequent']);
 | 
			
		||||
    let updated;
 | 
			
		||||
    if (consequent.node !== EMPTY) {
 | 
			
		||||
      REPLACE_IF_EMPTY(consequent, EMPTY);
 | 
			
		||||
      if (consequent.parent.node[consequent.key] === EMPTY) {
 | 
			
		||||
        updated = true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (alternate) {
 | 
			
		||||
      alternate = path.get(['alternate']);
 | 
			
		||||
      REMOVE_IF_EMPTY(alternate);
 | 
			
		||||
      if (path.node.alternate === null) {
 | 
			
		||||
        updated = true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (updated) {
 | 
			
		||||
      return path;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
const FOLD_SEQUENCE = function*(path) {
 | 
			
		||||
  if (path && path.node && path.node.type === 'SequenceExpression') {
 | 
			
		||||
    console.error('FOLD_SEQUENCE');
 | 
			
		||||
    // never delete the last value
 | 
			
		||||
    for (let i = 0; i < path.node.expressions.length - 1; i++) {
 | 
			
		||||
      if (IS_CONSTEXPR(path.node.expressions[i])) {
 | 
			
		||||
        path.node.expressions.splice(i, 1);
 | 
			
		||||
        i--;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (path.node.expressions.length === 1) {
 | 
			
		||||
      return REPLACE(path, path.node.expressions[0]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
const FOLD_LOGICAL = function*(path) {
 | 
			
		||||
  if (path && path.node && path.node.type === 'LogicalExpression') {
 | 
			
		||||
    console.error('FOLD_LOGICAL');
 | 
			
		||||
    let { left, right, operator } = path.node;
 | 
			
		||||
    if (IS_CONSTEXPR(left)) {
 | 
			
		||||
      left = CONSTVALUE(left);
 | 
			
		||||
      if (operator === '||') {
 | 
			
		||||
        if (left) {
 | 
			
		||||
          return REPLACE(path, TO_CONSTEXPR(left));
 | 
			
		||||
        }
 | 
			
		||||
        return REPLACE(path, right);
 | 
			
		||||
      } else if (operator === '&&') {
 | 
			
		||||
        if (!left) {
 | 
			
		||||
          return REPLACE(path, TO_CONSTEXPR(left));
 | 
			
		||||
        }
 | 
			
		||||
        return REPLACE(path, right);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
const FOLD_SWITCH = function*(path) {
 | 
			
		||||
  if (path && path.node && path.node.type === 'SwitchStatement') {
 | 
			
		||||
    let { discriminant, cases } = path.node;
 | 
			
		||||
    // if there are no cases, just become an expression
 | 
			
		||||
    if (cases.length === 0 && IS_NOT_COMPLETION(path)) {
 | 
			
		||||
      return REPLACE(path, {
 | 
			
		||||
        type: 'ExpressionStatement',
 | 
			
		||||
        expression: discriminant
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    // if the discriminant is static
 | 
			
		||||
    //   remove any preceding non-matching static cases
 | 
			
		||||
    //   fold any trailing cases into the matching case
 | 
			
		||||
    if (cases.length > 1 && IS_CONSTEXPR(discriminant)) {
 | 
			
		||||
      const discriminant_value = CONSTVALUE(discriminant);
 | 
			
		||||
      for (var i = 0; i < cases.length; i++) {
 | 
			
		||||
        const test = cases[i].test;
 | 
			
		||||
        if (IS_CONSTEXPR(test)) {
 | 
			
		||||
          let test_value = CONSTVALUE(test);
 | 
			
		||||
          if (discriminant_value === test_value) {
 | 
			
		||||
            let new_consequent = cases[i].consequent;
 | 
			
		||||
            if (i < cases.length - 1) {
 | 
			
		||||
              for (let fallthrough of cases.slice(i+1)) {
 | 
			
		||||
                new_consequent.push(...fallthrough.consequent);
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            cases[i].consequent = new_consequent;
 | 
			
		||||
            REPLACE(path.get(['cases']), [cases[i]]);
 | 
			
		||||
            return path;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          // we had a dynamic case need to bail
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
const FOLD_UNREACHABLE = function*(path) {
 | 
			
		||||
  if (path && path.node && path.parent && Array.isArray(path.parent.node)) {
 | 
			
		||||
    if (path.node.type === 'ReturnStatement' ||
 | 
			
		||||
    path.node.type === 'ContinueStatement' ||
 | 
			
		||||
    path.node.type === 'BreakStatement' ||
 | 
			
		||||
    path.node.type === 'ThrowStatement') {
 | 
			
		||||
      const next_key = path.key + 1;
 | 
			
		||||
      path.parent.node.splice(next_key, path.parent.node.length - next_key);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
}
 | 
			
		||||
const FOLD_CONDITIONAL = function*(path) {
 | 
			
		||||
  if (path && path.node && path.node.type === 'ConditionalExpression') {
 | 
			
		||||
    console.error('FOLD_CONDITIONAL');
 | 
			
		||||
    let { test, consequent, alternate } = path.node;
 | 
			
		||||
    if (IS_CONSTEXPR(test)) {
 | 
			
		||||
      test = CONSTVALUE(test);
 | 
			
		||||
      if (test) {
 | 
			
		||||
        return REPLACE(path, consequent);
 | 
			
		||||
      }
 | 
			
		||||
      return REPLACE(path, alternate);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
const FOLD_BINARY = function*(path) {
 | 
			
		||||
  if (
 | 
			
		||||
    path &&
 | 
			
		||||
    path.node &&
 | 
			
		||||
    path.node.type === 'BinaryExpression' &&
 | 
			
		||||
    !IS_NAN(path.node)
 | 
			
		||||
  ) {
 | 
			
		||||
    console.error('FOLD_BINARY');
 | 
			
		||||
    let { left, right, operator } = path.node;
 | 
			
		||||
    if (operator === '==' || operator === '!=') {
 | 
			
		||||
      let updated = false;
 | 
			
		||||
      if (IS_UNDEFINED(left)) {
 | 
			
		||||
        updated = true;
 | 
			
		||||
        REPLACE(path.get(['left']), NULL);
 | 
			
		||||
      }
 | 
			
		||||
      if (IS_UNDEFINED(right)) {
 | 
			
		||||
        updated = true;
 | 
			
		||||
        REPLACE(path.get(['right']), NULL);
 | 
			
		||||
      }
 | 
			
		||||
      if (updated) {
 | 
			
		||||
        return path;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (path.node !== INFINITY && path.node !== NEG_INFINITY && IS_CONSTEXPR(left) && IS_CONSTEXPR(right)) {
 | 
			
		||||
      left = CONSTVALUE(left);
 | 
			
		||||
      right = CONSTVALUE(right);
 | 
			
		||||
      let value;
 | 
			
		||||
      if ((!left || typeof left !== 'object') && (!right || typeof right !== 'object')) {
 | 
			
		||||
        if (operator === '+') {
 | 
			
		||||
          value = left + right;
 | 
			
		||||
        } else if (operator === '-') {
 | 
			
		||||
          value = left - right;
 | 
			
		||||
        } else if (operator === '*') {
 | 
			
		||||
          value = left * right;
 | 
			
		||||
        } else if (operator === '/') {
 | 
			
		||||
          value = left / right;
 | 
			
		||||
        } else if (operator === '%') {
 | 
			
		||||
          value = left % right;
 | 
			
		||||
        } else if (operator === '==') {
 | 
			
		||||
          value = left == right;
 | 
			
		||||
        } else if (operator === '!=') {
 | 
			
		||||
          value = left != right;
 | 
			
		||||
        } else if (operator === '===') {
 | 
			
		||||
          value = left === right;
 | 
			
		||||
        } else if (operator === '!==') {
 | 
			
		||||
          value = left !== right;
 | 
			
		||||
        } else if (operator === '<') {
 | 
			
		||||
          value = left < right;
 | 
			
		||||
        } else if (operator === '<=') {
 | 
			
		||||
          value = left <= right;
 | 
			
		||||
        } else if (operator === '>') {
 | 
			
		||||
          value = left > right;
 | 
			
		||||
        } else if (operator === '>=') {
 | 
			
		||||
          value = left >= right;
 | 
			
		||||
        } else if (operator === '<<') {
 | 
			
		||||
          value = left << right;
 | 
			
		||||
        } else if (operator === '>>') {
 | 
			
		||||
          value = left >> right;
 | 
			
		||||
        } else if (operator === '>>>') {
 | 
			
		||||
          value = left >>> right;
 | 
			
		||||
        } else if (operator === '|') {
 | 
			
		||||
          value = left | right;
 | 
			
		||||
        } else if (operator === '&') {
 | 
			
		||||
          value = left & right;
 | 
			
		||||
        } else if (operator === '^') {
 | 
			
		||||
          value = left ^ right;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        if (operator === '==') value = false;
 | 
			
		||||
        if (operator === '===') value = false;
 | 
			
		||||
        if (operator === '!=') value = true;
 | 
			
		||||
        if (operator === '!==') value = true;
 | 
			
		||||
        if (operator === 'in' && typeof right === 'object' && right) {
 | 
			
		||||
          value = Boolean(Object.getOwnPropertyDescriptor(right, left));
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (value !== void 0) {
 | 
			
		||||
        if (typeof value === 'string' || typeof value === 'boolean' || value === null) {
 | 
			
		||||
          return REPLACE(path, TO_CONSTEXPR(value));
 | 
			
		||||
        }
 | 
			
		||||
        if (typeof value === 'number') {
 | 
			
		||||
          return REPLACE(path, TO_CONSTEXPR(value));
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
const FOLD_UNARY = function*(path) {
 | 
			
		||||
  if (path && path.node && path.node.type === 'UnaryExpression') {
 | 
			
		||||
    console.error('FOLD_UNARY');
 | 
			
		||||
    if (IS_CONSTEXPR(path.node)) {
 | 
			
		||||
      return yield path;
 | 
			
		||||
    }
 | 
			
		||||
    let { argument, operator } = path.node;
 | 
			
		||||
    if (IS_CONSTEXPR(argument)) {
 | 
			
		||||
      if (operator === 'void') {
 | 
			
		||||
        return REPLACE(path, UNDEFINED);
 | 
			
		||||
      }
 | 
			
		||||
      let value = CONSTVALUE(argument);
 | 
			
		||||
      if (operator === '-') {
 | 
			
		||||
        value = -value;
 | 
			
		||||
      } else if (operator === '+') {
 | 
			
		||||
        value = +value;
 | 
			
		||||
      } else if (operator === '~') {
 | 
			
		||||
        value = ~value;
 | 
			
		||||
      } else if (operator === '!') {
 | 
			
		||||
        value = !value;
 | 
			
		||||
      } else if (operator === 'typeof') {
 | 
			
		||||
        value = typeof value;
 | 
			
		||||
      } else if (operator === 'delete') {
 | 
			
		||||
        value = true;
 | 
			
		||||
      }
 | 
			
		||||
      return REPLACE(path, TO_CONSTEXPR(value));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
const FOLD_EVAL = function*(path) {
 | 
			
		||||
  if (path && path.node && path.node.type === 'CallExpression' &&
 | 
			
		||||
    path.node.callee.type === 'Identifier' && path.node.callee.name === 'eval') {
 | 
			
		||||
    console.error('FOLD_EVAL');
 | 
			
		||||
    if (path.node.arguments.length === 1 && path.node.arguments[0].type === 'Literal') {
 | 
			
		||||
      let result = esprima.parse(`${
 | 
			
		||||
        CONSTVALUE(path.node.arguments[0])
 | 
			
		||||
      }`);
 | 
			
		||||
      if (result.body.length === 1 && result.body[0].type === 'ExpressionStatement') {
 | 
			
		||||
        return REPLACE(path, result.body[0].expression);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
}
 | 
			
		||||
const FOLD_MEMBER = function*(path) {
 | 
			
		||||
  if (path && path.node && path.node.type === 'MemberExpression') {
 | 
			
		||||
    console.error('FOLD_MEMBER');
 | 
			
		||||
    if (path.node.computed && path.node.property.type === 'Literal') {
 | 
			
		||||
      const current = `${CONSTVALUE(path.node.property)}`;
 | 
			
		||||
      if (typeof current === 'string' && /^[$_a-z][$_a-z\d]*$/i.test(current)) {
 | 
			
		||||
        path.node.computed = false;
 | 
			
		||||
        path.node.property = {
 | 
			
		||||
          type: 'Identifier',
 | 
			
		||||
          name: current,
 | 
			
		||||
        };
 | 
			
		||||
        return path;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (IS_CONSTEXPR(path.node.object)) {
 | 
			
		||||
      const value = CONSTVALUE(path.node.object);
 | 
			
		||||
      if (typeof value === 'string' || Array.isArray(value) || (value && typeof value === 'object')) {
 | 
			
		||||
        let key;
 | 
			
		||||
        if (IS_CONSTEXPR(path.node.property)) {
 | 
			
		||||
          key = `${CONSTVALUE(path.node.property)}`;
 | 
			
		||||
        }
 | 
			
		||||
        else if (!path.node.computed) {
 | 
			
		||||
          key = path.node.property.name;
 | 
			
		||||
        }
 | 
			
		||||
        if (key !== void 0) {
 | 
			
		||||
          const desc = Object.getOwnPropertyDescriptor(value, key);
 | 
			
		||||
          if (desc) {
 | 
			
		||||
            const folded = value[key];
 | 
			
		||||
            console.error('FOLDING', JSON.stringify(folded));
 | 
			
		||||
            if (IN_PRAGMA_POS(path) && typeof folded === 'string') {
 | 
			
		||||
              if (value.length > 1) {
 | 
			
		||||
                REPLACE(
 | 
			
		||||
                  path.get(['object']),
 | 
			
		||||
                  TO_CONSTEXPR(value.slice(key, key + 1))
 | 
			
		||||
                );
 | 
			
		||||
                REPLACE(path.get(['property']), TO_CONSTEXPR(0));
 | 
			
		||||
                return path;
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
              return REPLACE(path, TO_CONSTEXPR(value[key]));
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const $MIN = Symbol();
 | 
			
		||||
const MIN_TRUE = Object.freeze({
 | 
			
		||||
  [$MIN]: true,
 | 
			
		||||
  type: 'UnaryExpression',
 | 
			
		||||
  operator: '!',
 | 
			
		||||
  argument: Object.freeze({
 | 
			
		||||
    [$MIN]: true,
 | 
			
		||||
    type: 'Literal',
 | 
			
		||||
    value: 0
 | 
			
		||||
  })
 | 
			
		||||
});
 | 
			
		||||
const MIN_FALSE = Object.freeze({
 | 
			
		||||
  [$MIN]: true,
 | 
			
		||||
  type: 'UnaryExpression',
 | 
			
		||||
  operator: '!',
 | 
			
		||||
  argument: Object.freeze({
 | 
			
		||||
    [$MIN]: true,
 | 
			
		||||
    type: 'Literal',
 | 
			
		||||
    value: 1
 | 
			
		||||
  })
 | 
			
		||||
});
 | 
			
		||||
const MIN_REPLACEMENTS = new Map;
 | 
			
		||||
MIN_REPLACEMENTS.set(true, MIN_TRUE);
 | 
			
		||||
MIN_REPLACEMENTS.set(false, MIN_FALSE);
 | 
			
		||||
const MIN_VALUES = function*(path) {
 | 
			
		||||
  if (path && path.node && !path.node[$MIN] && IS_CONSTEXPR(path.node)) {
 | 
			
		||||
    let value = CONSTVALUE(path.node);
 | 
			
		||||
    if (MIN_REPLACEMENTS.has(value)) {
 | 
			
		||||
      console.error('MIN_VALUE', value)
 | 
			
		||||
      return REPLACE(path, MIN_REPLACEMENTS.get(value));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return yield path;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
import esprima from 'esprima';
 | 
			
		||||
import util from 'util';
 | 
			
		||||
import escodegen from 'escodegen';
 | 
			
		||||
const optimize = (src) => {
 | 
			
		||||
    const ROOT = new NodePath(
 | 
			
		||||
      null,
 | 
			
		||||
      esprima.parse(
 | 
			
		||||
        src,
 | 
			
		||||
        {
 | 
			
		||||
          // loc: true,
 | 
			
		||||
          // source: '<stdin>',
 | 
			
		||||
        }
 | 
			
		||||
      ),
 | 
			
		||||
      null
 | 
			
		||||
    );
 | 
			
		||||
    // all of these are things that could affect completion value positions
 | 
			
		||||
    const walk_expressions = WalkCombinator.pipe(
 | 
			
		||||
      ...[
 | 
			
		||||
        WalkCombinator.DEPTH_FIRST,
 | 
			
		||||
        {
 | 
			
		||||
          // We never work on Arrays
 | 
			
		||||
          *inputs(path) {
 | 
			
		||||
            if (Array.isArray(path)) return;
 | 
			
		||||
            return yield path;
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        { inputs: FOLD_UNREACHABLE },
 | 
			
		||||
        { inputs: FOLD_IF },
 | 
			
		||||
        { inputs: FOLD_SWITCH },
 | 
			
		||||
        { inputs: FOLD_EXPR_STMT },
 | 
			
		||||
        { inputs: FOLD_CONDITIONAL },
 | 
			
		||||
        { inputs: FOLD_LOGICAL },
 | 
			
		||||
        { inputs: FOLD_BINARY },
 | 
			
		||||
        { inputs: FOLD_UNARY },
 | 
			
		||||
        { inputs: FOLD_SEQUENCE },
 | 
			
		||||
        { inputs: FOLD_MEMBER },
 | 
			
		||||
        { inputs: FOLD_EMPTY },
 | 
			
		||||
        { inputs: FOLD_WHILE },
 | 
			
		||||
        { inputs: FOLD_EVAL },
 | 
			
		||||
      ]
 | 
			
		||||
    ).walk(ROOT);
 | 
			
		||||
    for (const _ of walk_expressions) {
 | 
			
		||||
    }
 | 
			
		||||
    const minify = WalkCombinator.pipe(
 | 
			
		||||
      ...[
 | 
			
		||||
        WalkCombinator.DEPTH_FIRST,
 | 
			
		||||
        {
 | 
			
		||||
          // We never work on Arrays
 | 
			
		||||
          *inputs(path) {
 | 
			
		||||
            if (Array.isArray(path)) return;
 | 
			
		||||
            return yield path;
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        { inputs: MIN_VALUES },
 | 
			
		||||
      ]
 | 
			
		||||
    ).walk(ROOT);
 | 
			
		||||
    for (const _ of minify) {
 | 
			
		||||
    }
 | 
			
		||||
    return ROOT;
 | 
			
		||||
}
 | 
			
		||||
import mississippi from 'mississippi';
 | 
			
		||||
process.stdin.pipe(
 | 
			
		||||
  mississippi.concat(buff => {
 | 
			
		||||
    const ROOT = optimize(`${buff}`)
 | 
			
		||||
    console.error(
 | 
			
		||||
      '%s',
 | 
			
		||||
      util.inspect(ROOT.node, {
 | 
			
		||||
        depth: null,
 | 
			
		||||
        colors: true,
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
    const out = escodegen.generate(ROOT.node);
 | 
			
		||||
    console.log(out);
 | 
			
		||||
  })
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										6
									
								
								samples/JavaScript/entry.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								samples/JavaScript/entry.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
import bar from './module.mjs';
 | 
			
		||||
function foo() {
 | 
			
		||||
  return "I am foo";
 | 
			
		||||
}
 | 
			
		||||
export {foo};
 | 
			
		||||
console.log(bar);
 | 
			
		||||
							
								
								
									
										5
									
								
								samples/JavaScript/module.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								samples/JavaScript/module.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
import {foo} from './entry.mjs';
 | 
			
		||||
console.log(foo());
 | 
			
		||||
 | 
			
		||||
const bar = "I am bar.";
 | 
			
		||||
export {bar as default};
 | 
			
		||||
							
								
								
									
										106
									
								
								samples/Nearley/nearley-language-bootstrapped.ne
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								samples/Nearley/nearley-language-bootstrapped.ne
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
			
		||||
# nearley grammar
 | 
			
		||||
@builtin "string.ne"
 | 
			
		||||
 | 
			
		||||
@{%
 | 
			
		||||
 | 
			
		||||
function insensitive(sl) {
 | 
			
		||||
    var s = sl.literal;
 | 
			
		||||
    result = [];
 | 
			
		||||
    for (var i=0; i<s.length; i++) {
 | 
			
		||||
        var c = s.charAt(i);
 | 
			
		||||
        if (c.toUpperCase() !== c || c.toLowerCase() !== c) {
 | 
			
		||||
            result.push(new RegExp("[" + c.toLowerCase() + c.toUpperCase() + "]"));
 | 
			
		||||
        } else {
 | 
			
		||||
            result.push({literal: c});
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return {subexpression: [{tokens: result, postprocess: function(d) {return d.join(""); }}]};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
%}
 | 
			
		||||
 | 
			
		||||
final -> whit? prog whit?  {% function(d) { return d[1]; } %}
 | 
			
		||||
 | 
			
		||||
prog -> prod  {% function(d) { return [d[0]]; } %}
 | 
			
		||||
      | prod whit prog  {% function(d) { return [d[0]].concat(d[2]); } %}
 | 
			
		||||
 | 
			
		||||
prod -> word whit? ("-"|"="):+ ">" whit? expression+  {% function(d) { return {name: d[0], rules: d[5]}; } %}
 | 
			
		||||
      | word "[" wordlist "]" whit? ("-"|"="):+ ">" whit? expression+ {% function(d) {return {macro: d[0], args: d[2], exprs: d[8]}} %}
 | 
			
		||||
      | "@" whit? js  {% function(d) { return {body: d[2]}; } %}
 | 
			
		||||
      | "@" word whit word  {% function(d) { return {config: d[1], value: d[3]}; } %}
 | 
			
		||||
      | "@include"  whit? string {% function(d) {return {include: d[2].literal, builtin: false}} %}
 | 
			
		||||
      | "@builtin"  whit? string {% function(d) {return {include: d[2].literal, builtin: true }} %}
 | 
			
		||||
 | 
			
		||||
expression+ -> completeexpression
 | 
			
		||||
             | expression+ whit? "|" whit? completeexpression  {% function(d) { return d[0].concat([d[4]]); } %}
 | 
			
		||||
 | 
			
		||||
expressionlist -> completeexpression
 | 
			
		||||
             | expressionlist whit? "," whit? completeexpression {% function(d) { return d[0].concat([d[4]]); } %}
 | 
			
		||||
 | 
			
		||||
wordlist -> word
 | 
			
		||||
            | wordlist whit? "," whit? word {% function(d) { return d[0].concat([d[4]]); } %}
 | 
			
		||||
 | 
			
		||||
completeexpression -> expr  {% function(d) { return {tokens: d[0]}; } %}
 | 
			
		||||
                    | expr whit? js  {% function(d) { return {tokens: d[0], postprocess: d[2]}; } %}
 | 
			
		||||
 | 
			
		||||
expr_member ->
 | 
			
		||||
      word {% id %}
 | 
			
		||||
    | "$" word {% function(d) {return {mixin: d[1]}} %}
 | 
			
		||||
    | word "[" expressionlist "]" {% function(d) {return {macrocall: d[0], args: d[2]}} %} 
 | 
			
		||||
    | string "i":? {% function(d) { if (d[1]) {return insensitive(d[0]); } else {return d[0]; } } %}
 | 
			
		||||
    | "%" word {% function(d) {return {token: d[1]}} %}
 | 
			
		||||
    | charclass {% id %}
 | 
			
		||||
    | "(" whit? expression+ whit? ")" {% function(d) {return {'subexpression': d[2]} ;} %}
 | 
			
		||||
    | expr_member whit? ebnf_modifier {% function(d) {return {'ebnf': d[0], 'modifier': d[2]}; } %}
 | 
			
		||||
 | 
			
		||||
ebnf_modifier -> ":+" {% id %} | ":*" {% id %} | ":?" {% id %}
 | 
			
		||||
 | 
			
		||||
expr -> expr_member
 | 
			
		||||
      | expr whit expr_member  {% function(d){ return d[0].concat([d[2]]); } %}
 | 
			
		||||
 | 
			
		||||
word -> [\w\?\+]  {% function(d){ return d[0]; } %}
 | 
			
		||||
      | word [\w\?\+]  {% function(d){ return d[0]+d[1]; } %}
 | 
			
		||||
 | 
			
		||||
string -> dqstring {% function(d) {return { literal: d[0] }; } %}
 | 
			
		||||
#string -> "\"" charset "\""  {% function(d) { return { literal: d[1].join("") }; } %}
 | 
			
		||||
#
 | 
			
		||||
#charset -> null
 | 
			
		||||
#         | charset char  {% function(d) { return d[0].concat([d[1]]); } %}
 | 
			
		||||
#
 | 
			
		||||
#char -> [^\\"]  {% function(d) { return d[0]; } %}
 | 
			
		||||
#      | "\\" .  {% function(d) { return JSON.parse("\""+"\\"+d[1]+"\""); } %}
 | 
			
		||||
 | 
			
		||||
charclass -> "."  {% function(d) { return new RegExp("."); } %}
 | 
			
		||||
           | "[" charclassmembers "]"  {% function(d) { return new RegExp("[" + d[1].join('') + "]"); } %}
 | 
			
		||||
 | 
			
		||||
charclassmembers -> null
 | 
			
		||||
                  | charclassmembers charclassmember  {% function(d) { return d[0].concat([d[1]]); } %}
 | 
			
		||||
 | 
			
		||||
charclassmember -> [^\\\]]  {% function(d) { return d[0]; } %}
 | 
			
		||||
                 | "\\" .  {% function(d) { return d[0] + d[1]; } %}
 | 
			
		||||
 | 
			
		||||
js -> "{" "%" jscode "%" "}"  {% function(d) { return d[2]; } %}
 | 
			
		||||
 | 
			
		||||
jscode -> null  {% function() {return "";} %}
 | 
			
		||||
        | jscode [^%]  {% function(d) {return d[0] + d[1];} %}
 | 
			
		||||
        | jscode "%" [^}] {% function(d) {return d[0] + d[1] + d[2]; } %}
 | 
			
		||||
 | 
			
		||||
# Whitespace with a comment
 | 
			
		||||
whit -> whitraw
 | 
			
		||||
      | whitraw? comment whit?
 | 
			
		||||
 | 
			
		||||
# Optional whitespace with a comment
 | 
			
		||||
whit? -> null
 | 
			
		||||
       | whit
 | 
			
		||||
 | 
			
		||||
# Literally a string of whitespace
 | 
			
		||||
whitraw -> [\s]
 | 
			
		||||
         | whitraw [\s]
 | 
			
		||||
 | 
			
		||||
# A string of whitespace OR the empty string
 | 
			
		||||
whitraw? -> null
 | 
			
		||||
          | whitraw
 | 
			
		||||
 | 
			
		||||
comment -> "#" commentchars "\n"
 | 
			
		||||
commentchars -> null
 | 
			
		||||
              | commentchars [^\n]
 | 
			
		||||
							
								
								
									
										230
									
								
								samples/OpenEdge ABL/test-win.w
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								samples/OpenEdge ABL/test-win.w
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,230 @@
 | 
			
		||||
&ANALYZE-SUSPEND _VERSION-NUMBER AB_v10r12 GUI
 | 
			
		||||
&ANALYZE-RESUME
 | 
			
		||||
&Scoped-define WINDOW-NAME C-Win
 | 
			
		||||
&ANALYZE-SUSPEND _UIB-CODE-BLOCK _CUSTOM _DEFINITIONS C-Win 
 | 
			
		||||
/*------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  File: 
 | 
			
		||||
 | 
			
		||||
  Description: 
 | 
			
		||||
 | 
			
		||||
  Input Parameters:
 | 
			
		||||
      <none>
 | 
			
		||||
 | 
			
		||||
  Output Parameters:
 | 
			
		||||
      <none>
 | 
			
		||||
 | 
			
		||||
  Author: 
 | 
			
		||||
 | 
			
		||||
  Created: 
 | 
			
		||||
 | 
			
		||||
------------------------------------------------------------------------*/
 | 
			
		||||
/*          This .W file was created with the Progress AppBuilder.      */
 | 
			
		||||
/*----------------------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Create an unnamed pool to store all the widgets created 
 | 
			
		||||
     by this procedure. This is a good default which assures
 | 
			
		||||
     that this procedure's triggers and internal procedures 
 | 
			
		||||
     will execute in this procedure's storage, and that proper
 | 
			
		||||
     cleanup will occur on deletion of the procedure. */
 | 
			
		||||
 | 
			
		||||
CREATE WIDGET-POOL.
 | 
			
		||||
 | 
			
		||||
/* ***************************  Definitions  ************************** */
 | 
			
		||||
 | 
			
		||||
/* Parameters Definitions ---                                           */
 | 
			
		||||
 | 
			
		||||
/* Local Variable Definitions ---                                       */
 | 
			
		||||
 | 
			
		||||
/* _UIB-CODE-BLOCK-END */
 | 
			
		||||
&ANALYZE-RESUME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
&ANALYZE-SUSPEND _UIB-PREPROCESSOR-BLOCK 
 | 
			
		||||
 | 
			
		||||
/* ********************  Preprocessor Definitions  ******************** */
 | 
			
		||||
 | 
			
		||||
&Scoped-define PROCEDURE-TYPE Window
 | 
			
		||||
&Scoped-define DB-AWARE no
 | 
			
		||||
 | 
			
		||||
/* Name of designated FRAME-NAME and/or first browse and/or first query */
 | 
			
		||||
&Scoped-define FRAME-NAME DEFAULT-FRAME
 | 
			
		||||
 | 
			
		||||
/* Custom List Definitions                                              */
 | 
			
		||||
/* List-1,List-2,List-3,List-4,List-5,List-6                            */
 | 
			
		||||
 | 
			
		||||
/* _UIB-PREPROCESSOR-BLOCK-END */
 | 
			
		||||
&ANALYZE-RESUME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ***********************  Control Definitions  ********************** */
 | 
			
		||||
 | 
			
		||||
/* Define the widget handle for the window                              */
 | 
			
		||||
DEFINE VAR C-Win AS WIDGET-HANDLE NO-UNDO.
 | 
			
		||||
 | 
			
		||||
/* ************************  Frame Definitions  *********************** */
 | 
			
		||||
 | 
			
		||||
DEFINE FRAME DEFAULT-FRAME
 | 
			
		||||
    WITH 1 DOWN NO-BOX KEEP-TAB-ORDER OVERLAY 
 | 
			
		||||
         SIDE-LABELS NO-UNDERLINE THREE-D 
 | 
			
		||||
         AT COL 1 ROW 1
 | 
			
		||||
         SIZE 80 BY 16 WIDGET-ID 100.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* *********************** Procedure Settings ************************ */
 | 
			
		||||
 | 
			
		||||
&ANALYZE-SUSPEND _PROCEDURE-SETTINGS
 | 
			
		||||
/* Settings for THIS-PROCEDURE
 | 
			
		||||
   Type: Window
 | 
			
		||||
   Allow: Basic,Browse,DB-Fields,Window,Query
 | 
			
		||||
   Other Settings: COMPILE
 | 
			
		||||
 */
 | 
			
		||||
&ANALYZE-RESUME _END-PROCEDURE-SETTINGS
 | 
			
		||||
 | 
			
		||||
/* *************************  Create Window  ************************** */
 | 
			
		||||
 | 
			
		||||
&ANALYZE-SUSPEND _CREATE-WINDOW
 | 
			
		||||
IF SESSION:DISPLAY-TYPE = "GUI":U THEN
 | 
			
		||||
  CREATE WINDOW C-Win ASSIGN
 | 
			
		||||
         HIDDEN             = YES
 | 
			
		||||
         TITLE              = "<insert window title>"
 | 
			
		||||
         HEIGHT             = 16
 | 
			
		||||
         WIDTH              = 80
 | 
			
		||||
         MAX-HEIGHT         = 16
 | 
			
		||||
         MAX-WIDTH          = 80
 | 
			
		||||
         VIRTUAL-HEIGHT     = 16
 | 
			
		||||
         VIRTUAL-WIDTH      = 80
 | 
			
		||||
         RESIZE             = yes
 | 
			
		||||
         SCROLL-BARS        = no
 | 
			
		||||
         STATUS-AREA        = no
 | 
			
		||||
         BGCOLOR            = ?
 | 
			
		||||
         FGCOLOR            = ?
 | 
			
		||||
         KEEP-FRAME-Z-ORDER = yes
 | 
			
		||||
         THREE-D            = yes
 | 
			
		||||
         MESSAGE-AREA       = no
 | 
			
		||||
         SENSITIVE          = yes.
 | 
			
		||||
ELSE {&WINDOW-NAME} = CURRENT-WINDOW.
 | 
			
		||||
/* END WINDOW DEFINITION                                                */
 | 
			
		||||
&ANALYZE-RESUME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ***********  Runtime Attributes and AppBuilder Settings  *********** */
 | 
			
		||||
 | 
			
		||||
&ANALYZE-SUSPEND _RUN-TIME-ATTRIBUTES
 | 
			
		||||
/* SETTINGS FOR WINDOW C-Win
 | 
			
		||||
  VISIBLE,,RUN-PERSISTENT                                               */
 | 
			
		||||
/* SETTINGS FOR FRAME DEFAULT-FRAME
 | 
			
		||||
   FRAME-NAME                                                           */
 | 
			
		||||
IF SESSION:DISPLAY-TYPE = "GUI":U AND VALID-HANDLE(C-Win)
 | 
			
		||||
THEN C-Win:HIDDEN = no.
 | 
			
		||||
 | 
			
		||||
/* _RUN-TIME-ATTRIBUTES-END */
 | 
			
		||||
&ANALYZE-RESUME
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ************************  Control Triggers  ************************ */
 | 
			
		||||
 | 
			
		||||
&Scoped-define SELF-NAME C-Win
 | 
			
		||||
&ANALYZE-SUSPEND _UIB-CODE-BLOCK _CONTROL C-Win C-Win
 | 
			
		||||
ON END-ERROR OF C-Win /* <insert window title> */
 | 
			
		||||
OR ENDKEY OF {&WINDOW-NAME} ANYWHERE DO:
 | 
			
		||||
  /* This case occurs when the user presses the "Esc" key.
 | 
			
		||||
     In a persistently run window, just ignore this.  If we did not, the
 | 
			
		||||
     application would exit. */
 | 
			
		||||
  IF THIS-PROCEDURE:PERSISTENT THEN RETURN NO-APPLY.
 | 
			
		||||
END.
 | 
			
		||||
 | 
			
		||||
/* _UIB-CODE-BLOCK-END */
 | 
			
		||||
&ANALYZE-RESUME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
&ANALYZE-SUSPEND _UIB-CODE-BLOCK _CONTROL C-Win C-Win
 | 
			
		||||
ON WINDOW-CLOSE OF C-Win /* <insert window title> */
 | 
			
		||||
DO:
 | 
			
		||||
  /* This event will close the window and terminate the procedure.  */
 | 
			
		||||
  APPLY "CLOSE":U TO THIS-PROCEDURE.
 | 
			
		||||
  RETURN NO-APPLY.
 | 
			
		||||
END.
 | 
			
		||||
 | 
			
		||||
/* _UIB-CODE-BLOCK-END */
 | 
			
		||||
&ANALYZE-RESUME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
&UNDEFINE SELF-NAME
 | 
			
		||||
 | 
			
		||||
&ANALYZE-SUSPEND _UIB-CODE-BLOCK _CUSTOM _MAIN-BLOCK C-Win 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ***************************  Main Block  *************************** */
 | 
			
		||||
 | 
			
		||||
/* Set CURRENT-WINDOW: this will parent dialog-boxes and frames.        */
 | 
			
		||||
ASSIGN CURRENT-WINDOW                = {&WINDOW-NAME} 
 | 
			
		||||
       THIS-PROCEDURE:CURRENT-WINDOW = {&WINDOW-NAME}.
 | 
			
		||||
 | 
			
		||||
/* The CLOSE event can be used from inside or outside the procedure to  */
 | 
			
		||||
/* terminate it.                                                        */
 | 
			
		||||
ON CLOSE OF THIS-PROCEDURE 
 | 
			
		||||
   RUN disable_UI.
 | 
			
		||||
 | 
			
		||||
/* Best default for GUI applications is...                              */
 | 
			
		||||
PAUSE 0 BEFORE-HIDE.
 | 
			
		||||
 | 
			
		||||
/* Now enable the interface and wait for the exit condition.            */
 | 
			
		||||
/* (NOTE: handle ERROR and END-KEY so cleanup code will always fire.    */
 | 
			
		||||
MAIN-BLOCK:
 | 
			
		||||
DO ON ERROR   UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK
 | 
			
		||||
   ON END-KEY UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK:
 | 
			
		||||
  RUN enable_UI.
 | 
			
		||||
  IF NOT THIS-PROCEDURE:PERSISTENT THEN
 | 
			
		||||
    WAIT-FOR CLOSE OF THIS-PROCEDURE.
 | 
			
		||||
END.
 | 
			
		||||
 | 
			
		||||
/* _UIB-CODE-BLOCK-END */
 | 
			
		||||
&ANALYZE-RESUME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* **********************  Internal Procedures  *********************** */
 | 
			
		||||
 | 
			
		||||
&ANALYZE-SUSPEND _UIB-CODE-BLOCK _PROCEDURE disable_UI C-Win  _DEFAULT-DISABLE
 | 
			
		||||
PROCEDURE disable_UI :
 | 
			
		||||
/*------------------------------------------------------------------------------
 | 
			
		||||
  Purpose:     DISABLE the User Interface
 | 
			
		||||
  Parameters:  <none>
 | 
			
		||||
  Notes:       Here we clean-up the user-interface by deleting
 | 
			
		||||
               dynamic widgets we have created and/or hide 
 | 
			
		||||
               frames.  This procedure is usually called when
 | 
			
		||||
               we are ready to "clean-up" after running.
 | 
			
		||||
------------------------------------------------------------------------------*/
 | 
			
		||||
  /* Delete the WINDOW we created */
 | 
			
		||||
  IF SESSION:DISPLAY-TYPE = "GUI":U AND VALID-HANDLE(C-Win)
 | 
			
		||||
  THEN DELETE WIDGET C-Win.
 | 
			
		||||
  IF THIS-PROCEDURE:PERSISTENT THEN DELETE PROCEDURE THIS-PROCEDURE.
 | 
			
		||||
END PROCEDURE.
 | 
			
		||||
 | 
			
		||||
/* _UIB-CODE-BLOCK-END */
 | 
			
		||||
&ANALYZE-RESUME
 | 
			
		||||
 | 
			
		||||
&ANALYZE-SUSPEND _UIB-CODE-BLOCK _PROCEDURE enable_UI C-Win  _DEFAULT-ENABLE
 | 
			
		||||
PROCEDURE enable_UI :
 | 
			
		||||
/*------------------------------------------------------------------------------
 | 
			
		||||
  Purpose:     ENABLE the User Interface
 | 
			
		||||
  Parameters:  <none>
 | 
			
		||||
  Notes:       Here we display/view/enable the widgets in the
 | 
			
		||||
               user-interface.  In addition, OPEN all queries
 | 
			
		||||
               associated with each FRAME and BROWSE.
 | 
			
		||||
               These statements here are based on the "Other 
 | 
			
		||||
               Settings" section of the widget Property Sheets.
 | 
			
		||||
------------------------------------------------------------------------------*/
 | 
			
		||||
  VIEW FRAME DEFAULT-FRAME IN WINDOW C-Win.
 | 
			
		||||
  {&OPEN-BROWSERS-IN-QUERY-DEFAULT-FRAME}
 | 
			
		||||
  VIEW C-Win.
 | 
			
		||||
END PROCEDURE.
 | 
			
		||||
 | 
			
		||||
/* _UIB-CODE-BLOCK-END */
 | 
			
		||||
&ANALYZE-RESUME
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								samples/PostCSS/sample.pcss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								samples/PostCSS/sample.pcss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
@define-mixin size $size {
 | 
			
		||||
  width: $size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$big: 100px;
 | 
			
		||||
 | 
			
		||||
/* Main block */
 | 
			
		||||
.block {
 | 
			
		||||
  &_logo {
 | 
			
		||||
    background: inline("./logo.png");
 | 
			
		||||
    @mixin size $big;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								samples/SugarSS/sample.sss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								samples/SugarSS/sample.sss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
@define-mixin size $size
 | 
			
		||||
  width: $size
 | 
			
		||||
 | 
			
		||||
$big: 100px
 | 
			
		||||
 | 
			
		||||
// Main block
 | 
			
		||||
.block
 | 
			
		||||
  &_logo
 | 
			
		||||
    background: inline("./logo.png")
 | 
			
		||||
    @mixin size $big
 | 
			
		||||
							
								
								
									
										102
									
								
								samples/TypeScript/cache.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								samples/TypeScript/cache.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
			
		||||
import { DocumentNode } from 'graphql';
 | 
			
		||||
import { getFragmentQueryDocument } from 'apollo-utilities';
 | 
			
		||||
 | 
			
		||||
import { DataProxy, Cache } from './types';
 | 
			
		||||
 | 
			
		||||
export type Transaction<T> = (c: ApolloCache<T>) => void;
 | 
			
		||||
 | 
			
		||||
export abstract class ApolloCache<TSerialized> implements DataProxy {
 | 
			
		||||
  // required to implement
 | 
			
		||||
  // core API
 | 
			
		||||
  public abstract read<T>(query: Cache.ReadOptions): T;
 | 
			
		||||
  public abstract write(write: Cache.WriteOptions): void;
 | 
			
		||||
  public abstract diff<T>(query: Cache.DiffOptions): Cache.DiffResult<T>;
 | 
			
		||||
  public abstract watch(watch: Cache.WatchOptions): () => void;
 | 
			
		||||
  public abstract evict(query: Cache.EvictOptions): Cache.EvictionResult;
 | 
			
		||||
  public abstract reset(): Promise<void>;
 | 
			
		||||
 | 
			
		||||
  // intializer / offline / ssr API
 | 
			
		||||
  /**
 | 
			
		||||
   * Replaces existing state in the cache (if any) with the values expressed by
 | 
			
		||||
   * `serializedState`.
 | 
			
		||||
   *
 | 
			
		||||
   * Called when hydrating a cache (server side rendering, or offline storage),
 | 
			
		||||
   * and also (potentially) during hot reloads.
 | 
			
		||||
   */
 | 
			
		||||
  public abstract restore(
 | 
			
		||||
    serializedState: TSerialized,
 | 
			
		||||
  ): ApolloCache<TSerialized>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Exposes the cache's complete state, in a serializable format for later restoration.
 | 
			
		||||
   */
 | 
			
		||||
  public abstract extract(optimistic: boolean): TSerialized;
 | 
			
		||||
 | 
			
		||||
  // optimistic API
 | 
			
		||||
  public abstract removeOptimistic(id: string): void;
 | 
			
		||||
 | 
			
		||||
  // transactional API
 | 
			
		||||
  public abstract performTransaction(
 | 
			
		||||
    transaction: Transaction<TSerialized>,
 | 
			
		||||
  ): void;
 | 
			
		||||
  public abstract recordOptimisticTransaction(
 | 
			
		||||
    transaction: Transaction<TSerialized>,
 | 
			
		||||
    id: string,
 | 
			
		||||
  ): void;
 | 
			
		||||
 | 
			
		||||
  // optional API
 | 
			
		||||
  public transformDocument(document: DocumentNode): DocumentNode {
 | 
			
		||||
    return document;
 | 
			
		||||
  }
 | 
			
		||||
  // experimental
 | 
			
		||||
  public transformForLink(document: DocumentNode): DocumentNode {
 | 
			
		||||
    return document;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // DataProxy API
 | 
			
		||||
  /**
 | 
			
		||||
   *
 | 
			
		||||
   * @param options
 | 
			
		||||
   * @param optimistic
 | 
			
		||||
   */
 | 
			
		||||
  public readQuery<QueryType>(
 | 
			
		||||
    options: DataProxy.Query,
 | 
			
		||||
    optimistic: boolean = false,
 | 
			
		||||
  ): QueryType {
 | 
			
		||||
    return this.read({
 | 
			
		||||
      query: options.query,
 | 
			
		||||
      variables: options.variables,
 | 
			
		||||
      optimistic,
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public readFragment<FragmentType>(
 | 
			
		||||
    options: DataProxy.Fragment,
 | 
			
		||||
    optimistic: boolean = false,
 | 
			
		||||
  ): FragmentType | null {
 | 
			
		||||
    return this.read({
 | 
			
		||||
      query: getFragmentQueryDocument(options.fragment, options.fragmentName),
 | 
			
		||||
      variables: options.variables,
 | 
			
		||||
      rootId: options.id,
 | 
			
		||||
      optimistic,
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public writeQuery(options: Cache.WriteQueryOptions): void {
 | 
			
		||||
    this.write({
 | 
			
		||||
      dataId: 'ROOT_QUERY',
 | 
			
		||||
      result: options.data,
 | 
			
		||||
      query: options.query,
 | 
			
		||||
      variables: options.variables,
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public writeFragment(options: Cache.WriteFragmentOptions): void {
 | 
			
		||||
    this.write({
 | 
			
		||||
      dataId: options.id,
 | 
			
		||||
      result: options.data,
 | 
			
		||||
      variables: options.variables,
 | 
			
		||||
      query: getFragmentQueryDocument(options.fragment, options.fragmentName),
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1093
									
								
								samples/Visual Basic/VBAllInOne.vb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1093
									
								
								samples/Visual Basic/VBAllInOne.vb
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										77
									
								
								samples/XML/NDepends_Example.ndproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								samples/XML/NDepends_Example.ndproj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
 | 
			
		||||
<NDepend AppName="ExampleNDApp" Platform="DotNet">
 | 
			
		||||
  <OutputDir KeepHistoric="True" KeepXmlFiles="True">c:\temp</OutputDir>
 | 
			
		||||
  <Assemblies />
 | 
			
		||||
  <FrameworkAssemblies />
 | 
			
		||||
  <Dirs>
 | 
			
		||||
    <Dir>C:\Windows\Microsoft.NET\Framework\v4.0.30319</Dir>
 | 
			
		||||
    <Dir>C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF</Dir>
 | 
			
		||||
  </Dirs>
 | 
			
		||||
  <Report Kind="0" SectionsEnabled="12287" XslPath="" Flags="64512">
 | 
			
		||||
    <Section Enabled="True">Application Metrics</Section>
 | 
			
		||||
    <Section Enabled="True">.NET Assemblies Metrics</Section>
 | 
			
		||||
    <Section Enabled="True">Treemap Metric View</Section>
 | 
			
		||||
    <Section Enabled="True">.NET Assemblies Abstractness vs. Instability</Section>
 | 
			
		||||
    <Section Enabled="True">.NET Assemblies Dependencies</Section>
 | 
			
		||||
    <Section Enabled="True">.NET Assemblies Dependency Graph</Section>
 | 
			
		||||
    <Section Enabled="True">.NET Assemblies Build Order</Section>
 | 
			
		||||
    <Section Enabled="True">Analysis Log</Section>
 | 
			
		||||
    <Section Enabled="True">CQL Rules Violated</Section>
 | 
			
		||||
    <Section Enabled="True">Types Metrics</Section>
 | 
			
		||||
    <Section Enabled="False">Types Dependencies</Section>
 | 
			
		||||
  </Report>
 | 
			
		||||
  <BuildComparisonSetting ProjectMode="DontCompare" BuildMode="MostRecentAnalysisResultAvailable" ProjectFileToCompareWith="" BuildFileToCompareWith="" NDaysAgo="1" />
 | 
			
		||||
  <BaselineInUISetting ProjectMode="DontCompare" BuildMode="MostRecentAnalysisResultAvailable" ProjectFileToCompareWith="" BuildFileToCompareWith="" NDaysAgo="1" />
 | 
			
		||||
  <CoverageFiles UncoverableAttribute="" />
 | 
			
		||||
  <SourceFileRebasing FromPath="" ToPath="" />
 | 
			
		||||
  <Queries>
 | 
			
		||||
    <Group Name="Code Quality" Active="True" ShownInReport="False">
 | 
			
		||||
      <Query Active="True" DisplayList="True" DisplayStat="True" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[// <Name>Discard generated and designer Methods from JustMyCode</Name>
 | 
			
		||||
// --- Make sure to make this query richer to discard generated methods from NDepend rules results ---
 | 
			
		||||
notmycode 
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// First define source files paths to discard
 | 
			
		||||
//
 | 
			
		||||
from a in Application.Assemblies 
 | 
			
		||||
where a.SourceFileDeclAvailable 
 | 
			
		||||
let asmSourceFilesPaths = a.SourceDecls.Select(s => s.SourceFile.FilePath)
 | 
			
		||||
 | 
			
		||||
let sourceFilesPathsToDiscard = (
 | 
			
		||||
    from filePath in asmSourceFilesPaths 
 | 
			
		||||
    let filePathLower= filePath.ToString().ToLower()
 | 
			
		||||
    where     
 | 
			
		||||
      filePathLower.EndsWithAny(
 | 
			
		||||
        ".g.cs",        // Popular pattern to name generated files.
 | 
			
		||||
        ".g.vb",
 | 
			
		||||
        ".xaml",        // notmycode WPF xaml code
 | 
			
		||||
        ".designer.cs", // notmycode C# Windows Forms designer code
 | 
			
		||||
        ".designer.vb") // notmycode VB.NET Windows Forms designer code
 | 
			
		||||
       ||
 | 
			
		||||
       // notmycode methods in source files in a directory containing generated
 | 
			
		||||
       filePathLower.Contains("generated")
 | 
			
		||||
  select filePath
 | 
			
		||||
).ToHashSet() 
 | 
			
		||||
  
 | 
			
		||||
//
 | 
			
		||||
// Second: discard methods in sourceFilesPathsToDiscard 
 | 
			
		||||
//
 | 
			
		||||
from m in a.ChildMethods
 | 
			
		||||
where (m.SourceFileDeclAvailable && 
 | 
			
		||||
       sourceFilesPathsToDiscard.Contains(m.SourceDecls.First().SourceFile.FilePath)) ||
 | 
			
		||||
      // Generated methods might be tagged with this attribute
 | 
			
		||||
      m.HasAttribute ("System.CodeDom.Compiler.GeneratedCodeAttribute".AllowNoMatch())
 | 
			
		||||
select new { m, m.NbLinesOfCode }]]></Query>
 | 
			
		||||
      <Query Active="True" DisplayList="True" DisplayStat="True" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[// <Name>Discard generated Fields from JustMyCode</Name>
 | 
			
		||||
// --- Make sure to make this query richer to discard generated fields from NDepend rules results ---
 | 
			
		||||
notmycode
 | 
			
		||||
from f in Application.Fields where 
 | 
			
		||||
  f.HasAttribute ("System.CodeDom.Compiler.GeneratedCodeAttribute".AllowNoMatch()) ||
 | 
			
		||||
 | 
			
		||||
  // Eliminate "components" generated in Windows Form Conrol context
 | 
			
		||||
  f.Name == "components" && f.ParentType.DeriveFrom("System.Windows.Forms.Control".AllowNoMatch())
 | 
			
		||||
select f]]></Query>
 | 
			
		||||
    </Group>
 | 
			
		||||
  </Queries>
 | 
			
		||||
  <WarnFilter />
 | 
			
		||||
</NDepend>
 | 
			
		||||
							
								
								
									
										183
									
								
								samples/XML/chrome.natvis
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								samples/XML/chrome.natvis
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,183 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<!-- 
 | 
			
		||||
Copyright 2015 The Chromium Authors. All rights reserved.
 | 
			
		||||
 | 
			
		||||
https://cs.chromium.org/chromium/src/tools/win/DebugVisualizers/chrome.natvis
 | 
			
		||||
-->
 | 
			
		||||
<AutoVisualizer
 | 
			
		||||
    xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
 | 
			
		||||
  <Type Name="gfx::Point">
 | 
			
		||||
    <AlternativeType Name="gfx::PointF"/>
 | 
			
		||||
    <DisplayString>({x_}, {y_})</DisplayString>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="gfx::Size">
 | 
			
		||||
    <AlternativeType Name="gfx::SizeF"/>
 | 
			
		||||
    <DisplayString>({width_}, {height_})</DisplayString>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="gfx::Rect">
 | 
			
		||||
    <AlternativeType Name="gfx::RectF"/>
 | 
			
		||||
    <DisplayString>({origin_.x_}, {origin_.y_}) x ({size_.width_}, {size_.height_})</DisplayString>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="scoped_refptr<*>">
 | 
			
		||||
    <DisplayString Condition="ptr_ == 0">null</DisplayString>
 | 
			
		||||
    <DisplayString>[{((base::subtle::RefCountedBase*)ptr_)->ref_count_}] {(void*)ptr_} {*ptr_}</DisplayString>
 | 
			
		||||
    <Expand>
 | 
			
		||||
      <Item Name="Ptr">ptr_</Item>
 | 
			
		||||
      <Item Name="RefCount">((base::subtle::RefCountedBase*)ptr_)->ref_count_</Item>
 | 
			
		||||
    </Expand>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="base::Optional<*>">
 | 
			
		||||
    <DisplayString Condition="storage_.is_null_">(null)</DisplayString>
 | 
			
		||||
    <DisplayString>{storage_.value_}</DisplayString>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="base::RefCounted<*>">
 | 
			
		||||
    <DisplayString>RefCount: {ref_count_}</DisplayString>
 | 
			
		||||
    <Expand>
 | 
			
		||||
      <Item Name="RefCount">ref_count_</Item>
 | 
			
		||||
    </Expand>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="IPC::Message::Header">
 | 
			
		||||
    <DisplayString>{{Routing: {routing}, Type: {type}}}</DisplayString>
 | 
			
		||||
    <Expand>
 | 
			
		||||
      <Item Name="RoutingId">routing</Item>
 | 
			
		||||
      <Item Name="Type">type</Item>
 | 
			
		||||
      <Synthetic Name="Priority"
 | 
			
		||||
                 Condition="(flags & IPC::Message::PRIORITY_MASK) ==
 | 
			
		||||
                                IPC::Message::PRIORITY_LOW">
 | 
			
		||||
        <DisplayString>Low</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Priority"
 | 
			
		||||
                 Condition="(flags & IPC::Message::PRIORITY_MASK) ==
 | 
			
		||||
                                IPC::Message::PRIORITY_NORMAL">
 | 
			
		||||
        <DisplayString>Normal</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Priority"
 | 
			
		||||
                 Condition="(flags & IPC::Message::PRIORITY_MASK) ==
 | 
			
		||||
                                IPC::Message::PRIORITY_HIGH">
 | 
			
		||||
        <DisplayString>High</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Sync"
 | 
			
		||||
                 Condition="(flags & IPC::Message::SYNC_BIT) != 0">
 | 
			
		||||
        <DisplayString>true</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Sync"
 | 
			
		||||
                 Condition="(flags & IPC::Message::SYNC_BIT) == 0">
 | 
			
		||||
        <DisplayString>false</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Reply"
 | 
			
		||||
                 Condition="(flags & IPC::Message::REPLY_BIT) != 0">
 | 
			
		||||
        <DisplayString>true</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Reply"
 | 
			
		||||
                 Condition="(flags & IPC::Message::REPLY_BIT) == 0">
 | 
			
		||||
        <DisplayString>false</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="ReplyError"
 | 
			
		||||
                 Condition="(flags & IPC::Message::REPLY_ERROR_BIT) != 0">
 | 
			
		||||
        <DisplayString>true</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="ReplyError"
 | 
			
		||||
                 Condition="(flags & IPC::Message::REPLY_ERROR_BIT) == 0">
 | 
			
		||||
        <DisplayString>false</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Unblock"
 | 
			
		||||
                 Condition="(flags & IPC::Message::UNBLOCK_BIT) != 0">
 | 
			
		||||
        <DisplayString>true</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Unblock"
 | 
			
		||||
                 Condition="(flags & IPC::Message::UNBLOCK_BIT) == 0">
 | 
			
		||||
        <DisplayString>false</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="PumpingMessages"
 | 
			
		||||
                 Condition="(flags & IPC::Message::PUMPING_MSGS_BIT) != 0">
 | 
			
		||||
        <DisplayString>true</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="PumpingMessages"
 | 
			
		||||
                 Condition="(flags & IPC::Message::PUMPING_MSGS_BIT) == 0">
 | 
			
		||||
        <DisplayString>false</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="HasSentTime"
 | 
			
		||||
                 Condition="(flags & IPC::Message::HAS_SENT_TIME_BIT) != 0">
 | 
			
		||||
        <DisplayString>true</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="HasSentTime"
 | 
			
		||||
                 Condition="(flags & IPC::Message::HAS_SENT_TIME_BIT) == 0">
 | 
			
		||||
        <DisplayString>false</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
    </Expand>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="IPC::Message">
 | 
			
		||||
    <DisplayString>{{size = {header_size_+capacity_after_header_}}}</DisplayString>
 | 
			
		||||
    <Expand>
 | 
			
		||||
      <ExpandedItem>*((IPC::Message::Header*)header_),nd</ExpandedItem>
 | 
			
		||||
      <Item Name="Payload">(void*)((char*)header_ + header_size_)</Item>
 | 
			
		||||
    </Expand>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="base::TimeDelta">
 | 
			
		||||
    <DisplayString>{delta_}</DisplayString>
 | 
			
		||||
    <Expand>
 | 
			
		||||
      <Synthetic Name="Days">
 | 
			
		||||
        <DisplayString>{(int)(delta_ / {,,base.dll}base::Time::kMicrosecondsPerDay)}</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Hours">
 | 
			
		||||
        <DisplayString>{(int)(delta_ / {,,base.dll}base::Time::kMicrosecondsPerHour)}</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Minutes">
 | 
			
		||||
        <DisplayString>{(int)(delta_ / {,,base.dll}base::Time::kMicrosecondsPerMinute)}</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Seconds">
 | 
			
		||||
        <DisplayString>{(int)(delta_ / {,,base.dll}base::Time::kMicrosecondsPerSecond)}</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Synthetic Name="Milliseconds">
 | 
			
		||||
        <DisplayString>{(int)(delta_ / {,,base.dll}base::Time::kMicrosecondsPerMillisecond)}</DisplayString>
 | 
			
		||||
      </Synthetic>
 | 
			
		||||
      <Item Name="Microseconds">delta_</Item>
 | 
			
		||||
    </Expand>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="GURL">
 | 
			
		||||
    <DisplayString>{spec_}</DisplayString>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="base::ManualConstructor<*>">
 | 
			
		||||
    <!-- $T1 expands to the first "*" in the name which is the template
 | 
			
		||||
         type. Use that to cast to the correct value. -->
 | 
			
		||||
    <DisplayString>{*($T1*)space_.data_}</DisplayString>
 | 
			
		||||
    <Expand>
 | 
			
		||||
      <ExpandedItem>*($T1*)space_.data_</ExpandedItem>
 | 
			
		||||
    </Expand>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="base::internal::flat_tree<*>">
 | 
			
		||||
    <AlternativeType Name="base::flat_set<*>"/>
 | 
			
		||||
    <DisplayString>{impl_.body_}</DisplayString>
 | 
			
		||||
    <Expand>
 | 
			
		||||
      <ExpandedItem>impl_.body_</ExpandedItem>
 | 
			
		||||
    </Expand>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="base::flat_map<*>">
 | 
			
		||||
    <DisplayString>{impl_.body_}</DisplayString>
 | 
			
		||||
    <Expand>
 | 
			
		||||
      <ExpandedItem>impl_.body_</ExpandedItem>
 | 
			
		||||
    </Expand>
 | 
			
		||||
  </Type>
 | 
			
		||||
  <Type Name="base::Value">
 | 
			
		||||
    <DisplayString Condition="type_ == NONE">NONE</DisplayString>
 | 
			
		||||
    <DisplayString Condition="type_ == BOOLEAN">BOOLEAN {bool_value_}</DisplayString>
 | 
			
		||||
    <DisplayString Condition="type_ == INTEGER">INTEGER {int_value_}</DisplayString>
 | 
			
		||||
    <DisplayString Condition="type_ == DOUBLE">DOUBLE {double_value_}</DisplayString>
 | 
			
		||||
    <DisplayString Condition="type_ == STRING">STRING {string_value_}</DisplayString>
 | 
			
		||||
    <DisplayString Condition="type_ == BINARY">BINARY {binary_value_}</DisplayString>
 | 
			
		||||
    <DisplayString Condition="type_ == DICTIONARY">DICTIONARY {dict_}</DisplayString>
 | 
			
		||||
    <DisplayString Condition="type_ == LIST">LIST {list_}</DisplayString>
 | 
			
		||||
    <Expand>
 | 
			
		||||
      <Item Name="[type]">type_</Item>
 | 
			
		||||
      <Item Condition="type_ == BOOLEAN" Name="[boolean]">bool_value_</Item>
 | 
			
		||||
      <Item Condition="type_ == INTEGER" Name="[integer]">int_value_</Item>
 | 
			
		||||
      <Item Condition="type_ == DOUBLE" Name="[double]">double_value_</Item>
 | 
			
		||||
      <Item Condition="type_ == STRING" Name="[string]">string_value_</Item>
 | 
			
		||||
      <Item Condition="type_ == BINARY" Name="[binary]">binary_value_</Item>
 | 
			
		||||
      <!-- Put the members for dictionary and list directly inline without
 | 
			
		||||
           requiring a separate expansion to view. -->
 | 
			
		||||
      <ExpandedItem Condition="type_ == DICTIONARY">dict_</ExpandedItem>
 | 
			
		||||
      <ExpandedItem Condition="type_ == LIST">list_</ExpandedItem>
 | 
			
		||||
    </Expand>
 | 
			
		||||
  </Type>
 | 
			
		||||
</AutoVisualizer>
 | 
			
		||||
							
								
								
									
										9
									
								
								samples/XML/cloudconfig.cscfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								samples/XML/cloudconfig.cscfg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<ServiceConfiguration serviceName="MyDef" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
 | 
			
		||||
  <Role name="My.Web">
 | 
			
		||||
    <Instances count="1" />
 | 
			
		||||
    <ConfigurationSettings>
 | 
			
		||||
      <Setting name="DiagnosticsConnectionString" value="UseDevelopmentStorage=true" />
 | 
			
		||||
    </ConfigurationSettings>
 | 
			
		||||
  </Role>
 | 
			
		||||
</ServiceConfiguration>
 | 
			
		||||
							
								
								
									
										11
									
								
								samples/XML/clouddef.csdef
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								samples/XML/clouddef.csdef
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<ServiceDefinition name="MyDef" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
 | 
			
		||||
  <WebRole name="My.Web">
 | 
			
		||||
    <InputEndpoints>
 | 
			
		||||
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
 | 
			
		||||
    </InputEndpoints>
 | 
			
		||||
    <ConfigurationSettings>
 | 
			
		||||
      <Setting name="DiagnosticsConnectionString" />
 | 
			
		||||
    </ConfigurationSettings>
 | 
			
		||||
  </WebRole>
 | 
			
		||||
</ServiceDefinition>
 | 
			
		||||
							
								
								
									
										9
									
								
								samples/XML/configdef.cscfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								samples/XML/configdef.cscfg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<ServiceConfiguration serviceName="MyDef" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
 | 
			
		||||
  <Role name="My.Web">
 | 
			
		||||
    <Instances count="1" />
 | 
			
		||||
    <ConfigurationSettings>
 | 
			
		||||
      <Setting name="DiagnosticsConnectionString" value="UseDevelopmentStorage=true" />
 | 
			
		||||
    </ConfigurationSettings>
 | 
			
		||||
  </Role>
 | 
			
		||||
</ServiceConfiguration>
 | 
			
		||||
							
								
								
									
										14
									
								
								samples/XML/dependency-example.depproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								samples/XML/dependency-example.depproj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
 | 
			
		||||
  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <AssemblyVersion>3.9.0.0</AssemblyVersion>
 | 
			
		||||
    <OutputType>Library</OutputType>
 | 
			
		||||
    <PackageTargetFramework>dotnet5.1</PackageTargetFramework>
 | 
			
		||||
    <NuGetTargetMoniker>.NETPlatform,Version=v5.1</NuGetTargetMoniker>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <None Include="project.json" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
 | 
			
		||||
</Project>
 | 
			
		||||
							
								
								
									
										11
									
								
								samples/XML/example-sharedproj.shproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								samples/XML/example-sharedproj.shproj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <ProjectGuid>{86244B26-C4AE-4F69-9315-B6148C0FE270}</ProjectGuid>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
 | 
			
		||||
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
 | 
			
		||||
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
 | 
			
		||||
  <Import Project="SharedProject.projitems" Label="Shared" />
 | 
			
		||||
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
 | 
			
		||||
</Project>
 | 
			
		||||
							
								
								
									
										38
									
								
								samples/XML/example.ccproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								samples/XML/example.ccproj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
 | 
			
		||||
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
 | 
			
		||||
    <ProductVersion>1.0.0</ProductVersion>
 | 
			
		||||
    <ProjectGuid>{0beae469-c1c6-4648-a2e5-0ae0ea9efffa}</ProjectGuid>
 | 
			
		||||
    <OutputType>Library</OutputType>
 | 
			
		||||
    <AppDesignerFolder>Properties</AppDesignerFolder>
 | 
			
		||||
    <RootNamespace>MyDef</RootNamespace>
 | 
			
		||||
    <AssemblyName>MyDef</AssemblyName>
 | 
			
		||||
    <StartDevelopmentStorage>True</StartDevelopmentStorage>
 | 
			
		||||
    <Name>My</Name>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 | 
			
		||||
    <DebugSymbols>true</DebugSymbols>
 | 
			
		||||
    <DebugType>full</DebugType>
 | 
			
		||||
    <Optimize>false</Optimize>
 | 
			
		||||
    <OutputPath>bin\Debug\</OutputPath>
 | 
			
		||||
    <DefineConstants>DEBUG;TRACE</DefineConstants>
 | 
			
		||||
    <ErrorReport>prompt</ErrorReport>
 | 
			
		||||
    <WarningLevel>4</WarningLevel>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <!-- Items for the project -->
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ServiceDefinition Include="ServiceDefinition.csdef" />
 | 
			
		||||
    <ServiceConfiguration Include="ServiceConfiguration.cscfg" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ProjectReference Include="..\My.Web\My.Web.csproj">
 | 
			
		||||
      <Name>My.Web</Name>
 | 
			
		||||
      <Project>{1515c2c3-0b57-422c-a6f9-0891b86fb7d3}</Project>
 | 
			
		||||
      <Private>True</Private>
 | 
			
		||||
      <RoleType>Web</RoleType>
 | 
			
		||||
      <RoleName>My.Web</RoleName>
 | 
			
		||||
    </ProjectReference>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
</Project>
 | 
			
		||||
							
								
								
									
										85
									
								
								samples/XML/msbuild-example.proj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								samples/XML/msbuild-example.proj
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 | 
			
		||||
  <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
 | 
			
		||||
  <UsingTask TaskName="Microsoft.Build.Tasks.XmlPeek" AssemblyName="Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
 | 
			
		||||
  <UsingTask TaskName="Microsoft.Build.Tasks.XmlPoke" AssemblyName="Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <SolutionRoot>$(MSBuildProjectDirectory)\..</SolutionRoot>
 | 
			
		||||
    <ProjectRoot>$(SolutionRoot)\Src\Bowerbird.Website</ProjectRoot>
 | 
			
		||||
    <ArtifactsDir>$(SolutionRoot)\Release</ArtifactsDir>
 | 
			
		||||
    <CurrentBuildDateStamp>$([System.DateTime]::Now.ToString("yyyyMMdd"))</CurrentBuildDateStamp>
 | 
			
		||||
    <CurrentBuildTimeStamp>$([System.DateTime]::Now.ToString("hhmm"))</CurrentBuildTimeStamp>
 | 
			
		||||
    <CurrentBuildDir>$(ArtifactsDir)\$(CurrentBuildDateStamp)-$(Configuration)</CurrentBuildDir>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <VersionMajor>0</VersionMajor>
 | 
			
		||||
    <VersionMinor>1</VersionMinor>
 | 
			
		||||
    <VersionPatch>0</VersionPatch>
 | 
			
		||||
    <VersionPreRelease></VersionPreRelease>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <WebConfig>$(CurrentBuildDir)\Web.config</WebConfig>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageFiles Include="$(ProjectRoot)\**\*.*"
 | 
			
		||||
                  Exclude="$(ProjectRoot)\bin\*.pdb;
 | 
			
		||||
                  $(ProjectRoot)\bin\*.xml;
 | 
			
		||||
                  $(ProjectRoot)\Logs\**\*.*;
 | 
			
		||||
                  $(ProjectRoot)\obj\**\*.*;
 | 
			
		||||
                  $(ProjectRoot)\test\**\*.*;
 | 
			
		||||
                  $(ProjectRoot)\media\**\*.*;
 | 
			
		||||
                  $(ProjectRoot)\**\*.orig;
 | 
			
		||||
                  $(ProjectRoot)\*.config;
 | 
			
		||||
                  $(ProjectRoot)\*.xml;
 | 
			
		||||
                  $(ProjectRoot)\**\*.csproj;
 | 
			
		||||
                  $(ProjectRoot)\*.csproj.user;">
 | 
			
		||||
    </PackageFiles>
 | 
			
		||||
    <ConfigFiles Include="$(ProjectRoot)\Web.config" >
 | 
			
		||||
    </ConfigFiles>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <Target Name="UpdateWebConfig"  Condition=" '$(CurrentBuildDateStamp)' != '' ">
 | 
			
		||||
      <XmlPoke Namespaces="<Namespace Prefix='msb' Uri='http://schemas.microsoft.com/developer/msbuild/2003'/>"
 | 
			
		||||
          XmlInputPath="$(WebConfig)"
 | 
			
		||||
          Query="//add[@key='staticContentIncrement']/@value"
 | 
			
		||||
          Value="$(CurrentBuildDateStamp)-$(CurrentBuildTimeStamp)" />
 | 
			
		||||
    </Target>
 | 
			
		||||
  <Target Name="CreateOutputDir">
 | 
			
		||||
    <Message Text="Creating Directory $(CurrentBuildDir)" />
 | 
			
		||||
    <RemoveDir Directories="$(CurrentBuildDir)" />
 | 
			
		||||
    <Delete Files="$(CurrentBuildDir)" />
 | 
			
		||||
    <MakeDir Directories="$(CurrentBuildDir)" />
 | 
			
		||||
  </Target>
 | 
			
		||||
  <Target Name="BuildMediaDirectories">
 | 
			
		||||
    <MakeDir Directories="$(CurrentBuildDir)\media" />
 | 
			
		||||
  </Target>
 | 
			
		||||
  <Target Name="ConfigSettingsMessages">
 | 
			
		||||
    <Message Text="Configuration is $(Configuration)" />
 | 
			
		||||
    <Message Text="BuildNumber is $(BuildNumber)" />
 | 
			
		||||
    <Message Text="ProjectRoot is $(ProjectRoot)" />
 | 
			
		||||
    <Message Text="CurrentBuildDir is $(CurrentBuildDir)" />
 | 
			
		||||
  </Target>
 | 
			
		||||
  <Target Name="BuildSolution">
 | 
			
		||||
    <MSBuild Projects="$(SolutionRoot)\Bowerbird.sln" Targets="Build" Properties="Configuration=$(Configuration)" />
 | 
			
		||||
  </Target>
 | 
			
		||||
  <Target Name="CopyFilesToReleaseDir">
 | 
			
		||||
    <Copy SourceFiles="@(PackageFiles)" DestinationFiles="@(PackageFiles->'$(CurrentBuildDir)\%(RecursiveDir)%(Filename)%(Extension)')" />
 | 
			
		||||
    <Copy SourceFiles="@(ConfigFiles)" DestinationFiles="$(CurrentBuildDir)\web.config" />
 | 
			
		||||
  </Target>
 | 
			
		||||
  <Target Name="ZipUpReleaseFiles">
 | 
			
		||||
    <ItemGroup>
 | 
			
		||||
      <ZipFiles Include="$(CurrentBuildDir)\**\*.*" Exclude="*.zip" />
 | 
			
		||||
    </ItemGroup>
 | 
			
		||||
    <Zip Files="@(ZipFiles)" WorkingDirectory="$(CurrentBuildDir)\$(Configuration)\" ZipFileName="$(CurrentBuildDateStamp)-$(Configuration).zip" ZipLevel="9" />
 | 
			
		||||
  </Target>
 | 
			
		||||
  <Target Name="CopyZipToReleaseDir" DependsOnTargets="ZipUpReleaseFiles">
 | 
			
		||||
    <Copy SourceFiles="$(MSBuildProjectDirectory)\$(CurrentBuildDateStamp)-$(Configuration).zip" DestinationFiles="$(ArtifactsDir)\$(CurrentBuildDateStamp)-$(Configuration).zip" />
 | 
			
		||||
    <Delete Files="$(MSBuildProjectDirectory)\$(CurrentBuildDateStamp)-$(Configuration).zip" />
 | 
			
		||||
  </Target>
 | 
			
		||||
  <Target Name="Build" DependsOnTargets="CreateOutputDir">
 | 
			
		||||
    <CallTarget Targets="BuildMediaDirectories"/>
 | 
			
		||||
    <CallTarget Targets="ConfigSettingsMessages"/>
 | 
			
		||||
    <CallTarget Targets="BuildSolution"/>
 | 
			
		||||
    <CallTarget Targets="CopyFilesToReleaseDir"/>
 | 
			
		||||
    <CallTarget Targets="UpdateWebConfig" />
 | 
			
		||||
    <CallTarget Targets="CopyZipToReleaseDir"/>
 | 
			
		||||
  </Target>
 | 
			
		||||
</Project>
 | 
			
		||||
							
								
								
									
										30
									
								
								samples/YAML/filenames/.clang-tidy
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								samples/YAML/filenames/.clang-tidy
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
---
 | 
			
		||||
Checks:          'clang-diagnostic-*,clang-analyzer-*'
 | 
			
		||||
WarningsAsErrors: ''
 | 
			
		||||
HeaderFilterRegex: ''
 | 
			
		||||
AnalyzeTemporaryDtors: false
 | 
			
		||||
FormatStyle:     none
 | 
			
		||||
User:            linguist-user
 | 
			
		||||
CheckOptions:
 | 
			
		||||
  - key:             google-readability-braces-around-statements.ShortStatementLines
 | 
			
		||||
    value:           '1'
 | 
			
		||||
  - key:             google-readability-function-size.StatementThreshold
 | 
			
		||||
    value:           '800'
 | 
			
		||||
  - key:             google-readability-namespace-comments.ShortNamespaceLines
 | 
			
		||||
    value:           '10'
 | 
			
		||||
  - key:             google-readability-namespace-comments.SpacesBeforeComments
 | 
			
		||||
    value:           '2'
 | 
			
		||||
  - key:             modernize-loop-convert.MaxCopySize
 | 
			
		||||
    value:           '16'
 | 
			
		||||
  - key:             modernize-loop-convert.MinConfidence
 | 
			
		||||
    value:           reasonable
 | 
			
		||||
  - key:             modernize-loop-convert.NamingStyle
 | 
			
		||||
    value:           CamelCase
 | 
			
		||||
  - key:             modernize-pass-by-value.IncludeStyle
 | 
			
		||||
    value:           llvm
 | 
			
		||||
  - key:             modernize-replace-auto-ptr.IncludeStyle
 | 
			
		||||
    value:           llvm
 | 
			
		||||
  - key:             modernize-use-nullptr.NullMacros
 | 
			
		||||
    value:           'NULL'
 | 
			
		||||
...
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								samples/YARA/OfExample.yar
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								samples/YARA/OfExample.yar
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
rule OfExample2
 | 
			
		||||
{
 | 
			
		||||
    strings:
 | 
			
		||||
        $foo1 = "foo1"
 | 
			
		||||
        $foo2 = "foo2"
 | 
			
		||||
        $foo3 = "foo3"
 | 
			
		||||
 | 
			
		||||
    condition:
 | 
			
		||||
        2 of ($foo*)  // equivalent to 2 of ($foo1,$foo2,$foo3)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rule OfExample3
 | 
			
		||||
{
 | 
			
		||||
    strings:
 | 
			
		||||
        $foo1 = "foo1"
 | 
			
		||||
        $foo2 = "foo2"
 | 
			
		||||
 | 
			
		||||
        $bar1 = "bar1"
 | 
			
		||||
        $bar2 = "bar2"
 | 
			
		||||
 | 
			
		||||
    condition:
 | 
			
		||||
        3 of ($foo*,$bar1,$bar2)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								samples/YARA/example.yara
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								samples/YARA/example.yara
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
rule silent_banker : banker
 | 
			
		||||
{
 | 
			
		||||
    meta:
 | 
			
		||||
        description = "This is just an example"
 | 
			
		||||
        thread_level = 3
 | 
			
		||||
        in_the_wild = true
 | 
			
		||||
    strings:
 | 
			
		||||
        $a = {6A 40 68 00 30 00 00 6A 14 8D 91}
 | 
			
		||||
        $b = {8D 4D B0 2B C1 83 C0 27 99 6A 4E 59 F7 F9}
 | 
			
		||||
        $c = "UVODFRYSIHLNWPEJXQZAKCBGMT"
 | 
			
		||||
    condition:
 | 
			
		||||
        $a or $b or $c
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								samples/YARA/true.yar
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								samples/YARA/true.yar
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
rule test { condition: true }
 | 
			
		||||
							
								
								
									
										21
									
								
								samples/wdl/hello.wdl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								samples/wdl/hello.wdl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
# Sample originally from https://github.com/broadinstitute/centaur
 | 
			
		||||
 | 
			
		||||
task hello {
 | 
			
		||||
  String addressee
 | 
			
		||||
  command {
 | 
			
		||||
    echo "Hello ${addressee}!"
 | 
			
		||||
  }
 | 
			
		||||
  output {
 | 
			
		||||
    String salutation = read_string(stdout())
 | 
			
		||||
  }
 | 
			
		||||
  runtime {
 | 
			
		||||
    docker: "ubuntu@sha256:71cd81252a3563a03ad8daee81047b62ab5d892ebbfbf71cf53415f29c130950"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
workflow wf_hello {
 | 
			
		||||
  call hello
 | 
			
		||||
  output {
 | 
			
		||||
     hello.salutation
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								samples/wdl/ifs_in_scatters.wdl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								samples/wdl/ifs_in_scatters.wdl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
# Sample originally from https://github.com/broadinstitute/centaur
 | 
			
		||||
 | 
			
		||||
task validate_int {
 | 
			
		||||
  Int i
 | 
			
		||||
  command {
 | 
			
		||||
    echo $(( ${i} % 2 ))
 | 
			
		||||
  }
 | 
			
		||||
  output {
 | 
			
		||||
    Boolean validation = read_int(stdout()) == 1
 | 
			
		||||
  }
 | 
			
		||||
  runtime {
 | 
			
		||||
    docker: "ubuntu:latest"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
task mirror {
 | 
			
		||||
  Int i
 | 
			
		||||
  command {
 | 
			
		||||
    echo ${i}
 | 
			
		||||
  }
 | 
			
		||||
  output {
 | 
			
		||||
    Int out = read_int(stdout())
 | 
			
		||||
  }
 | 
			
		||||
  runtime {
 | 
			
		||||
    docker: "ubuntu:latest"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
workflow ifs_in_scatters {
 | 
			
		||||
  Array[Int] numbers = range(5)
 | 
			
		||||
 | 
			
		||||
  scatter (n in numbers) {
 | 
			
		||||
 | 
			
		||||
    call validate_int { input: i = n }
 | 
			
		||||
    if (validate_int.validation) {
 | 
			
		||||
      Int incremented = n + 1
 | 
			
		||||
      call mirror { input: i = incremented }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  output {
 | 
			
		||||
    Array[Int?] mirrors = mirror.out
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								samples/wdl/passingfiles.wdl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								samples/wdl/passingfiles.wdl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
# Sample originally from https://github.com/broadinstitute/centaur
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
# Check that we can:
 | 
			
		||||
# - Create a file from a task and feed it into subsequent commands.
 | 
			
		||||
# - Create a file output by interpolating a file name
 | 
			
		||||
# - Use engine functions on an interpolated file name
 | 
			
		||||
##
 | 
			
		||||
 | 
			
		||||
task mkFile {
 | 
			
		||||
  command { 
 | 
			
		||||
    echo "small file contents" > out.txt
 | 
			
		||||
  }
 | 
			
		||||
  output { File out = "out.txt" }
 | 
			
		||||
  runtime { docker: "ubuntu:latest" }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
task consumeFile {
 | 
			
		||||
  File in_file
 | 
			
		||||
  String out_name
 | 
			
		||||
 | 
			
		||||
  command {
 | 
			
		||||
    cat ${in_file} > ${out_name}
 | 
			
		||||
  }
 | 
			
		||||
  runtime {
 | 
			
		||||
    docker: "ubuntu:latest"
 | 
			
		||||
  }
 | 
			
		||||
  output {
 | 
			
		||||
    File out_interpolation = "${out_name}"
 | 
			
		||||
    String contents = read_string("${out_name}")
 | 
			
		||||
    String contentsAlt = read_string(out_interpolation)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
workflow filepassing {
 | 
			
		||||
  call mkFile
 | 
			
		||||
  call consumeFile {input: in_file=mkFile.out, out_name = "myFileName.abc.txt" }
 | 
			
		||||
  output {
 | 
			
		||||
      consumeFile.contents
 | 
			
		||||
      consumeFile.contentsAlt
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
#!/usr/bin/env ruby
 | 
			
		||||
 | 
			
		||||
require "optparse"
 | 
			
		||||
require "open3"
 | 
			
		||||
 | 
			
		||||
ROOT = File.expand_path("../../", __FILE__)
 | 
			
		||||
 | 
			
		||||
@@ -42,6 +43,17 @@ def log(msg)
 | 
			
		||||
  puts msg if $verbose
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def command(*args)
 | 
			
		||||
  log "$ #{args.join(' ')}"
 | 
			
		||||
  output, status = Open3.capture2e(*args)
 | 
			
		||||
  if !status.success?
 | 
			
		||||
    output.each_line do |line|
 | 
			
		||||
      log "  > #{line}"
 | 
			
		||||
    end
 | 
			
		||||
    warn "Command failed. Aborting."
 | 
			
		||||
    exit 1
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
usage = """Usage:
 | 
			
		||||
  #{$0} [-v|--verbose] [--replace grammar] url
 | 
			
		||||
@@ -51,12 +63,12 @@ Examples:
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
$replace = nil
 | 
			
		||||
$verbose = false
 | 
			
		||||
$verbose = true
 | 
			
		||||
 | 
			
		||||
OptionParser.new do |opts|
 | 
			
		||||
  opts.banner = usage
 | 
			
		||||
  opts.on("-v", "--verbose", "Print verbose feedback to STDOUT") do
 | 
			
		||||
    $verbose = true
 | 
			
		||||
  opts.on("-q", "--quiet", "Do not print output unless there's a failure") do
 | 
			
		||||
    $verbose = false
 | 
			
		||||
  end
 | 
			
		||||
  opts.on("-rSUBMODULE", "--replace=SUBMODDULE", "Replace an existing grammar submodule.") do |name|
 | 
			
		||||
    $replace = name
 | 
			
		||||
@@ -82,23 +94,22 @@ Dir.chdir(ROOT)
 | 
			
		||||
 | 
			
		||||
if repo_old
 | 
			
		||||
  log "Deregistering: #{repo_old}"
 | 
			
		||||
  `git submodule deinit #{repo_old}`
 | 
			
		||||
  `git rm -rf #{repo_old}`
 | 
			
		||||
  `script/convert-grammars`
 | 
			
		||||
  command('git', 'submodule', 'deinit', repo_old)
 | 
			
		||||
  command('git', 'rm', '-rf', repo_old)
 | 
			
		||||
  command('script/grammar-compiler', 'update', '-f')
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
log "Registering new submodule: #{repo_new}"
 | 
			
		||||
`git submodule add -f #{https} #{repo_new}`
 | 
			
		||||
exit 1 if $?.exitstatus > 0
 | 
			
		||||
`script/convert-grammars --add #{repo_new}`
 | 
			
		||||
command('git', 'submodule', 'add', '-f', https, repo_new)
 | 
			
		||||
command('script/grammar-compiler', 'add', repo_new)
 | 
			
		||||
 | 
			
		||||
log "Confirming license"
 | 
			
		||||
if repo_old
 | 
			
		||||
  `script/licensed`
 | 
			
		||||
  command('script/licensed')
 | 
			
		||||
else
 | 
			
		||||
  `script/licensed --module "#{repo_new}"`
 | 
			
		||||
  command('script/licensed', '--module', repo_new)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
log "Updating grammar documentation in vendor/REAEDME.md"
 | 
			
		||||
`bundle exec rake samples`
 | 
			
		||||
`script/list-grammars`
 | 
			
		||||
log "Updating grammar documentation in vendor/README.md"
 | 
			
		||||
command('bundle', 'exec', 'rake', 'samples')
 | 
			
		||||
command('script/list-grammars')
 | 
			
		||||
 
 | 
			
		||||
@@ -1,319 +0,0 @@
 | 
			
		||||
#!/usr/bin/env ruby
 | 
			
		||||
 | 
			
		||||
require 'bundler/setup'
 | 
			
		||||
require 'json'
 | 
			
		||||
require 'net/http'
 | 
			
		||||
require 'optparse'
 | 
			
		||||
require 'plist'
 | 
			
		||||
require 'set'
 | 
			
		||||
require 'thread'
 | 
			
		||||
require 'tmpdir'
 | 
			
		||||
require 'uri'
 | 
			
		||||
require 'yaml'
 | 
			
		||||
 | 
			
		||||
ROOT = File.expand_path("../..", __FILE__)
 | 
			
		||||
GRAMMARS_PATH = File.join(ROOT, "grammars")
 | 
			
		||||
SOURCES_FILE = File.join(ROOT, "grammars.yml")
 | 
			
		||||
CSONC = File.join(ROOT, "node_modules", ".bin", "csonc")
 | 
			
		||||
 | 
			
		||||
$options = {
 | 
			
		||||
  :add => false,
 | 
			
		||||
  :install => true,
 | 
			
		||||
  :output => SOURCES_FILE,
 | 
			
		||||
  :remote => true,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class SingleFile
 | 
			
		||||
  def initialize(path)
 | 
			
		||||
    @path = path
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def url
 | 
			
		||||
    @path
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def fetch(tmp_dir)
 | 
			
		||||
    [@path]
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class DirectoryPackage
 | 
			
		||||
  def self.fetch(dir)
 | 
			
		||||
    Dir["#{dir}/**/*"].select do |path|
 | 
			
		||||
      case File.extname(path.downcase)
 | 
			
		||||
      when '.plist'
 | 
			
		||||
        path.split('/')[-2] == 'Syntaxes'
 | 
			
		||||
      when '.tmlanguage', '.yaml-tmlanguage'
 | 
			
		||||
        true
 | 
			
		||||
      when '.cson', '.json'
 | 
			
		||||
        path.split('/')[-2] == 'grammars'
 | 
			
		||||
      else
 | 
			
		||||
        false
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def initialize(directory)
 | 
			
		||||
    @directory = directory
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def url
 | 
			
		||||
    @directory
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def fetch(tmp_dir)
 | 
			
		||||
    self.class.fetch(File.join(ROOT, @directory))
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class TarballPackage
 | 
			
		||||
  def self.fetch(tmp_dir, url)
 | 
			
		||||
    `curl --silent --location --max-time 30 --output "#{tmp_dir}/archive" "#{url}"`
 | 
			
		||||
    raise "Failed to fetch GH package: #{url} #{$?.to_s}" unless $?.success?
 | 
			
		||||
 | 
			
		||||
    output = File.join(tmp_dir, 'extracted')
 | 
			
		||||
    Dir.mkdir(output)
 | 
			
		||||
    `tar -C "#{output}" -xf "#{tmp_dir}/archive"`
 | 
			
		||||
    raise "Failed to uncompress tarball: #{tmp_dir}/archive (from #{url}) #{$?.to_s}" unless $?.success?
 | 
			
		||||
 | 
			
		||||
    DirectoryPackage.fetch(output)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  attr_reader :url
 | 
			
		||||
 | 
			
		||||
  def initialize(url)
 | 
			
		||||
    @url = url
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def fetch(tmp_dir)
 | 
			
		||||
    self.class.fetch(tmp_dir, url)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class SingleGrammar
 | 
			
		||||
  attr_reader :url
 | 
			
		||||
 | 
			
		||||
  def initialize(url)
 | 
			
		||||
    @url = url
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def fetch(tmp_dir)
 | 
			
		||||
    filename = File.join(tmp_dir, File.basename(url))
 | 
			
		||||
    `curl --silent --location --max-time 10 --output "#{filename}" "#{url}"`
 | 
			
		||||
    raise "Failed to fetch grammar: #{url}: #{$?.to_s}" unless $?.success?
 | 
			
		||||
    [filename]
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class SVNPackage
 | 
			
		||||
  attr_reader :url
 | 
			
		||||
 | 
			
		||||
  def initialize(url)
 | 
			
		||||
    @url = url
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def fetch(tmp_dir)
 | 
			
		||||
    `svn export -q "#{url}/Syntaxes" "#{tmp_dir}/Syntaxes"`
 | 
			
		||||
    raise "Failed to export SVN repository: #{url}: #{$?.to_s}" unless $?.success?
 | 
			
		||||
    Dir["#{tmp_dir}/Syntaxes/*.{plist,tmLanguage,tmlanguage,YAML-tmLanguage}"]
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class GitHubPackage
 | 
			
		||||
  def self.parse_url(url)
 | 
			
		||||
    url, ref = url.split("@", 2)
 | 
			
		||||
    path = URI.parse(url).path.split('/')
 | 
			
		||||
    [path[1], path[2].chomp('.git'), ref || "master"]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  attr_reader :user
 | 
			
		||||
  attr_reader :repo
 | 
			
		||||
  attr_reader :ref
 | 
			
		||||
 | 
			
		||||
  def initialize(url)
 | 
			
		||||
    @user, @repo, @ref = self.class.parse_url(url)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def url
 | 
			
		||||
    suffix = "@#{ref}" unless ref == "master"
 | 
			
		||||
    "https://github.com/#{user}/#{repo}#{suffix}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def fetch(tmp_dir)
 | 
			
		||||
    url = "https://github.com/#{user}/#{repo}/archive/#{ref}.tar.gz"
 | 
			
		||||
    TarballPackage.fetch(tmp_dir, url)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def load_grammar(path)
 | 
			
		||||
  case File.extname(path.downcase)
 | 
			
		||||
  when '.plist', '.tmlanguage'
 | 
			
		||||
    Plist::parse_xml(path)
 | 
			
		||||
  when '.yaml-tmlanguage'
 | 
			
		||||
    content = File.read(path)
 | 
			
		||||
    # Attempt to parse YAML file even if it has a YAML 1.2 header
 | 
			
		||||
    if content.lines[0] =~ /^%YAML[ :]1\.2/
 | 
			
		||||
      content = content.lines[1..-1].join
 | 
			
		||||
    end
 | 
			
		||||
    begin
 | 
			
		||||
      YAML.load(content)
 | 
			
		||||
    rescue Psych::SyntaxError => e
 | 
			
		||||
      $stderr.puts "Failed to parse YAML grammar '#{path}'"
 | 
			
		||||
    end
 | 
			
		||||
  when '.cson'
 | 
			
		||||
    cson = `"#{CSONC}" "#{path}"`
 | 
			
		||||
    raise "Failed to convert CSON grammar '#{path}': #{$?.to_s}" unless $?.success?
 | 
			
		||||
    JSON.parse(cson)
 | 
			
		||||
  when '.json'
 | 
			
		||||
    JSON.parse(File.read(path))
 | 
			
		||||
  else
 | 
			
		||||
    raise "Invalid document type #{path}"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def load_grammars(tmp_dir, source, all_scopes)
 | 
			
		||||
  is_url = source.start_with?("http:", "https:")
 | 
			
		||||
  return [] if is_url && !$options[:remote]
 | 
			
		||||
  return [] if !is_url && !File.exist?(source)
 | 
			
		||||
 | 
			
		||||
  p = if !is_url
 | 
			
		||||
        if File.directory?(source)
 | 
			
		||||
          DirectoryPackage.new(source)
 | 
			
		||||
        else
 | 
			
		||||
          SingleFile.new(source)
 | 
			
		||||
        end
 | 
			
		||||
      elsif source.end_with?('.tmLanguage', '.plist', '.YAML-tmLanguage')
 | 
			
		||||
        SingleGrammar.new(source)
 | 
			
		||||
      elsif source.start_with?('https://github.com')
 | 
			
		||||
        GitHubPackage.new(source)
 | 
			
		||||
      elsif source.start_with?('http://svn.textmate.org')
 | 
			
		||||
        SVNPackage.new(source)
 | 
			
		||||
      elsif source.end_with?('.tar.gz')
 | 
			
		||||
        TarballPackage.new(source)
 | 
			
		||||
      else
 | 
			
		||||
        nil
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
  raise "Unsupported source: #{source}" unless p
 | 
			
		||||
 | 
			
		||||
  p.fetch(tmp_dir).map do |path|
 | 
			
		||||
    grammar = load_grammar(path)
 | 
			
		||||
    scope = grammar['scopeName'] || grammar['scope']
 | 
			
		||||
 | 
			
		||||
    if all_scopes.key?(scope)
 | 
			
		||||
      unless all_scopes[scope] == p.url
 | 
			
		||||
        $stderr.puts "WARN: Duplicated scope #{scope}\n" +
 | 
			
		||||
          "  Current package: #{p.url}\n" +
 | 
			
		||||
          "  Previous package: #{all_scopes[scope]}"
 | 
			
		||||
      end
 | 
			
		||||
      next
 | 
			
		||||
    end
 | 
			
		||||
    all_scopes[scope] = p.url
 | 
			
		||||
    grammar
 | 
			
		||||
  end.compact
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def install_grammars(grammars, path)
 | 
			
		||||
  installed = []
 | 
			
		||||
 | 
			
		||||
  grammars.each do |grammar|
 | 
			
		||||
    scope = grammar['scopeName'] || grammar['scope']
 | 
			
		||||
    File.write(File.join(GRAMMARS_PATH, "#{scope}.json"), JSON.pretty_generate(grammar))
 | 
			
		||||
    installed << scope
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  $stderr.puts("OK #{path} (#{installed.join(', ')})")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def run_thread(queue, all_scopes)
 | 
			
		||||
  Dir.mktmpdir do |tmpdir|
 | 
			
		||||
    loop do
 | 
			
		||||
      source, index = begin
 | 
			
		||||
        queue.pop(true)
 | 
			
		||||
      rescue ThreadError
 | 
			
		||||
        # The queue is empty.
 | 
			
		||||
        break
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      dir = "#{tmpdir}/#{index}"
 | 
			
		||||
      Dir.mkdir(dir)
 | 
			
		||||
 | 
			
		||||
      grammars = load_grammars(dir, source, all_scopes)
 | 
			
		||||
      install_grammars(grammars, source) if $options[:install]
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def generate_yaml(all_scopes, base)
 | 
			
		||||
  yaml = all_scopes.each_with_object(base) do |(key,value),out|
 | 
			
		||||
    out[value] ||= []
 | 
			
		||||
    out[value] << key
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  yaml = Hash[yaml.sort]
 | 
			
		||||
  yaml.each { |k, v| v.sort! }
 | 
			
		||||
  yaml
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def main(sources)
 | 
			
		||||
  begin
 | 
			
		||||
    Dir.mkdir(GRAMMARS_PATH)
 | 
			
		||||
  rescue Errno::EEXIST
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  `npm install`
 | 
			
		||||
 | 
			
		||||
  all_scopes = {}
 | 
			
		||||
 | 
			
		||||
  if source = $options[:add]
 | 
			
		||||
    Dir.mktmpdir do |tmpdir|
 | 
			
		||||
      grammars = load_grammars(tmpdir, source, all_scopes)
 | 
			
		||||
      install_grammars(grammars, source) if $options[:install]
 | 
			
		||||
    end
 | 
			
		||||
    generate_yaml(all_scopes, sources)
 | 
			
		||||
  else
 | 
			
		||||
    queue = Queue.new
 | 
			
		||||
 | 
			
		||||
    sources.each do |url, scopes|
 | 
			
		||||
      queue.push([url, queue.length])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    threads = 8.times.map do
 | 
			
		||||
      Thread.new { run_thread(queue, all_scopes) }
 | 
			
		||||
    end
 | 
			
		||||
    threads.each(&:join)
 | 
			
		||||
    generate_yaml(all_scopes, {})
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
OptionParser.new do |opts|
 | 
			
		||||
  opts.banner = "Usage: #{$0} [options]"
 | 
			
		||||
 | 
			
		||||
  opts.on("--add GRAMMAR", "Add a new grammar. GRAMMAR may be a file path or URL.") do |a|
 | 
			
		||||
    $options[:add] = a
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  opts.on("--[no-]install", "Install grammars into grammars/ directory.") do |i|
 | 
			
		||||
    $options[:install] = i
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  opts.on("--output FILE", "Write output to FILE. Use - for stdout.") do |o|
 | 
			
		||||
    $options[:output] = o == "-" ? $stdout : o
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  opts.on("--[no-]remote", "Download remote grammars.") do |r|
 | 
			
		||||
    $options[:remote] = r
 | 
			
		||||
  end
 | 
			
		||||
end.parse!
 | 
			
		||||
 | 
			
		||||
sources = File.open(SOURCES_FILE) do |file|
 | 
			
		||||
  YAML.load(file)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
yaml = main(sources)
 | 
			
		||||
 | 
			
		||||
if $options[:output].is_a?(IO)
 | 
			
		||||
  $options[:output].write(YAML.dump(yaml))
 | 
			
		||||
else
 | 
			
		||||
  File.write($options[:output], YAML.dump(yaml))
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										12
									
								
								script/grammar-compiler
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										12
									
								
								script/grammar-compiler
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
cd "$(dirname "$0")/.."
 | 
			
		||||
 | 
			
		||||
image="linguist/grammar-compiler:latest"
 | 
			
		||||
mkdir -p grammars
 | 
			
		||||
 | 
			
		||||
exec docker run --rm \
 | 
			
		||||
    -u $(id -u $USER):$(id -g $USER) \
 | 
			
		||||
    -v $PWD:/src/linguist \
 | 
			
		||||
    -w /src/linguist $image "$@"
 | 
			
		||||
@@ -99,4 +99,8 @@ class GrammarList
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
list = GrammarList.new
 | 
			
		||||
list.update_readme()
 | 
			
		||||
if ARGV.include? "--print"
 | 
			
		||||
  puts list.to_markdown
 | 
			
		||||
else
 | 
			
		||||
  list.update_readme
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -1,60 +0,0 @@
 | 
			
		||||
#!/usr/bin/env ruby
 | 
			
		||||
 | 
			
		||||
require "bundler/setup"
 | 
			
		||||
require "json"
 | 
			
		||||
require "linguist"
 | 
			
		||||
require "set"
 | 
			
		||||
require "yaml"
 | 
			
		||||
 | 
			
		||||
ROOT = File.expand_path("../../", __FILE__)
 | 
			
		||||
 | 
			
		||||
def find_includes(json)
 | 
			
		||||
  case json
 | 
			
		||||
  when Hash
 | 
			
		||||
    result = []
 | 
			
		||||
    if inc = json["include"]
 | 
			
		||||
      result << inc.split("#", 2).first unless inc.start_with?("#", "$")
 | 
			
		||||
    end
 | 
			
		||||
    result + json.values.flat_map { |v| find_includes(v) }
 | 
			
		||||
  when Array
 | 
			
		||||
    json.flat_map { |v| find_includes(v) }
 | 
			
		||||
  else
 | 
			
		||||
    []
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def transitive_includes(scope, includes)
 | 
			
		||||
  scopes = Set.new
 | 
			
		||||
  queue = includes[scope] || []
 | 
			
		||||
  while s = queue.shift
 | 
			
		||||
    next if scopes.include?(s)
 | 
			
		||||
    scopes << s
 | 
			
		||||
    queue += includes[s] || []
 | 
			
		||||
  end
 | 
			
		||||
  scopes
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
includes = {}
 | 
			
		||||
Dir[File.join(ROOT, "grammars/*.json")].each do |path|
 | 
			
		||||
  scope = File.basename(path).sub(/\.json/, '')
 | 
			
		||||
  json = JSON.load(File.read(path))
 | 
			
		||||
  incs = find_includes(json)
 | 
			
		||||
  next if incs.empty?
 | 
			
		||||
  includes[scope] ||= []
 | 
			
		||||
  includes[scope] += incs
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
yaml = YAML.load(File.read(File.join(ROOT, "grammars.yml")))
 | 
			
		||||
language_scopes = Linguist::Language.all.map(&:tm_scope).to_set
 | 
			
		||||
 | 
			
		||||
# The set of used scopes is the scopes for each language, plus all the scopes
 | 
			
		||||
# they include, transitively.
 | 
			
		||||
used_scopes = language_scopes + language_scopes.flat_map { |s| transitive_includes(s, includes).to_a }.to_set
 | 
			
		||||
 | 
			
		||||
unused = yaml.reject { |repo, scopes| scopes.any? { |scope| used_scopes.include?(scope) } }
 | 
			
		||||
 | 
			
		||||
puts "Unused grammar repos"
 | 
			
		||||
puts unused.map { |repo, scopes| sprintf("%-100s %s", repo, scopes.join(", ")) }.sort.join("\n")
 | 
			
		||||
 | 
			
		||||
yaml.delete_if { |k| unused.key?(k) }
 | 
			
		||||
File.write(File.join(ROOT, "grammars.yml"), YAML.dump(yaml))
 | 
			
		||||
							
								
								
									
										8
									
								
								test/fixtures/Perl/Module.pm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								test/fixtures/Perl/Module.pm
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
use 5.006;
 | 
			
		||||
use strict;
 | 
			
		||||
 | 
			
		||||
=head1
 | 
			
		||||
 | 
			
		||||
module
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
@@ -188,6 +188,17 @@ class TestFileBlob < Minitest::Test
 | 
			
		||||
    assert fixture_blob("Binary/MainMenu.nib").generated?
 | 
			
		||||
    assert !sample_blob("XML/project.pbxproj").generated?
 | 
			
		||||
 | 
			
		||||
    # Cocoapods
 | 
			
		||||
    assert sample_blob('Pods/blah').generated?
 | 
			
		||||
    assert !sample_blob('My-Pods/blah').generated?
 | 
			
		||||
 | 
			
		||||
    # Carthage
 | 
			
		||||
    assert sample_blob('Carthage/Build/blah').generated?
 | 
			
		||||
    assert !sample_blob('Carthage/blah').generated?
 | 
			
		||||
    assert !sample_blob('Carthage/Checkout/blah').generated?
 | 
			
		||||
    assert !sample_blob('My-Carthage/Build/blah').generated?
 | 
			
		||||
    assert !sample_blob('My-Carthage/Build/blah').generated?
 | 
			
		||||
 | 
			
		||||
    # Gemfile.lock is NOT generated
 | 
			
		||||
    assert !sample_blob("Gemfile.lock").generated?
 | 
			
		||||
 | 
			
		||||
@@ -313,8 +324,6 @@ class TestFileBlob < Minitest::Test
 | 
			
		||||
    assert sample_blob("deps/http_parser/http_parser.c").vendored?
 | 
			
		||||
    assert sample_blob("deps/v8/src/v8.h").vendored?
 | 
			
		||||
 | 
			
		||||
    assert sample_blob("tools/something/else.c").vendored?
 | 
			
		||||
 | 
			
		||||
    # Chart.js
 | 
			
		||||
    assert sample_blob("some/vendored/path/Chart.js").vendored?
 | 
			
		||||
    assert !sample_blob("some/vendored/path/chart.js").vendored?
 | 
			
		||||
@@ -490,9 +499,9 @@ class TestFileBlob < Minitest::Test
 | 
			
		||||
 | 
			
		||||
    # Carthage
 | 
			
		||||
    assert sample_blob('Carthage/blah').vendored?
 | 
			
		||||
 | 
			
		||||
    # Cocoapods
 | 
			
		||||
    assert sample_blob('Pods/blah').vendored?
 | 
			
		||||
    assert sample_blob('iOS/Carthage/blah').vendored?
 | 
			
		||||
    assert !sample_blob('My-Carthage/blah').vendored?
 | 
			
		||||
    assert !sample_blob('iOS/My-Carthage/blah').vendored?
 | 
			
		||||
 | 
			
		||||
    # Html5shiv
 | 
			
		||||
    assert sample_blob("Scripts/html5shiv.js").vendored?
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,24 @@ class TestGenerated < Minitest::Test
 | 
			
		||||
    generated_sample_without_loading_data("Dummy/foo.xcworkspacedata")
 | 
			
		||||
    generated_sample_without_loading_data("Dummy/foo.xcuserstate")
 | 
			
		||||
 | 
			
		||||
    # Cocoapods
 | 
			
		||||
    generated_sample_without_loading_data("Pods/Pods.xcodeproj")
 | 
			
		||||
    generated_sample_without_loading_data("Pods/SwiftDependency/foo.swift")
 | 
			
		||||
    generated_sample_without_loading_data("Pods/ObjCDependency/foo.h")
 | 
			
		||||
    generated_sample_without_loading_data("Pods/ObjCDependency/foo.m")
 | 
			
		||||
    generated_sample_without_loading_data("Dummy/Pods/Pods.xcodeproj")
 | 
			
		||||
    generated_sample_without_loading_data("Dummy/Pods/SwiftDependency/foo.swift")
 | 
			
		||||
    generated_sample_without_loading_data("Dummy/Pods/ObjCDependency/foo.h")
 | 
			
		||||
    generated_sample_without_loading_data("Dummy/Pods/ObjCDependency/foo.m")
 | 
			
		||||
 | 
			
		||||
    # Carthage
 | 
			
		||||
    generated_sample_without_loading_data("Carthage/Build/.Dependency.version")
 | 
			
		||||
    generated_sample_without_loading_data("Carthage/Build/iOS/Dependency.framework")
 | 
			
		||||
    generated_sample_without_loading_data("Carthage/Build/Mac/Dependency.framework")
 | 
			
		||||
    generated_sample_without_loading_data("src/Carthage/Build/.Dependency.version")
 | 
			
		||||
    generated_sample_without_loading_data("src/Carthage/Build/iOS/Dependency.framework")
 | 
			
		||||
    generated_sample_without_loading_data("src/Carthage/Build/Mac/Dependency.framework")
 | 
			
		||||
 | 
			
		||||
    # Go-specific vendored paths
 | 
			
		||||
    generated_sample_without_loading_data("go/vendor/github.com/foo.go")
 | 
			
		||||
    generated_sample_without_loading_data("go/vendor/golang.org/src/foo.c")
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,6 @@ class TestGrammars < Minitest::Test
 | 
			
		||||
    "8653305b358375d0fced85dc24793b99919b11ef", # language-shellscript
 | 
			
		||||
    "9f0c0b0926a18f5038e455e8df60221125fc3111", # elixir-tmbundle
 | 
			
		||||
    "a4dadb2374282098c5b8b14df308906f5347d79a", # mako-tmbundle
 | 
			
		||||
    "b9b24778619dce325b651f0d77cbc72e7ae0b0a3", # Julia.tmbundle
 | 
			
		||||
    "e06722add999e7428048abcc067cd85f1f7ca71c", # r.tmbundle
 | 
			
		||||
    "50b14a0e3f03d7ca754dac42ffb33302b5882b78", # smalltalk-tmbundle
 | 
			
		||||
    "eafbc4a2f283752858e6908907f3c0c90188785b", # gap-tmbundle
 | 
			
		||||
@@ -43,6 +42,8 @@ class TestGrammars < Minitest::Test
 | 
			
		||||
    "82c356d6ecb143a8a20e1658b0d6a2d77ea8126f", # idl.tmbundle
 | 
			
		||||
    "9dafd4e2a79cb13a6793b93877a254bc4d351e74", # sublime-text-ox
 | 
			
		||||
    "8e111741d97ba2e27b3d18a309d426b4a37e604f", # sublime-varnish
 | 
			
		||||
    "23d2538e33ce62d58abda2c039364b92f64ea6bc", # sublime-angelscript
 | 
			
		||||
    "53714285caad3c480ebd248c490509695d10404b", # atom-language-julia
 | 
			
		||||
  ].freeze
 | 
			
		||||
 | 
			
		||||
  # List of allowed SPDX license names
 | 
			
		||||
@@ -90,34 +91,27 @@ class TestGrammars < Minitest::Test
 | 
			
		||||
      message << unlisted_submodules.sort.join("\n")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    assert nonexistent_submodules.empty? && unlisted_submodules.empty?, message
 | 
			
		||||
    assert nonexistent_submodules.empty? && unlisted_submodules.empty?, message.sub(/\.\Z/, "")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_local_scopes_are_in_sync
 | 
			
		||||
    actual = YAML.load(`"#{File.join(ROOT, "script", "convert-grammars")}" --output - --no-install --no-remote`)
 | 
			
		||||
    assert $?.success?, "script/convert-grammars failed"
 | 
			
		||||
 | 
			
		||||
    # We're not checking remote grammars. That can take a long time and make CI
 | 
			
		||||
    # flaky if network conditions are poor.
 | 
			
		||||
    @grammars.delete_if { |k, v| k.start_with?("http:", "https:") }
 | 
			
		||||
 | 
			
		||||
    @grammars.each do |k, v|
 | 
			
		||||
      assert_equal v, actual[k], "The scopes listed for #{k} in grammars.yml don't match the scopes found in that repository"
 | 
			
		||||
    end
 | 
			
		||||
  def test_readme_file_is_in_sync
 | 
			
		||||
    current_data = File.read("#{ROOT}/vendor/README.md").to_s.sub(/\A.+?<!--.+?-->\n/ms, "")
 | 
			
		||||
    updated_data = `script/list-grammars --print`
 | 
			
		||||
    assert_equal current_data, updated_data, "Grammar list is out-of-date. Run `script/list-grammars`"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_submodules_have_recognized_licenses
 | 
			
		||||
    unrecognized = submodule_licenses.select { |k,v| v.nil? && Licensee::FSProject.new(k).license_file }
 | 
			
		||||
    unrecognized.reject! { |k,v| PROJECT_WHITELIST.include?(k) }
 | 
			
		||||
    message = "The following submodules have unrecognized licenses:\n* #{unrecognized.keys.join("\n* ")}\n"
 | 
			
		||||
    message << "Please ensure that the project's LICENSE file contains the full text of the license."
 | 
			
		||||
    message << "Please ensure that the project's LICENSE file contains the full text of the license"
 | 
			
		||||
    assert_equal Hash.new, unrecognized, message
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_submodules_have_licenses
 | 
			
		||||
    unlicensed = submodule_licenses.select { |k,v| v.nil? }.reject { |k,v| PROJECT_WHITELIST.include?(k) }
 | 
			
		||||
    message = "The following submodules don't have licenses:\n* #{unlicensed.keys.join("\n* ")}\n"
 | 
			
		||||
    message << "Please ensure that the project has a LICENSE file, and that the LICENSE file contains the full text of the license."
 | 
			
		||||
    message << "Please ensure that the project has a LICENSE file, and that the LICENSE file contains the full text of the license"
 | 
			
		||||
    assert_equal Hash.new, unlicensed, message
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@@ -127,14 +121,14 @@ class TestGrammars < Minitest::Test
 | 
			
		||||
                                                   HASH_WHITELIST.include?(v) }
 | 
			
		||||
                                   .map { |k,v| "#{k}: #{v}"}
 | 
			
		||||
    message = "The following submodules have unapproved licenses:\n* #{unapproved.join("\n* ")}\n"
 | 
			
		||||
    message << "The license must be added to the LICENSE_WHITELIST in /test/test_grammars.rb once approved."
 | 
			
		||||
    message << "The license must be added to the LICENSE_WHITELIST in /test/test_grammars.rb once approved"
 | 
			
		||||
    assert_equal [], unapproved, message
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_whitelisted_submodules_dont_have_licenses
 | 
			
		||||
    licensed = submodule_licenses.reject { |k,v| v.nil? }.select { |k,v| PROJECT_WHITELIST.include?(k) }
 | 
			
		||||
    message = "The following whitelisted submodules have a license:\n* #{licensed.keys.join("\n* ")}\n"
 | 
			
		||||
    message << "Please remove them from the project whitelist."
 | 
			
		||||
    message << "Please remove them from the project whitelist"
 | 
			
		||||
    assert_equal Hash.new, licensed, message
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@@ -142,7 +136,7 @@ class TestGrammars < Minitest::Test
 | 
			
		||||
    used_hashes = submodule_licenses.values.reject { |v| v.nil? || LICENSE_WHITELIST.include?(v) }
 | 
			
		||||
    unused_hashes = HASH_WHITELIST - used_hashes
 | 
			
		||||
    message = "The following whitelisted license hashes are unused:\n* #{unused_hashes.join("\n* ")}\n"
 | 
			
		||||
    message << "Please remove them from the hash whitelist."
 | 
			
		||||
    message << "Please remove them from the hash whitelist"
 | 
			
		||||
    assert_equal Array.new, unused_hashes, message
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
require_relative "./helper"
 | 
			
		||||
 | 
			
		||||
class TestHeuristcs < Minitest::Test
 | 
			
		||||
class TestHeuristics < Minitest::Test
 | 
			
		||||
  include Linguist
 | 
			
		||||
 | 
			
		||||
  def fixture(name)
 | 
			
		||||
@@ -44,6 +44,13 @@ class TestHeuristcs < Minitest::Test
 | 
			
		||||
    assert_equal Language["Objective-C"], match
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_as_by_heuristics
 | 
			
		||||
    assert_heuristics({
 | 
			
		||||
      "ActionScript" => all_fixtures("ActionScript", "*.as"),
 | 
			
		||||
      "AngelScript" => all_fixtures("AngelScript", "*.as")
 | 
			
		||||
    })
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Candidate languages = ["AGS Script", "AsciiDoc", "Public Key"]
 | 
			
		||||
  def test_asc_by_heuristics
 | 
			
		||||
    assert_heuristics({
 | 
			
		||||
@@ -230,14 +237,6 @@ class TestHeuristcs < Minitest::Test
 | 
			
		||||
    })
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Candidate languages = ["Pod", "Perl"]
 | 
			
		||||
  def test_pod_by_heuristics
 | 
			
		||||
    assert_heuristics({
 | 
			
		||||
      "Perl" => all_fixtures("Perl", "*.pod"),
 | 
			
		||||
      "Pod" => all_fixtures("Pod", "*.pod")
 | 
			
		||||
    })
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Candidate languages = ["IDL", "Prolog", "QMake", "INI"]
 | 
			
		||||
  def test_pro_by_heuristics
 | 
			
		||||
    assert_heuristics({
 | 
			
		||||
 
 | 
			
		||||
@@ -470,5 +470,7 @@ class TestLanguage < Minitest::Test
 | 
			
		||||
 | 
			
		||||
  def test_non_crash_on_comma
 | 
			
		||||
    assert_nil Language[',']
 | 
			
		||||
    assert_nil Language.find_by_name(',')
 | 
			
		||||
    assert_nil Language.find_by_alias(',')
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								tools/grammars/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tools/grammars/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
/vendor
 | 
			
		||||
							
								
								
									
										35
									
								
								tools/grammars/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								tools/grammars/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
FROM golang:1.9.2
 | 
			
		||||
 | 
			
		||||
RUN apt-get update
 | 
			
		||||
RUN apt-get upgrade -y
 | 
			
		||||
RUN apt-get install -y curl gnupg
 | 
			
		||||
 | 
			
		||||
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
 | 
			
		||||
RUN apt-get install -y nodejs
 | 
			
		||||
RUN npm install -g season
 | 
			
		||||
 | 
			
		||||
RUN apt-get install -y cmake
 | 
			
		||||
RUN cd /tmp && git clone https://github.com/vmg/pcre
 | 
			
		||||
RUN mkdir -p /tmp/pcre/build && cd /tmp/pcre/build && \
 | 
			
		||||
	cmake .. \
 | 
			
		||||
		-DPCRE_SUPPORT_JIT=ON \
 | 
			
		||||
		-DPCRE_SUPPORT_UTF=ON \
 | 
			
		||||
		-DPCRE_SUPPORT_UNICODE_PROPERTIES=ON \
 | 
			
		||||
		-DBUILD_SHARED_LIBS=OFF \
 | 
			
		||||
		-DCMAKE_C_FLAGS="-fPIC $(EXTRA_PCRE_CFLAGS)" \
 | 
			
		||||
		-DCMAKE_BUILD_TYPE=RelWithDebInfo \
 | 
			
		||||
		-DPCRE_BUILD_PCRECPP=OFF \
 | 
			
		||||
		-DPCRE_BUILD_PCREGREP=OFF \
 | 
			
		||||
		-DPCRE_BUILD_TESTS=OFF \
 | 
			
		||||
		-G "Unix Makefiles" && \
 | 
			
		||||
    make && make install
 | 
			
		||||
RUN rm -rf /tmp/pcre
 | 
			
		||||
 | 
			
		||||
RUN go get -u github.com/golang/dep/cmd/dep
 | 
			
		||||
WORKDIR /go/src/github.com/github/linguist/tools/grammars
 | 
			
		||||
COPY . .
 | 
			
		||||
 | 
			
		||||
RUN dep ensure
 | 
			
		||||
RUN go install ./cmd/grammar-compiler
 | 
			
		||||
 | 
			
		||||
ENTRYPOINT ["grammar-compiler"]
 | 
			
		||||
							
								
								
									
										51
									
								
								tools/grammars/Gopkg.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								tools/grammars/Gopkg.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "github.com/golang/protobuf"
 | 
			
		||||
  packages = ["proto"]
 | 
			
		||||
  revision = "1e59b77b52bf8e4b449a57e6f79f21226d571845"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "github.com/groob/plist"
 | 
			
		||||
  packages = ["."]
 | 
			
		||||
  revision = "7b367e0aa692e62a223e823f3288c0c00f519a36"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  name = "github.com/mattn/go-runewidth"
 | 
			
		||||
  packages = ["."]
 | 
			
		||||
  revision = "9e777a8366cce605130a531d2cd6363d07ad7317"
 | 
			
		||||
  version = "v0.0.2"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "github.com/mitchellh/mapstructure"
 | 
			
		||||
  packages = ["."]
 | 
			
		||||
  revision = "06020f85339e21b2478f756a78e295255ffa4d6a"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  name = "github.com/urfave/cli"
 | 
			
		||||
  packages = ["."]
 | 
			
		||||
  revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1"
 | 
			
		||||
  version = "v1.20.0"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  name = "gopkg.in/cheggaaa/pb.v1"
 | 
			
		||||
  packages = ["."]
 | 
			
		||||
  revision = "657164d0228d6bebe316fdf725c69f131a50fb10"
 | 
			
		||||
  version = "v1.0.18"
 | 
			
		||||
 | 
			
		||||
[[projects]]
 | 
			
		||||
  branch = "v2"
 | 
			
		||||
  name = "gopkg.in/yaml.v2"
 | 
			
		||||
  packages = ["."]
 | 
			
		||||
  revision = "287cf08546ab5e7e37d55a84f7ed3fd1db036de5"
 | 
			
		||||
 | 
			
		||||
[solve-meta]
 | 
			
		||||
  analyzer-name = "dep"
 | 
			
		||||
  analyzer-version = 1
 | 
			
		||||
  inputs-digest = "ba2e3150d728692b49e3e2d652b6ea23db82777c340e0c432cd4af6f0eef9f55"
 | 
			
		||||
  solver-name = "gps-cdcl"
 | 
			
		||||
  solver-version = 1
 | 
			
		||||
							
								
								
									
										23
									
								
								tools/grammars/Gopkg.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tools/grammars/Gopkg.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
[[constraint]]
 | 
			
		||||
  branch = "v2"
 | 
			
		||||
  name = "gopkg.in/yaml.v2"
 | 
			
		||||
 | 
			
		||||
[[constraint]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "github.com/groob/plist"
 | 
			
		||||
 | 
			
		||||
[[constraint]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "github.com/golang/protobuf"
 | 
			
		||||
 | 
			
		||||
[[constraint]]
 | 
			
		||||
  branch = "master"
 | 
			
		||||
  name = "github.com/mitchellh/mapstructure"
 | 
			
		||||
 | 
			
		||||
[[constraint]]
 | 
			
		||||
  name = "gopkg.in/cheggaaa/pb.v1"
 | 
			
		||||
  version = "1.0.18"
 | 
			
		||||
 | 
			
		||||
[[constraint]]
 | 
			
		||||
  name = "github.com/urfave/cli"
 | 
			
		||||
  version = "1.20.0"
 | 
			
		||||
							
								
								
									
										120
									
								
								tools/grammars/cmd/grammar-compiler/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								tools/grammars/cmd/grammar-compiler/main.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/github/linguist/tools/grammars/compiler"
 | 
			
		||||
	"github.com/urfave/cli"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func cwd() string {
 | 
			
		||||
	cwd, _ := os.Getwd()
 | 
			
		||||
	return cwd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func wrap(err error) error {
 | 
			
		||||
	return cli.NewExitError(err, 255)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	app := cli.NewApp()
 | 
			
		||||
	app.Name = "Linguist Grammars Compiler"
 | 
			
		||||
	app.Usage = "Compile user-submitted grammars and check them for errors"
 | 
			
		||||
 | 
			
		||||
	app.Flags = []cli.Flag{
 | 
			
		||||
		cli.StringFlag{
 | 
			
		||||
			Name:  "linguist-path",
 | 
			
		||||
			Value: cwd(),
 | 
			
		||||
			Usage: "path to Linguist root",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	app.Commands = []cli.Command{
 | 
			
		||||
		{
 | 
			
		||||
			Name:  "add",
 | 
			
		||||
			Usage: "add a new grammar source",
 | 
			
		||||
			Flags: []cli.Flag{
 | 
			
		||||
				cli.BoolFlag{
 | 
			
		||||
					Name:  "force, f",
 | 
			
		||||
					Usage: "ignore compilation errors",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Action: func(c *cli.Context) error {
 | 
			
		||||
				conv, err := compiler.NewConverter(c.String("linguist-path"))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return wrap(err)
 | 
			
		||||
				}
 | 
			
		||||
				if err := conv.AddGrammar(c.Args().First()); err != nil {
 | 
			
		||||
					if !c.Bool("force") {
 | 
			
		||||
						return wrap(err)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if err := conv.WriteGrammarList(); err != nil {
 | 
			
		||||
					return wrap(err)
 | 
			
		||||
				}
 | 
			
		||||
				return nil
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Name:  "update",
 | 
			
		||||
			Usage: "update grammars.yml with the contents of the grammars library",
 | 
			
		||||
			Flags: []cli.Flag{
 | 
			
		||||
				cli.BoolFlag{
 | 
			
		||||
					Name:  "force, f",
 | 
			
		||||
					Usage: "write grammars.yml even if grammars fail to compile",
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			Action: func(c *cli.Context) error {
 | 
			
		||||
				conv, err := compiler.NewConverter(c.String("linguist-path"))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return wrap(err)
 | 
			
		||||
				}
 | 
			
		||||
				if err := conv.ConvertGrammars(true); err != nil {
 | 
			
		||||
					return wrap(err)
 | 
			
		||||
				}
 | 
			
		||||
				if err := conv.Report(); err != nil {
 | 
			
		||||
					if !c.Bool("force") {
 | 
			
		||||
						return wrap(err)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if err := conv.WriteGrammarList(); err != nil {
 | 
			
		||||
					return wrap(err)
 | 
			
		||||
				}
 | 
			
		||||
				return nil
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			Name:  "compile",
 | 
			
		||||
			Usage: "convert the grammars from the library",
 | 
			
		||||
			Flags: []cli.Flag{
 | 
			
		||||
				cli.StringFlag{Name: "proto-out, P"},
 | 
			
		||||
				cli.StringFlag{Name: "out, o"},
 | 
			
		||||
			},
 | 
			
		||||
			Action: func(c *cli.Context) error {
 | 
			
		||||
				conv, err := compiler.NewConverter(c.String("linguist-path"))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return cli.NewExitError(err, 1)
 | 
			
		||||
				}
 | 
			
		||||
				if err := conv.ConvertGrammars(false); err != nil {
 | 
			
		||||
					return cli.NewExitError(err, 1)
 | 
			
		||||
				}
 | 
			
		||||
				if out := c.String("proto-out"); out != "" {
 | 
			
		||||
					if err := conv.WriteProto(out); err != nil {
 | 
			
		||||
						return cli.NewExitError(err, 1)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if out := c.String("out"); out != "" {
 | 
			
		||||
					if err := conv.WriteJSON(out); err != nil {
 | 
			
		||||
						return cli.NewExitError(err, 1)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if err := conv.Report(); err != nil {
 | 
			
		||||
					return wrap(err)
 | 
			
		||||
				}
 | 
			
		||||
				return nil
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	app.Run(os.Args)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										261
									
								
								tools/grammars/compiler/converter.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								tools/grammars/compiler/converter.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,261 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	grammar "github.com/github/linguist/tools/grammars/proto"
 | 
			
		||||
	"github.com/golang/protobuf/proto"
 | 
			
		||||
	pb "gopkg.in/cheggaaa/pb.v1"
 | 
			
		||||
	yaml "gopkg.in/yaml.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Converter struct {
 | 
			
		||||
	root string
 | 
			
		||||
 | 
			
		||||
	modified bool
 | 
			
		||||
	grammars map[string][]string
 | 
			
		||||
	Loaded   map[string]*Repository
 | 
			
		||||
 | 
			
		||||
	progress *pb.ProgressBar
 | 
			
		||||
	wg       sync.WaitGroup
 | 
			
		||||
	queue    chan string
 | 
			
		||||
	mu       sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conv *Converter) Load(src string) *Repository {
 | 
			
		||||
	if strings.HasPrefix(src, "http://") || strings.HasPrefix(src, "https://") {
 | 
			
		||||
		return LoadFromURL(src)
 | 
			
		||||
	}
 | 
			
		||||
	return LoadFromFilesystem(conv.root, src)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conv *Converter) work() {
 | 
			
		||||
	for source := range conv.queue {
 | 
			
		||||
		repo := conv.Load(source)
 | 
			
		||||
 | 
			
		||||
		conv.mu.Lock()
 | 
			
		||||
		conv.Loaded[source] = repo
 | 
			
		||||
		conv.mu.Unlock()
 | 
			
		||||
 | 
			
		||||
		conv.progress.Increment()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	conv.wg.Done()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conv *Converter) tmpScopes() map[string]bool {
 | 
			
		||||
	scopes := make(map[string]bool)
 | 
			
		||||
	for _, ary := range conv.grammars {
 | 
			
		||||
		for _, s := range ary {
 | 
			
		||||
			scopes[s] = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return scopes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conv *Converter) AddGrammar(source string) error {
 | 
			
		||||
	repo := conv.Load(source)
 | 
			
		||||
	if len(repo.Files) == 0 {
 | 
			
		||||
		return fmt.Errorf("source '%s' contains no grammar files", source)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	conv.grammars[source] = repo.Scopes()
 | 
			
		||||
	conv.modified = true
 | 
			
		||||
 | 
			
		||||
	knownScopes := conv.tmpScopes()
 | 
			
		||||
	repo.FixRules(knownScopes)
 | 
			
		||||
 | 
			
		||||
	if len(repo.Errors) > 0 {
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "The new grammar %s contains %d errors:\n",
 | 
			
		||||
			repo, len(repo.Errors))
 | 
			
		||||
		for _, err := range repo.Errors {
 | 
			
		||||
			fmt.Fprintf(os.Stderr, "    - %s\n", err)
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "\n")
 | 
			
		||||
		return fmt.Errorf("failed to compile the given grammar")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Printf("OK! added grammar source '%s'\n", source)
 | 
			
		||||
	for scope := range repo.Files {
 | 
			
		||||
		fmt.Printf("\tnew scope: %s\n", scope)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conv *Converter) AllScopes() map[string]bool {
 | 
			
		||||
	// Map from scope -> Repository first to error check
 | 
			
		||||
	// possible duplicates
 | 
			
		||||
	allScopes := make(map[string]*Repository)
 | 
			
		||||
	for _, repo := range conv.Loaded {
 | 
			
		||||
		for scope := range repo.Files {
 | 
			
		||||
			if original := allScopes[scope]; original != nil {
 | 
			
		||||
				repo.Fail(&DuplicateScopeError{original, scope})
 | 
			
		||||
			} else {
 | 
			
		||||
				allScopes[scope] = repo
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Convert to scope -> bool
 | 
			
		||||
	scopes := make(map[string]bool)
 | 
			
		||||
	for s := range allScopes {
 | 
			
		||||
		scopes[s] = true
 | 
			
		||||
	}
 | 
			
		||||
	return scopes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conv *Converter) ConvertGrammars(update bool) error {
 | 
			
		||||
	conv.Loaded = make(map[string]*Repository)
 | 
			
		||||
	conv.queue = make(chan string, 128)
 | 
			
		||||
 | 
			
		||||
	conv.progress = pb.New(len(conv.grammars))
 | 
			
		||||
	conv.progress.Start()
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < runtime.NumCPU(); i++ {
 | 
			
		||||
		conv.wg.Add(1)
 | 
			
		||||
		go conv.work()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for src := range conv.grammars {
 | 
			
		||||
		conv.queue <- src
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	close(conv.queue)
 | 
			
		||||
	conv.wg.Wait()
 | 
			
		||||
 | 
			
		||||
	done := fmt.Sprintf("done! processed %d grammars\n", len(conv.Loaded))
 | 
			
		||||
	conv.progress.FinishPrint(done)
 | 
			
		||||
 | 
			
		||||
	if update {
 | 
			
		||||
		conv.grammars = make(map[string][]string)
 | 
			
		||||
		conv.modified = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	knownScopes := conv.AllScopes()
 | 
			
		||||
 | 
			
		||||
	for source, repo := range conv.Loaded {
 | 
			
		||||
		repo.FixRules(knownScopes)
 | 
			
		||||
 | 
			
		||||
		if update {
 | 
			
		||||
			conv.grammars[source] = repo.Scopes()
 | 
			
		||||
		} else {
 | 
			
		||||
			expected := conv.grammars[source]
 | 
			
		||||
			repo.CompareScopes(expected)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conv *Converter) WriteProto(path string) error {
 | 
			
		||||
	library := grammar.Library{
 | 
			
		||||
		Grammars: make(map[string]*grammar.Rule),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, repo := range conv.Loaded {
 | 
			
		||||
		for scope, file := range repo.Files {
 | 
			
		||||
			library.Grammars[scope] = file.Rule
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pb, err := proto.Marshal(&library)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ioutil.WriteFile(path, pb, 0666)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conv *Converter) writeJSONFile(path string, rule *grammar.Rule) error {
 | 
			
		||||
	j, err := os.Create(path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer j.Close()
 | 
			
		||||
 | 
			
		||||
	enc := json.NewEncoder(j)
 | 
			
		||||
	enc.SetIndent("", "  ")
 | 
			
		||||
	return enc.Encode(rule)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conv *Converter) WriteJSON(rulePath string) error {
 | 
			
		||||
	if err := os.MkdirAll(rulePath, os.ModePerm); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, repo := range conv.Loaded {
 | 
			
		||||
		for scope, file := range repo.Files {
 | 
			
		||||
			p := path.Join(rulePath, scope+".json")
 | 
			
		||||
			if err := conv.writeJSONFile(p, file.Rule); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conv *Converter) WriteGrammarList() error {
 | 
			
		||||
	if !conv.modified {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	outyml, err := yaml.Marshal(conv.grammars)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ymlpath := path.Join(conv.root, "grammars.yml")
 | 
			
		||||
	return ioutil.WriteFile(ymlpath, outyml, 0666)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (conv *Converter) Report() error {
 | 
			
		||||
	var failed []*Repository
 | 
			
		||||
	for _, repo := range conv.Loaded {
 | 
			
		||||
		if len(repo.Errors) > 0 {
 | 
			
		||||
			failed = append(failed, repo)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sort.Slice(failed, func(i, j int) bool {
 | 
			
		||||
		return failed[i].Source < failed[j].Source
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	total := 0
 | 
			
		||||
	for _, repo := range failed {
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "- [ ] %s (%d errors)\n", repo, len(repo.Errors))
 | 
			
		||||
		for _, err := range repo.Errors {
 | 
			
		||||
			fmt.Fprintf(os.Stderr, "    - [ ] %s\n", err)
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "\n")
 | 
			
		||||
		total += len(repo.Errors)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if total > 0 {
 | 
			
		||||
		return fmt.Errorf("the grammar library contains %d errors", total)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewConverter(root string) (*Converter, error) {
 | 
			
		||||
	yml, err := ioutil.ReadFile(path.Join(root, "grammars.yml"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	conv := &Converter{root: root}
 | 
			
		||||
 | 
			
		||||
	if err := yaml.Unmarshal(yml, &conv.grammars); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return conv, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								tools/grammars/compiler/cson.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tools/grammars/compiler/cson.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ConvertCSON(data []byte) ([]byte, error) {
 | 
			
		||||
	stdin := bytes.NewBuffer(data)
 | 
			
		||||
	stdout := &bytes.Buffer{}
 | 
			
		||||
 | 
			
		||||
	cmd := exec.Command("csonc")
 | 
			
		||||
	cmd.Stdin = stdin
 | 
			
		||||
	cmd.Stdout = stdout
 | 
			
		||||
 | 
			
		||||
	if err := cmd.Run(); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return stdout.Bytes(), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								tools/grammars/compiler/data.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								tools/grammars/compiler/data.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
var GrammarAliases = map[string]string{
 | 
			
		||||
	"source.erb":         "text.html.erb",
 | 
			
		||||
	"source.cpp":         "source.c++",
 | 
			
		||||
	"source.less":        "source.css.less",
 | 
			
		||||
	"text.html.markdown": "source.gfm",
 | 
			
		||||
	"text.md":            "source.gfm",
 | 
			
		||||
	"source.php":         "text.html.php",
 | 
			
		||||
	"text.plain":         "",
 | 
			
		||||
	"source.asciidoc":    "text.html.asciidoc",
 | 
			
		||||
	"source.perl6":       "source.perl6fe",
 | 
			
		||||
	"source.css.scss":    "source.scss",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var KnownFields = map[string]bool{
 | 
			
		||||
	"comment":            true,
 | 
			
		||||
	"uuid":               true,
 | 
			
		||||
	"author":             true,
 | 
			
		||||
	"comments":           true,
 | 
			
		||||
	"macros":             true,
 | 
			
		||||
	"fileTypes":          true,
 | 
			
		||||
	"firstLineMatch":     true,
 | 
			
		||||
	"keyEquivalent":      true,
 | 
			
		||||
	"foldingStopMarker":  true,
 | 
			
		||||
	"foldingStartMarker": true,
 | 
			
		||||
	"foldingEndMarker":   true,
 | 
			
		||||
	"limitLineLength":    true,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										85
									
								
								tools/grammars/compiler/errors.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								tools/grammars/compiler/errors.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
import "strings"
 | 
			
		||||
 | 
			
		||||
type ConversionError struct {
 | 
			
		||||
	Path string
 | 
			
		||||
	Err  error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err *ConversionError) Error() string {
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"Grammar conversion failed. File `%s` failed to parse: %s",
 | 
			
		||||
		err.Path, err.Err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type DuplicateScopeError struct {
 | 
			
		||||
	Original  *Repository
 | 
			
		||||
	Duplicate string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err *DuplicateScopeError) Error() string {
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"Duplicate scope in repository: scope `%s` was already defined in %s",
 | 
			
		||||
		err.Duplicate, err.Original)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type MissingScopeError struct {
 | 
			
		||||
	Scope string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err *MissingScopeError) Error() string {
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"Missing scope in repository: `%s` is listed in grammars.yml but cannot be found",
 | 
			
		||||
		err.Scope)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type UnexpectedScopeError struct {
 | 
			
		||||
	File  *LoadedFile
 | 
			
		||||
	Scope string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err *UnexpectedScopeError) Error() string {
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"Unexpected scope in repository: `%s` declared in %s was not listed in grammars.yml",
 | 
			
		||||
		err.Scope, err.File)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type MissingIncludeError struct {
 | 
			
		||||
	File    *LoadedFile
 | 
			
		||||
	Include string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err *MissingIncludeError) Error() string {
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"Missing include in grammar: %s attempts to include `%s` but the scope cannot be found",
 | 
			
		||||
		err.File, err.Include)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type UnknownKeysError struct {
 | 
			
		||||
	File *LoadedFile
 | 
			
		||||
	Keys []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err *UnknownKeysError) Error() string {
 | 
			
		||||
	var keys []string
 | 
			
		||||
	for _, k := range err.Keys {
 | 
			
		||||
		keys = append(keys, fmt.Sprintf("`%s`", k))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"Unknown keys in grammar: %s contains invalid keys (%s)",
 | 
			
		||||
		err.File, strings.Join(keys, ", "))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type InvalidRegexError struct {
 | 
			
		||||
	File *LoadedFile
 | 
			
		||||
	Err  error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err *InvalidRegexError) Error() string {
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"Invalid regex in grammar: %s contains a malformed regex (%s)",
 | 
			
		||||
		err.File, err.Err)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										124
									
								
								tools/grammars/compiler/loader.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								tools/grammars/compiler/loader.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	grammar "github.com/github/linguist/tools/grammars/proto"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type LoadedFile struct {
 | 
			
		||||
	Path string
 | 
			
		||||
	Rule *grammar.Rule
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *LoadedFile) String() string {
 | 
			
		||||
	return fmt.Sprintf("`%s` (in `%s`)", f.Rule.ScopeName, f.Path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Repository struct {
 | 
			
		||||
	Source   string
 | 
			
		||||
	Upstream string
 | 
			
		||||
	Files    map[string]*LoadedFile
 | 
			
		||||
	Errors   []error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newRepository(src string) *Repository {
 | 
			
		||||
	return &Repository{
 | 
			
		||||
		Source: src,
 | 
			
		||||
		Files:  make(map[string]*LoadedFile),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (repo *Repository) String() string {
 | 
			
		||||
	str := fmt.Sprintf("repository `%s`", repo.Source)
 | 
			
		||||
	if repo.Upstream != "" {
 | 
			
		||||
		str = str + fmt.Sprintf(" (from %s)", repo.Upstream)
 | 
			
		||||
	}
 | 
			
		||||
	return str
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (repo *Repository) Fail(err error) {
 | 
			
		||||
	repo.Errors = append(repo.Errors, err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (repo *Repository) AddFile(path string, rule *grammar.Rule, uk []string) {
 | 
			
		||||
	file := &LoadedFile{
 | 
			
		||||
		Path: path,
 | 
			
		||||
		Rule: rule,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	repo.Files[rule.ScopeName] = file
 | 
			
		||||
	if len(uk) > 0 {
 | 
			
		||||
		repo.Fail(&UnknownKeysError{file, uk})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toMap(slice []string) map[string]bool {
 | 
			
		||||
	m := make(map[string]bool)
 | 
			
		||||
	for _, s := range slice {
 | 
			
		||||
		m[s] = true
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (repo *Repository) CompareScopes(scopes []string) {
 | 
			
		||||
	expected := toMap(scopes)
 | 
			
		||||
 | 
			
		||||
	for scope, file := range repo.Files {
 | 
			
		||||
		if !expected[scope] {
 | 
			
		||||
			repo.Fail(&UnexpectedScopeError{file, scope})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for scope := range expected {
 | 
			
		||||
		if _, ok := repo.Files[scope]; !ok {
 | 
			
		||||
			repo.Fail(&MissingScopeError{scope})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (repo *Repository) FixRules(knownScopes map[string]bool) {
 | 
			
		||||
	for _, file := range repo.Files {
 | 
			
		||||
		w := walker{
 | 
			
		||||
			File:    file,
 | 
			
		||||
			Known:   knownScopes,
 | 
			
		||||
			Missing: make(map[string]bool),
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		w.walk(file.Rule)
 | 
			
		||||
		repo.Errors = append(repo.Errors, w.Errors...)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (repo *Repository) Scopes() (scopes []string) {
 | 
			
		||||
	for s := range repo.Files {
 | 
			
		||||
		scopes = append(scopes, s)
 | 
			
		||||
	}
 | 
			
		||||
	sort.Strings(scopes)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isValidGrammar(path string, info os.FileInfo) bool {
 | 
			
		||||
	if info.IsDir() {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dir := filepath.Dir(path)
 | 
			
		||||
	ext := filepath.Ext(path)
 | 
			
		||||
 | 
			
		||||
	switch strings.ToLower(ext) {
 | 
			
		||||
	case ".plist":
 | 
			
		||||
		return strings.HasSuffix(dir, "/Syntaxes")
 | 
			
		||||
	case ".tmlanguage", ".yaml-tmlanguage":
 | 
			
		||||
		return true
 | 
			
		||||
	case ".cson", ".json":
 | 
			
		||||
		return strings.HasSuffix(dir, "/grammars")
 | 
			
		||||
	default:
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										80
									
								
								tools/grammars/compiler/loader_fs.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								tools/grammars/compiler/loader_fs.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"path"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type fsLoader struct {
 | 
			
		||||
	*Repository
 | 
			
		||||
	abspath string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *fsLoader) findGrammars() (files []string, err error) {
 | 
			
		||||
	err = filepath.Walk(l.abspath,
 | 
			
		||||
		func(path string, info os.FileInfo, err error) error {
 | 
			
		||||
			if err == nil && isValidGrammar(path, info) {
 | 
			
		||||
				files = append(files, path)
 | 
			
		||||
			}
 | 
			
		||||
			return nil
 | 
			
		||||
		})
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *fsLoader) load() {
 | 
			
		||||
	grammars, err := l.findGrammars()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		l.Fail(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, path := range grammars {
 | 
			
		||||
		data, err := ioutil.ReadFile(path)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			l.Fail(err)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if rel, err := filepath.Rel(l.abspath, path); err == nil {
 | 
			
		||||
			path = rel
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		rule, unknown, err := ConvertProto(filepath.Ext(path), data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			l.Fail(&ConversionError{path, err})
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if _, ok := l.Files[rule.ScopeName]; ok {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		l.AddFile(path, rule, unknown)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func gitRemoteName(path string) (string, error) {
 | 
			
		||||
	remote, err := exec.Command("git", "-C", path, "remote", "get-url", "origin").Output()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return strings.TrimSpace(string(remote)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func LoadFromFilesystem(root, src string) *Repository {
 | 
			
		||||
	loader := fsLoader{
 | 
			
		||||
		Repository: newRepository(src),
 | 
			
		||||
		abspath:    path.Join(root, src),
 | 
			
		||||
	}
 | 
			
		||||
	loader.load()
 | 
			
		||||
 | 
			
		||||
	if ups, err := gitRemoteName(loader.abspath); err == nil {
 | 
			
		||||
		loader.Repository.Upstream = ups
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return loader.Repository
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										93
									
								
								tools/grammars/compiler/loader_url.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								tools/grammars/compiler/loader_url.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"archive/tar"
 | 
			
		||||
	"compress/gzip"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type urlLoader struct {
 | 
			
		||||
	*Repository
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *urlLoader) loadTarball(r io.Reader) {
 | 
			
		||||
	gzf, err := gzip.NewReader(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		l.Fail(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer gzf.Close()
 | 
			
		||||
 | 
			
		||||
	tarReader := tar.NewReader(gzf)
 | 
			
		||||
	for true {
 | 
			
		||||
		header, err := tarReader.Next()
 | 
			
		||||
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if err != io.EOF {
 | 
			
		||||
				l.Fail(err)
 | 
			
		||||
			}
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if isValidGrammar(header.Name, header.FileInfo()) {
 | 
			
		||||
			data, err := ioutil.ReadAll(tarReader)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				l.Fail(err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ext := filepath.Ext(header.Name)
 | 
			
		||||
			rule, unknown, err := ConvertProto(ext, data)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				l.Fail(&ConversionError{header.Name, err})
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if _, ok := l.Files[rule.ScopeName]; ok {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			l.AddFile(header.Name, rule, unknown)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *urlLoader) load() {
 | 
			
		||||
	res, err := http.Get(l.Source)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		l.Fail(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer res.Body.Close()
 | 
			
		||||
 | 
			
		||||
	if strings.HasSuffix(l.Source, ".tar.gz") {
 | 
			
		||||
		l.loadTarball(res.Body)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data, err := ioutil.ReadAll(res.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		l.Fail(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ext := filepath.Ext(l.Source)
 | 
			
		||||
	filename := filepath.Base(l.Source)
 | 
			
		||||
	rule, unknown, err := ConvertProto(ext, data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		l.Fail(&ConversionError{filename, err})
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l.AddFile(filename, rule, unknown)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func LoadFromURL(src string) *Repository {
 | 
			
		||||
	loader := urlLoader{newRepository(src)}
 | 
			
		||||
	loader.load()
 | 
			
		||||
	return loader.Repository
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								tools/grammars/compiler/pcre.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								tools/grammars/compiler/pcre.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/github/linguist/tools/grammars/pcre"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type replacement struct {
 | 
			
		||||
	pos int
 | 
			
		||||
	len int
 | 
			
		||||
	val string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fixRegex(re string) (string, bool) {
 | 
			
		||||
	var (
 | 
			
		||||
		replace     []replacement
 | 
			
		||||
		escape      = false
 | 
			
		||||
		hasBackRefs = false
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	for i, ch := range re {
 | 
			
		||||
		if escape {
 | 
			
		||||
			if ch == 'h' {
 | 
			
		||||
				replace = append(replace, replacement{i - 1, 2, "[[:xdigit:]]"})
 | 
			
		||||
			}
 | 
			
		||||
			if '0' <= ch && ch <= '9' {
 | 
			
		||||
				hasBackRefs = true
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		escape = !escape && ch == '\\'
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(replace) > 0 {
 | 
			
		||||
		reb := []byte(re)
 | 
			
		||||
		offset := 0
 | 
			
		||||
		for _, repl := range replace {
 | 
			
		||||
			reb = append(
 | 
			
		||||
				reb[:offset+repl.pos],
 | 
			
		||||
				append([]byte(repl.val), reb[offset+repl.pos+repl.len:]...)...)
 | 
			
		||||
			offset += len(repl.val) - repl.len
 | 
			
		||||
		}
 | 
			
		||||
		return string(reb), hasBackRefs
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return re, hasBackRefs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CheckPCRE(re string) (string, error) {
 | 
			
		||||
	hasBackRefs := false
 | 
			
		||||
 | 
			
		||||
	if re == "" {
 | 
			
		||||
		return "", nil
 | 
			
		||||
	}
 | 
			
		||||
	if len(re) > 32*1024 {
 | 
			
		||||
		return "", fmt.Errorf(
 | 
			
		||||
			"regex %s: definition too long (%d bytes)",
 | 
			
		||||
			pcre.RegexPP(re), len(re))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	re, hasBackRefs = fixRegex(re)
 | 
			
		||||
	if !hasBackRefs {
 | 
			
		||||
		if err := pcre.CheckRegexp(re, pcre.DefaultFlags); err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return re, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								tools/grammars/compiler/pcre_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								tools/grammars/compiler/pcre_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Test_fixRegex(t *testing.T) {
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		re   string
 | 
			
		||||
		want string
 | 
			
		||||
	}{
 | 
			
		||||
		{"foobar", "foobar"},
 | 
			
		||||
		{`testing\h`, "testing[[:xdigit:]]"},
 | 
			
		||||
		{`\htest`, `[[:xdigit:]]test`},
 | 
			
		||||
		{`abc\hdef`, `abc[[:xdigit:]]def`},
 | 
			
		||||
		{`\\\htest`, `\\[[:xdigit:]]test`},
 | 
			
		||||
		{`\\htest`, `\\htest`},
 | 
			
		||||
		{`\h\h\h\h`, `[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]`},
 | 
			
		||||
		{`abc\hdef\hghi\h`, `abc[[:xdigit:]]def[[:xdigit:]]ghi[[:xdigit:]]`},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		got, _ := fixRegex(tt.re)
 | 
			
		||||
		if got != tt.want {
 | 
			
		||||
			t.Errorf("fixRegex() got = %v, want %v", got, tt.want)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										96
									
								
								tools/grammars/compiler/proto.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								tools/grammars/compiler/proto.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	grammar "github.com/github/linguist/tools/grammars/proto"
 | 
			
		||||
	"github.com/groob/plist"
 | 
			
		||||
	"github.com/mitchellh/mapstructure"
 | 
			
		||||
	yaml "gopkg.in/yaml.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func looseDecoder(f reflect.Kind, t reflect.Kind, data interface{}) (interface{}, error) {
 | 
			
		||||
	dataVal := reflect.ValueOf(data)
 | 
			
		||||
	switch t {
 | 
			
		||||
	case reflect.Bool:
 | 
			
		||||
		switch f {
 | 
			
		||||
		case reflect.Bool:
 | 
			
		||||
			return dataVal.Bool(), nil
 | 
			
		||||
		case reflect.Float32, reflect.Float64:
 | 
			
		||||
			return (int(dataVal.Float()) != 0), nil
 | 
			
		||||
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
			
		||||
			return (dataVal.Int() != 0), nil
 | 
			
		||||
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
			
		||||
			return (dataVal.Uint() != 0), nil
 | 
			
		||||
		case reflect.String:
 | 
			
		||||
			switch dataVal.String() {
 | 
			
		||||
			case "1":
 | 
			
		||||
				return true, nil
 | 
			
		||||
			case "0":
 | 
			
		||||
				return false, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return data, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func filterUnusedKeys(keys []string) (out []string) {
 | 
			
		||||
	for _, k := range keys {
 | 
			
		||||
		parts := strings.Split(k, ".")
 | 
			
		||||
		field := parts[len(parts)-1]
 | 
			
		||||
		if !KnownFields[field] {
 | 
			
		||||
			out = append(out, k)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ConvertProto(ext string, data []byte) (*grammar.Rule, []string, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		raw map[string]interface{}
 | 
			
		||||
		out grammar.Rule
 | 
			
		||||
		err error
 | 
			
		||||
		md  mapstructure.Metadata
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	switch strings.ToLower(ext) {
 | 
			
		||||
	case ".plist", ".tmlanguage":
 | 
			
		||||
		err = plist.Unmarshal(data, &raw)
 | 
			
		||||
	case ".yaml-tmlanguage":
 | 
			
		||||
		err = yaml.Unmarshal(data, &raw)
 | 
			
		||||
	case ".cson":
 | 
			
		||||
		data, err = ConvertCSON(data)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			err = json.Unmarshal(data, &raw)
 | 
			
		||||
		}
 | 
			
		||||
	case ".json":
 | 
			
		||||
		err = json.Unmarshal(data, &raw)
 | 
			
		||||
	default:
 | 
			
		||||
		err = fmt.Errorf("grammars: unsupported extension '%s'", ext)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config := mapstructure.DecoderConfig{
 | 
			
		||||
		Result:     &out,
 | 
			
		||||
		Metadata:   &md,
 | 
			
		||||
		DecodeHook: looseDecoder,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	decoder, err := mapstructure.NewDecoder(&config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := decoder.Decode(raw); err != nil {
 | 
			
		||||
		return nil, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &out, filterUnusedKeys(md.Unused), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										79
									
								
								tools/grammars/compiler/walker.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								tools/grammars/compiler/walker.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
			
		||||
package compiler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	grammar "github.com/github/linguist/tools/grammars/proto"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (w *walker) checkInclude(rule *grammar.Rule) {
 | 
			
		||||
	include := rule.Include
 | 
			
		||||
 | 
			
		||||
	if include == "" || include[0] == '#' || include[0] == '$' {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if alias, ok := GrammarAliases[include]; ok {
 | 
			
		||||
		rule.Include = alias
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	include = strings.Split(include, "#")[0]
 | 
			
		||||
	ok := w.Known[include]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		if !w.Missing[include] {
 | 
			
		||||
			w.Missing[include] = true
 | 
			
		||||
			w.Errors = append(w.Errors, &MissingIncludeError{w.File, include})
 | 
			
		||||
		}
 | 
			
		||||
		rule.Include = ""
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) checkRegexps(rule *grammar.Rule) {
 | 
			
		||||
	check := func(re string) string {
 | 
			
		||||
		re2, err := CheckPCRE(re)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			w.Errors = append(w.Errors, &InvalidRegexError{w.File, err})
 | 
			
		||||
		}
 | 
			
		||||
		return re2
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rule.Match = check(rule.Match)
 | 
			
		||||
	rule.Begin = check(rule.Begin)
 | 
			
		||||
	rule.While = check(rule.While)
 | 
			
		||||
	rule.End = check(rule.End)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *walker) walk(rule *grammar.Rule) {
 | 
			
		||||
	w.checkInclude(rule)
 | 
			
		||||
	w.checkRegexps(rule)
 | 
			
		||||
 | 
			
		||||
	for _, rule := range rule.Patterns {
 | 
			
		||||
		w.walk(rule)
 | 
			
		||||
	}
 | 
			
		||||
	for _, rule := range rule.Captures {
 | 
			
		||||
		w.walk(rule)
 | 
			
		||||
	}
 | 
			
		||||
	for _, rule := range rule.BeginCaptures {
 | 
			
		||||
		w.walk(rule)
 | 
			
		||||
	}
 | 
			
		||||
	for _, rule := range rule.WhileCaptures {
 | 
			
		||||
		w.walk(rule)
 | 
			
		||||
	}
 | 
			
		||||
	for _, rule := range rule.EndCaptures {
 | 
			
		||||
		w.walk(rule)
 | 
			
		||||
	}
 | 
			
		||||
	for _, rule := range rule.Repository {
 | 
			
		||||
		w.walk(rule)
 | 
			
		||||
	}
 | 
			
		||||
	for _, rule := range rule.Injections {
 | 
			
		||||
		w.walk(rule)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type walker struct {
 | 
			
		||||
	File    *LoadedFile
 | 
			
		||||
	Known   map[string]bool
 | 
			
		||||
	Missing map[string]bool
 | 
			
		||||
	Errors  []error
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								tools/grammars/docker/build
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								tools/grammars/docker/build
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
set -ex
 | 
			
		||||
cd "$(dirname "$0")/.."
 | 
			
		||||
 | 
			
		||||
image=linguist/grammar-compiler
 | 
			
		||||
docker build -t $image .
 | 
			
		||||
 | 
			
		||||
if [ "$1" = "--push" ]; then
 | 
			
		||||
    docker push $image
 | 
			
		||||
fi
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user