summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ale_linters/cs/mcsc.vim2
-rw-r--r--ale_linters/cuda/nvcc.vim2
-rw-r--r--ale_linters/elm/make.vim9
-rw-r--r--ale_linters/erlang/erlc.vim2
-rw-r--r--ale_linters/thrift/thrift.vim2
-rw-r--r--ale_linters/verilog/verilator.vim2
-rw-r--r--autoload/ale/command.vim2
-rw-r--r--autoload/ale/engine.vim2
-rw-r--r--autoload/ale/handlers/haskell.vim2
-rw-r--r--autoload/ale/path.vim2
-rw-r--r--autoload/ale/util.vim19
-rw-r--r--doc/ale-development.txt3
-rw-r--r--plugin/ale.vim6
-rw-r--r--test/handler/test_elmmake_handler.vader201
-rwxr-xr-xtest/script/custom-linting-rules1
-rw-r--r--test/test_tmpdir_init.vader4
-rw-r--r--test/test_tmpdir_wrapper.vader13
-rw-r--r--test/vimrc4
18 files changed, 145 insertions, 133 deletions
diff --git a/ale_linters/cs/mcsc.vim b/ale_linters/cs/mcsc.vim
index 8a78d3b3..8e84620c 100644
--- a/ale_linters/cs/mcsc.vim
+++ b/ale_linters/cs/mcsc.vim
@@ -29,7 +29,7 @@ function! ale_linters#cs#mcsc#GetCommand(buffer) abort
\ : ''
" register temporary module target file with ale
- let l:out = tempname()
+ let l:out = ale#util#Tempname()
call ale#engine#ManageFile(a:buffer, l:out)
" The code is compiled as a module and the output is redirected to a
diff --git a/ale_linters/cuda/nvcc.vim b/ale_linters/cuda/nvcc.vim
index 7aaa5cc3..3764fe9d 100644
--- a/ale_linters/cuda/nvcc.vim
+++ b/ale_linters/cuda/nvcc.vim
@@ -10,7 +10,7 @@ endfunction
function! ale_linters#cuda#nvcc#GetCommand(buffer) abort
" Unused: use ale#util#nul_file
- " let l:output_file = tempname() . '.ii'
+ " let l:output_file = ale#util#Tempname() . '.ii'
" call ale#engine#ManageFile(a:buffer, l:output_file)
return ale#Escape(ale_linters#cuda#nvcc#GetExecutable(a:buffer))
diff --git a/ale_linters/elm/make.vim b/ale_linters/elm/make.vim
index cc14fe4e..d5bc19eb 100644
--- a/ale_linters/elm/make.vim
+++ b/ale_linters/elm/make.vim
@@ -128,14 +128,7 @@ function! ale_linters#elm#make#HandleElm018Line(line, output) abort
endfunction
function! ale_linters#elm#make#FileIsBuffer(path) abort
- let l:is_windows = has('win32')
- let l:temp_dir = l:is_windows ? $TMP : $TMPDIR
-
- if has('win32')
- return a:path[0:len(l:temp_dir) - 1] is? l:temp_dir
- else
- return a:path[0:len(l:temp_dir) - 1] is# l:temp_dir
- endif
+ return ale#path#IsTempName(a:path)
endfunction
function! ale_linters#elm#make#ParseMessage(message) abort
diff --git a/ale_linters/erlang/erlc.vim b/ale_linters/erlang/erlc.vim
index bddb175d..0bdb4dea 100644
--- a/ale_linters/erlang/erlc.vim
+++ b/ale_linters/erlang/erlc.vim
@@ -3,7 +3,7 @@
let g:ale_erlang_erlc_options = get(g:, 'ale_erlang_erlc_options', '')
function! ale_linters#erlang#erlc#GetCommand(buffer) abort
- let l:output_file = tempname()
+ let l:output_file = ale#util#Tempname()
call ale#engine#ManageFile(a:buffer, l:output_file)
return 'erlc -o ' . ale#Escape(l:output_file)
diff --git a/ale_linters/thrift/thrift.vim b/ale_linters/thrift/thrift.vim
index 2f62570a..741e80ab 100644
--- a/ale_linters/thrift/thrift.vim
+++ b/ale_linters/thrift/thrift.vim
@@ -20,7 +20,7 @@ function! ale_linters#thrift#thrift#GetCommand(buffer) abort
let l:generators = ['cpp']
endif
- let l:output_dir = tempname()
+ let l:output_dir = ale#util#Tempname()
call mkdir(l:output_dir)
call ale#engine#ManageDirectory(a:buffer, l:output_dir)
diff --git a/ale_linters/verilog/verilator.vim b/ale_linters/verilog/verilator.vim
index 6053da09..83d5f59d 100644
--- a/ale_linters/verilog/verilator.vim
+++ b/ale_linters/verilog/verilator.vim
@@ -7,7 +7,7 @@ if !exists('g:ale_verilog_verilator_options')
endif
function! ale_linters#verilog#verilator#GetCommand(buffer) abort
- let l:filename = tempname() . '_verilator_linted.v'
+ let l:filename = ale#util#Tempname() . '_verilator_linted.v'
" Create a special filename, so we can detect it in the handler.
call ale#engine#ManageFile(a:buffer, l:filename)
diff --git a/autoload/ale/command.vim b/autoload/ale/command.vim
index b4bf3794..543c9953 100644
--- a/autoload/ale/command.vim
+++ b/autoload/ale/command.vim
@@ -13,7 +13,7 @@ function! s:TemporaryFilename(buffer) abort
" Create a temporary filename, <temp_dir>/<original_basename>
" The file itself will not be created by this function.
- return tempname() . (has('win32') ? '\' : '/') . l:filename
+ return ale#util#Tempname() . (has('win32') ? '\' : '/') . l:filename
endfunction
" Given a command string, replace every...
diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim
index a64d8f9f..c644e63f 100644
--- a/autoload/ale/engine.vim
+++ b/autoload/ale/engine.vim
@@ -98,7 +98,7 @@ endfunction
" Create a new temporary directory and manage it in one go.
function! ale#engine#CreateDirectory(buffer) abort
- let l:temporary_directory = tempname()
+ let l:temporary_directory = ale#util#Tempname()
" Create the temporary directory for the file, unreadable by 'other'
" users.
call mkdir(l:temporary_directory, '', 0750)
diff --git a/autoload/ale/handlers/haskell.vim b/autoload/ale/handlers/haskell.vim
index 8a0d0013..9223b650 100644
--- a/autoload/ale/handlers/haskell.vim
+++ b/autoload/ale/handlers/haskell.vim
@@ -2,7 +2,7 @@
" Description: Error handling for the format GHC outputs.
" Remember the directory used for temporary files for Vim.
-let s:temp_dir = fnamemodify(tempname(), ':h')
+let s:temp_dir = fnamemodify(ale#util#Tempname(), ':h')
" Build part of a regular expression for matching ALE temporary filenames.
let s:temp_regex_prefix =
\ '\M'
diff --git a/autoload/ale/path.vim b/autoload/ale/path.vim
index 91832b35..45da3709 100644
--- a/autoload/ale/path.vim
+++ b/autoload/ale/path.vim
@@ -84,7 +84,7 @@ function! ale#path#IsAbsolute(filename) abort
return a:filename[:0] is# '/' || a:filename[1:2] is# ':\'
endfunction
-let s:temp_dir = ale#path#Simplify(fnamemodify(tempname(), ':h'))
+let s:temp_dir = ale#path#Simplify(fnamemodify(ale#util#Tempname(), ':h'))
" Given a filename, return 1 if the file represents some temporary file
" created by Vim.
diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim
index 267b0587..93b997ea 100644
--- a/autoload/ale/util.vim
+++ b/autoload/ale/util.vim
@@ -277,6 +277,25 @@ function! ale#util#InSandbox() abort
return 0
endfunction
+function! ale#util#Tempname() abort
+ let l:clear_tempdir = 0
+
+ if has('unix') && empty($TMPDIR)
+ let l:clear_tempdir = 1
+ let $TMPDIR = '/tmp'
+ endif
+
+ try
+ let l:name = tempname() " no-custom-checks
+ finally
+ if l:clear_tempdir
+ let $TMPDIR = ''
+ endif
+ endtry
+
+ return l:name
+endfunction
+
" Given a single line, or a List of lines, and a single pattern, or a List
" of patterns, return all of the matches for the lines(s) from the given
" patterns, using matchlist().
diff --git a/doc/ale-development.txt b/doc/ale-development.txt
index 841371c7..f97bdee4 100644
--- a/doc/ale-development.txt
+++ b/doc/ale-development.txt
@@ -111,6 +111,9 @@ these are reported with ALE's `custom-linting-rules` script. See
* Don't use the `shellescape()` function. It doesn't escape arguments properly
on Windows. Use `ale#Escape()` instead, which will avoid escaping where it
isn't needed, and generally escape arguments better on Windows.
+* Don't use the `tempname()` function. It doesn't work when `$TMPDIR` isn't
+ set. Use `ale#util#Tempname()` instead, which temporarily sets `$TMPDIR`
+ appropriately where needed.
Apply the following guidelines when writing Vader test files.
diff --git a/plugin/ale.vim b/plugin/ale.vim
index 16a40268..ad2639bb 100644
--- a/plugin/ale.vim
+++ b/plugin/ale.vim
@@ -35,12 +35,6 @@ endif
" Set this flag so that other plugins can use it, like airline.
let g:loaded_ale = 1
-" Set the TMPDIR environment variable if it is not set automatically.
-" This can automatically fix some environments.
-if has('unix') && empty($TMPDIR)
- let $TMPDIR = '/tmp'
-endif
-
" This global variable is used internally by ALE for tracking information for
" each buffer which linters are being run against.
let g:ale_buffer_info = {}
diff --git a/test/handler/test_elmmake_handler.vader b/test/handler/test_elmmake_handler.vader
index 41c9646f..f5906a8b 100644
--- a/test/handler/test_elmmake_handler.vader
+++ b/test/handler/test_elmmake_handler.vader
@@ -1,10 +1,7 @@
Before:
- let b:tmp = has('win32') ? substitute($TMP, '\\', '\\\\', 'g') : $TMPDIR
-
runtime ale_linters/elm/make.vim
After:
- unlet! b:tmp
unlet! g:config_error_lines
call ale#linter#Reset()
@@ -22,12 +19,12 @@ Execute(The elm-make handler should parse Elm 0.19 general problems correctly):
\ }
\ ],
\ ale_linters#elm#make#Handle(347, [
- \ '{
- \ "type": "error",
- \ "path": "' . b:tmp . '/Module.elm",
- \ "title": "UNKNOWN IMPORT",
- \ "message": ["error details\n\n", { "string": "styled details" }]
- \ }'
+ \ json_encode({
+ \ 'type': 'error',
+ \ 'path': ale#util#Tempname() . '/Module.elm',
+ \ 'title': 'UNKNOWN IMPORT',
+ \ 'message': ["error details\n\n", { 'string': 'styled details' }]
+ \ }),
\ ])
Execute(The elm-make handler should parse Elm 0.19 compilation errors correctly):
@@ -47,7 +44,7 @@ Execute(The elm-make handler should parse Elm 0.19 compilation errors correctly)
\ 'end_lnum': 407,
\ 'end_col': 17,
\ 'type': 'E',
- \ 'text': "error details 2",
+ \ 'text': 'error details 2',
\ },
\ {
\ 'lnum': 406,
@@ -55,35 +52,35 @@ Execute(The elm-make handler should parse Elm 0.19 compilation errors correctly)
\ 'end_lnum': 406,
\ 'end_col': 93,
\ 'type': 'E',
- \ 'text': "error details 3",
+ \ 'text': 'error details 3',
\ },
\ ],
\ ale_linters#elm#make#Handle(347, [
- \ '{
- \ "type": "compile-errors",
- \ "errors": [
+ \ json_encode({
+ \ 'type': 'compile-errors',
+ \ 'errors': [
\ {
- \ "path": "' . b:tmp . '/Module.elm",
- \ "problems": [
+ \ 'path': ale#util#Tempname() . '/Module.elm',
+ \ 'problems': [
\ {
- \ "title": "TYPE MISMATCH",
- \ "message": ["error details 1\n\n", { "string": "styled details" }],
- \ "region": { "start": { "line": 404, "column": 1 }, "end": { "line": 408, "column": 18 } }
+ \ 'title': 'TYPE MISMATCH',
+ \ 'message': ["error details 1\n\n", { 'string': 'styled details' }],
+ \ 'region': { 'start': { 'line': 404, 'column': 1 }, 'end': { 'line': 408, 'column': 18 } }
\ },
\ {
- \ "title": "TYPE MISMATCH",
- \ "message": ["error details 2"],
- \ "region": { "start": {"line": 406, "column": 5}, "end": {"line": 407, "column": 17 } }
+ \ 'title': 'TYPE MISMATCH',
+ \ 'message': ['error details 2'],
+ \ 'region': { 'start': {'line': 406, 'column': 5}, 'end': {'line': 407, 'column': 17 } }
\ },
\ {
- \ "title": "TYPE MISMATCH",
- \ "message": ["error details 3"],
- \ "region": { "start": { "line": 406, "column": 5}, "end": {"line": 406, "column": 93 } }
+ \ 'title': 'TYPE MISMATCH',
+ \ 'message': ['error details 3'],
+ \ 'region': { 'start': { 'line': 406, 'column': 5}, 'end': {'line': 406, 'column': 93 } }
\ }
\ ]
\ }
\ ]
- \ }'
+ \ }),
\ ])
Execute(The elm-make handler should handle errors in Elm 0.19 imported modules):
@@ -109,33 +106,33 @@ Execute(The elm-make handler should handle errors in Elm 0.19 imported modules):
\ },
\ ],
\ ale_linters#elm#make#Handle(347, [
- \ '{
- \ "type": "error",
- \ "path": "src/Module.elm",
- \ "title": "UNKNOWN IMPORT",
- \ "message": ["error details\n\n", { "string": "styled details" }]
- \ }',
- \ '{
- \ "type": "error",
- \ "path": null,
- \ "title": "UNKNOWN IMPORT",
- \ "message": ["error details\n\n", { "string": "styled details" }]
- \ }',
- \ '{
- \ "type": "compile-errors",
- \ "errors": [
+ \ json_encode({
+ \ 'type': 'error',
+ \ 'path': 'src/Module.elm',
+ \ 'title': 'UNKNOWN IMPORT',
+ \ 'message': ["error details\n\n", { 'string': 'styled details' }]
+ \ }),
+ \ json_encode({
+ \ 'type': 'error',
+ \ 'path': v:null,
+ \ 'title': 'UNKNOWN IMPORT',
+ \ 'message': ["error details\n\n", { 'string': 'styled details' }]
+ \ }),
+ \ json_encode({
+ \ 'type': 'compile-errors',
+ \ 'errors': [
\ {
- \ "path": "src/Module.elm",
- \ "problems": [
+ \ 'path': 'src/Module.elm',
+ \ 'problems': [
\ {
- \ "title": "TYPE MISMATCH",
- \ "message": ["error details\n\n", { "string": "styled details" }],
- \ "region": { "start": { "line": 404, "column": 1 }, "end": { "line": 408, "column": 18 } }
+ \ 'title': 'TYPE MISMATCH',
+ \ 'message': ["error details\n\n", { 'string': 'styled details' }],
+ \ 'region': { 'start': { 'line': 404, 'column': 1 }, 'end': { 'line': 408, 'column': 18 } }
\ }
\ ]
\ }
\ ]
- \ }'
+ \ }),
\ ])
@@ -182,45 +179,45 @@ Execute(The elm-make handler should parse Elm 0.18 compilation errors correctly)
\ },
\ ],
\ ale_linters#elm#make#Handle(347, [
- \ '[
+ \ json_encode([
\ {
- \ "tag": "unused import",
- \ "overview": "warning overview",
- \ "details": "warning details",
- \ "region": {"start": { "line": 33, "column": 1 }, "end": { "line": 33, "column": 19 } },
- \ "type": "warning",
- \ "file": "' . b:tmp . '/Module.elm"
+ \ 'tag': 'unused import',
+ \ 'overview': 'warning overview',
+ \ 'details': 'warning details',
+ \ 'region': {'start': { 'line': 33, 'column': 1 }, 'end': { 'line': 33, 'column': 19 } },
+ \ 'type': 'warning',
+ \ 'file': ale#util#Tempname() . '/Module.elm',
\ }
- \ ]',
- \ '[
+ \ ]),
+ \ json_encode([
\ {
- \ "tag": "TYPE MISMATCH",
- \ "overview": "error overview 1",
- \ "subregion": { "start": { "line": 406, "column": 5 }, "end": { "line": 408, "column": 18 } },
- \ "details": "error details 1",
- \ "region": { "start": { "line": 404, "column": 1 }, "end": { "line": 408, "column": 18 } },
- \ "type": "error",
- \ "file":"' . b:tmp . '/Module.elm"
+ \ 'tag': 'TYPE MISMATCH',
+ \ 'overview': 'error overview 1',
+ \ 'subregion': { 'start': { 'line': 406, 'column': 5 }, 'end': { 'line': 408, 'column': 18 } },
+ \ 'details': 'error details 1',
+ \ 'region': { 'start': { 'line': 404, 'column': 1 }, 'end': { 'line': 408, 'column': 18 } },
+ \ 'type': 'error',
+ \ 'file': ale#util#Tempname() . '/Module.elm',
\ },
\ {
- \ "tag": "TYPE MISMATCH",
- \ "overview": "error overview 2",
- \ "subregion": { "start": { "line": 407, "column": 12 }, "end": { "line": 407, "column": 17 } },
- \ "details": "error details 2",
- \ "region": { "start": { "line": 406, "column": 5}, "end": { "line": 407, "column": 17 } },
- \ "type":"error",
- \ "file":"' . b:tmp . '/Module.elm"
+ \ 'tag': 'TYPE MISMATCH',
+ \ 'overview': 'error overview 2',
+ \ 'subregion': { 'start': { 'line': 407, 'column': 12 }, 'end': { 'line': 407, 'column': 17 } },
+ \ 'details': 'error details 2',
+ \ 'region': { 'start': { 'line': 406, 'column': 5}, 'end': { 'line': 407, 'column': 17 } },
+ \ 'type':'error',
+ \ 'file': ale#util#Tempname() . '/Module.elm',
\ },
\ {
- \ "tag": "TYPE MISMATCH",
- \ "overview": "error overview 3",
- \ "subregion": { "start": { "line": 406, "column": 88 }, "end": { "line": 406, "column": 93 } },
- \ "details": "error details 3",
- \ "region": { "start": { "line": 406, "column": 5 }, "end": { "line": 406, "column": 93 } },
- \ "type":"error",
- \ "file":"' . b:tmp . '/Module.elm"
+ \ 'tag': 'TYPE MISMATCH',
+ \ 'overview': 'error overview 3',
+ \ 'subregion': { 'start': { 'line': 406, 'column': 88 }, 'end': { 'line': 406, 'column': 93 } },
+ \ 'details': 'error details 3',
+ \ 'region': { 'start': { 'line': 406, 'column': 5 }, 'end': { 'line': 406, 'column': 93 } },
+ \ 'type':'error',
+ \ 'file': ale#util#Tempname() . '/Module.elm',
\ }
- \ ]'
+ \ ]),
\ ])
Execute(The elm-make handler should handle errors in Elm 0.18 imported modules):
@@ -229,29 +226,29 @@ Execute(The elm-make handler should handle errors in Elm 0.18 imported modules):
\ {
\ 'lnum': 1,
\ 'type': 'E',
- \ 'text': "src/Module.elm:33 - error overview",
+ \ 'text': 'src/Module.elm:33 - error overview',
\ 'detail': "src/Module.elm:33 ----------\n\nerror overview\n\nerror details"
\ }
\ ],
\ ale_linters#elm#make#Handle(347, [
- \ '[
+ \ json_encode([
\ {
- \ "tag": "unused import",
- \ "overview": "warning overview",
- \ "details": "warning details",
- \ "region": {"start": { "line": 33, "column": 1 }, "end": { "line": 33, "column": 19 } },
- \ "type": "warning",
- \ "file": "src/Module.elm"
+ \ 'tag': 'unused import',
+ \ 'overview': 'warning overview',
+ \ 'details': 'warning details',
+ \ 'region': {'start': { 'line': 33, 'column': 1 }, 'end': { 'line': 33, 'column': 19 } },
+ \ 'type': 'warning',
+ \ 'file': 'src/Module.elm',
\ },
\ {
- \ "tag": "type error",
- \ "overview": "error overview",
- \ "details": "error details",
- \ "region": {"start": { "line": 33, "column": 1 }, "end": { "line": 33, "column": 19 } },
- \ "type": "error",
- \ "file": "src/Module.elm"
+ \ 'tag': 'type error',
+ \ 'overview': 'error overview',
+ \ 'details': 'error details',
+ \ 'region': {'start': { 'line': 33, 'column': 1 }, 'end': { 'line': 33, 'column': 19 } },
+ \ 'type': 'error',
+ \ 'file': 'src/Module.elm',
\ }
- \ ]',
+ \ ]),
\ ])
" Generic
@@ -275,21 +272,21 @@ Execute(The elm-make handler should put an error on the first line if a line can
\ },
\ ],
\ ale_linters#elm#make#Handle(347, [
- \ '{
- \ "type": "compile-errors",
- \ "errors": [
+ \ json_encode({
+ \ 'type': 'compile-errors',
+ \ 'errors': [
\ {
- \ "path": "' . b:tmp . '/Module.elm",
- \ "problems": [
+ \ 'path': ale#util#Tempname() . '/Module.elm',
+ \ 'problems': [
\ {
- \ "title": "TYPE MISMATCH",
- \ "message": ["error details 1\n\n", { "string": "styled details" }],
- \ "region": { "start": { "line": 404, "column": 1 }, "end": { "line": 408, "column": 18 } }
+ \ 'title': 'TYPE MISMATCH',
+ \ 'message': ["error details 1\n\n", { 'string': 'styled details' }],
+ \ 'region': { 'start': { 'line': 404, 'column': 1 }, 'end': { 'line': 408, 'column': 18 } }
\ }
\ ]
\ }
\ ]
- \ }',
+ \ }),
\ 'Not JSON',
\ 'Also not JSON',
\ ])
diff --git a/test/script/custom-linting-rules b/test/script/custom-linting-rules
index 0d1a0fd1..51cf5680 100755
--- a/test/script/custom-linting-rules
+++ b/test/script/custom-linting-rules
@@ -87,6 +87,7 @@ check_errors $'\t' 'Use four spaces, not tabs'
check_errors 'let g:ale_\w\+_\w\+_args =' 'Name your option g:ale_<filetype>_<lintername>_options instead'
check_errors 'shellescape(' 'Use ale#Escape instead of shellescape'
check_errors 'simplify(' 'Use ale#path#Simplify instead of simplify'
+check_errors 'tempname(' 'Use ale#util#Tempname instead of tempname'
check_errors "expand(['\"]%" "Use expand('#' . a:buffer . '...') instead. You might get a filename for the wrong buffer."
check_errors 'getcwd()' "Do not use getcwd(), as it could run from the wrong buffer. Use expand('#' . a:buffer . ':p:h') instead."
check_errors '==#' "Use 'is#' instead of '==#'. 0 ==# 'foobar' is true"
diff --git a/test/test_tmpdir_init.vader b/test/test_tmpdir_init.vader
deleted file mode 100644
index 23326dcc..00000000
--- a/test/test_tmpdir_init.vader
+++ /dev/null
@@ -1,4 +0,0 @@
-Execute($TMPDIR should be set to a default value if unset):
- if has('unix')
- AssertEqual '/tmp', $TMPDIR
- endif
diff --git a/test/test_tmpdir_wrapper.vader b/test/test_tmpdir_wrapper.vader
new file mode 100644
index 00000000..4d87061f
--- /dev/null
+++ b/test/test_tmpdir_wrapper.vader
@@ -0,0 +1,13 @@
+Before:
+ Save $TMPDIR
+
+After:
+ Restore
+
+Execute(ale#util#Tempname should create files in /tmp if $TMPDIR isn't set):
+ if has('unix')
+ let $TMPDIR = ''
+ Assert ale#util#Tempname() =~# '^/tmp'
+ " We should unlet the environment variable again.
+ AssertEqual '', $TMPDIR
+ endif
diff --git a/test/vimrc b/test/vimrc
index 970e20ee..9548f861 100644
--- a/test/vimrc
+++ b/test/vimrc
@@ -35,7 +35,3 @@ set ttimeoutlen=0
execute 'set encoding=utf-8'
let g:mapleader=','
-
-" Clear the TMPDIR value for tests.
-" The plugin should set this to /tmp by default, which we will test.
-let $TMPDIR = ''