Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for tsconfig.json files #1692

Merged
merged 14 commits into from Jan 21, 2015

Conversation

Projects
None yet
@ahejlsberg
Copy link
Member

commented Jan 16, 2015

This PR implements #1667 with some modifications.

The presence of a tsconfig.json file in a directory indicates that the directory is the root of a TypeScript project. The tsconfig.json file specifies the root files and the compiler options required to compile the project. A project is compiled in one of the following ways:

  • By invoking tsc with no input files, in which case the compiler searches for the tsconfig.json file starting in the current directory and continuing up the parent directory chain.
  • By invoking tsc with no input files and a -project (or just -p) command line option that specifies the path of a directory containing a tsconfig.json file.

When input files are specified on the command line, tsconfig.json files are ignored.

An example tsconfig.json file:

{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": true,
        "removeComments": true,
        "preserveConstEnums": true,
        "out": "../../built/local/tsc.js",
        "sourceMap": true,
    },
    "files": [
        "core.ts",
        "sys.ts",
        "types.ts",
        "scanner.ts",
        "parser.ts",
        "utilities.ts",
        "binder.ts",
        "checker.ts",
        "emitter.ts",
        "program.ts",
        "commandLineParser.ts",
        "tsc.ts",
        "diagnosticInformationMap.generated.ts"
    ]
}

The "compilerOptions" property can be omitted, in which case the compiler's defaults are used.

If no "files" property is present in a tsconfig.json, the compiler defaults to including all files the containing directory and subdirectories. When a "files" property is specified, only those files are included.

A tsconfig.json file is permitted to be completely empty, which compiles all files in the containing directory and subdirectories with the default compiler options.

Compiler options specified on the command line override those specified in the tsconfig.json file.

@basarat basarat referenced this pull request Jan 16, 2015

Merged

switch to TypeScript v1.4 #3466

@Arnavion

This comment has been minimized.

Copy link
Contributor

commented Jan 16, 2015

This allows watch as a compiler option in the file. Should it be ignored?

When input files are specified on the command line, tsconfig.json files are ignored.

Why is the entire file ignored instead of just the files section? It would be useful to partially compile a project by specifying individual files, but using the compiler options specified in the project file.

@ahejlsberg

This comment has been minimized.

Copy link
Member Author

commented Jan 16, 2015

@Arnavion I agree, we should probably disallow watch in tsconfig.json. Same for project which only makes sense on the command line.

Regarding your second question, I'd like to do what you suggest, but I wonder about this scenario: Say you have directories c:\src\foo and c:\src\bar, each containing a tsconfig.json, and that the current directory is c:\src\foo. Now if you say tsc c:\src\bar\somefile.ts we'd compile a file from the c:\src\bar project with the options of the c:\src\foo project. This may be just fine, but perhaps also confusing.

@DanielRosenwasser

This comment has been minimized.

Copy link
Member

commented on 65452aa Jan 16, 2015

This is pretty gross for the negated cases. I'd rather we just use a helper function.

@Arnavion

This comment has been minimized.

Copy link
Contributor

commented Jan 16, 2015

That makes sense. You could expect it to use the tsconfig.json based on the file being compiled (c:\src\bar\tsconfig.json), but then that won't work if you wanted to compile files from both directories with the same commandline. Compiling with the tsconfig.json based on the current directory would be deterministic but, as you said, not intuitive either.

One alternative is:

  • For each file, find the tsconfig.json relative to it (the same directory-tree-climbing algorithm as now).
  • If all files map to a single project file, use it.
  • Else print an error ("Multiple project files found. Please specify one with -p") and abort.

It'll probably be more common for all the individual files being compiled to be in the same project, so this approach would allow them to be compiled with that project file. On the other hand it's more complicated, and expensive if the files are in multiple directories.

Then again, this might not even be really necessary. The use case I was imagining was that someone makes a change to only a few files of a large project and wants to recompile those files, but perhaps they'd be okay with just compiling the whole project every time. Or they could use automation like tsc -watch, watchify, etc. to only compile the changed files.

I guess the current behavior is fine.

@NoelAbrahams

This comment has been minimized.

Copy link

commented Jan 16, 2015

@ahejlsberg

When a "files" property is specified, only those files are included.

I am thinking why would anyone want to have .ts files in a directory and not have them compiled?

Perhaps an "exclude": [ "foo/bar.ts" ] would make more sense?

@dbaeumer

This comment has been minimized.

Copy link
Member

commented Jan 16, 2015

+1 for the exclude behavior.

One question: can I combine regular command line options with the -p option E.g. tsc -p src -module "commonjs"

If you share code between the browser and nodejs and you need to compile the code once for commonjs and once for amd it would make sense to only maintain one tsconfig.json file.

@ahejlsberg

This comment has been minimized.

Copy link
Member Author

commented Jan 16, 2015

@NoelAbrahams I think there are two important scenarios: (1) Let me drop an empty tsconfig.json file in a directory and have everything in there be a project, and (2) let me describe the exact list of files I want included. The current design covers both with a minimum of complexity. That said, I can certainly see how an "exclude" list could be useful, although I suspect we'd then need globbing as well, so the level of complexity goes up. I definitely don't want this growing into an alternate build system. The intent is more to offer tools (e.g. editors) a simple and deterministic way to decide what the compilation context for a particular file is.

@dbaeumer Yes, you can combine other command line options with -p.

@mihailik

This comment has been minimized.

Copy link
Contributor

commented on src/compiler/commandLineParser.ts in f9f95ba Jan 16, 2015

Looks like when JSON config is used, any *.ts file sitting next to it is automatically included in the build.

Why is that? Handling of a config doesn't seem to be much related to a particular behaviour of scanning directories.

@fdecampredon

This comment has been minimized.

Copy link

commented Jan 17, 2015

I think there are two important scenarios: (1) Let me drop an empty tsconfig.json file in a directory and have everything in there be a project, and (2) let me describe the exact list of files I want included. The current design covers both with a minimum of complexity. That said, I can certainly see how an "exclude" list could be useful, although I suspect we'd then need globbing as well, so the level of complexity goes up. I definitely don't want this growing into an alternate build system. The intent is more to offer tools (e.g. editors) a simple and deterministic way to decide what the compilation context for a particular file is.

Honestly if your target is editor I would prefer that this feature never make it to master. If those configuration files are implemented, I will have to support them, if I want to offer more complex configuration mechanisms, I will have to support another config file and figure when a file configuration has precedence over another.
Build/project configuration has always be a topic where everyone make its own sauce, the amazing number of build/lint/configuration tools is a good example of that.
I don't clearly see the value of those tsconfig.json file over storing the command line in simple bash script, however I'm pretty much sure they will give me headache when I'll have to decide how I should integrate them.

@basarat

This comment has been minimized.

Copy link
Contributor

commented Jan 18, 2015

I agree with @fdecampredon that this PR might not be a good idea for IDE developers. Nevertheless

Perhaps an "exclude": [ "foo/bar.ts" ] would make more sense?

No. Better to have !foo/bar.ts included in files than to add another option to the root. If this PR does get merged I would as a second step recommend making files support the entire glob/minmatch/regexp syntax common in JavaScript build tools. Having a custom hacked exclude option would just be painful to allow that next step. You would pretty soon want to do exclude: node_modules/**/*.

@Arnavion

This comment has been minimized.

Copy link
Contributor

commented Jan 18, 2015

@basarat Anders mentioned that already:

That said, I can certainly see how an "exclude" list could be useful, although I suspect we'd then need globbing as well, so the level of complexity goes up.

The problem with supporting globbing is that it needs to be an own-implementation, since tsc can't rely on node modules. This is why the previous PR for wildcards was abandoned.

@basarat

This comment has been minimized.

Copy link
Contributor

commented Jan 18, 2015

@Arnavion sorry. Thanks!

@NoelAbrahams

This comment has been minimized.

Copy link

commented Jan 18, 2015

What's wrong with exclude: [ node_modules/**/*]? That's what people do already with .gitignore. I'm not suggesting that exclude be another option, rather it should be the only option. There's no real need for files. A directory already adequately describes that.

As I see it:

  • Use the file system to describe the project structure
  • Use .gitignore (or equivalent) to share that structure amongst your team
  • Use tsconfig.json to build the project structure
@ahejlsberg

This comment has been minimized.

Copy link
Member Author

commented Jan 18, 2015

@NoelAbrahams There are actually two very real needs for files:

  • It allows you to specify a file ordering, which matters in projects that use -out.
  • It allows you to reference files outside this directory tree. This is particularly important for referencing declarations files.

Yes, you can cover those with /// <reference /> but a lot of folks don't like putting those in their programs.

@NoelAbrahams

This comment has been minimized.

Copy link

commented Jan 18, 2015

@ahejlsberg, Ah! I failed to spot the potential for including references.

The only objection I have is to the following:

When a "files" property is specified, only those files are included.

In the project structure we have, all files are included in the compilation, including subdirectories.

But certainly, I would like to see ordering and referencing to be part of this.

@DanielRosenwasser

This comment has been minimized.

Copy link
Member

commented Jan 18, 2015

@ahejlsberg, this fails hard if you have a loop in your file system and "files" isn't specified.

compiler Daniel$ ln -s uhoh .
compiler Daniel$ node ../../built/local/tsc.js

fs.js:689
  return binding.stat(pathModule._makeLong(path));
                 ^
Error: ELOOP, too many symbolic links encountered 'uhoh'
    at Object.fs.statSync (fs.js:689:18)
    at visitDirectory (/Users/Daniel/TypeScript/built/local/tsc.js:1334:40)
    at Object.readDirectory (/Users/Daniel/TypeScript/built/local/tsc.js:1327:17)
    at getFiles (/Users/Daniel/TypeScript/built/local/tsc.js:20219:39)
    at Object.parseConfigFile (/Users/Daniel/TypeScript/built/local/tsc.js:20167:24)
    at Object.executeCommandLine (/Users/Daniel/TypeScript/built/local/tsc.js:20389:40)
    === Snip ===

This is mostly a problem if we let others consume this functionality.

@basarat basarat referenced this pull request Jan 18, 2015

Closed

tsconfig.json support #7

@NoelAbrahams

This comment has been minimized.

Copy link

commented Jan 19, 2015

Just to clarify my point above. We would like to make use of the external file reference and ordering feature introduced by files, but then we're also forced to include the files that need to be compiled, because one cannot have one without the other as it stands.

This introduces a maintenance problem: every time a new file is added or an existing file deleted tsconfig.json needs to be modified; and there is danger of files being inadvertently excluded from compilation.

If this change is accompanied by associated changes to the tooling (i.e. in Visual Studio for instance the "Add file" feature should automatically update tsconfig.json) then that should be fine.

@basarat

This comment has been minimized.

Copy link
Contributor

commented Jan 19, 2015

@NoelAbrahams perhaps solvable by a third party tool :

support a files-expansion:['!somefile','must/include/**/*.ts'] sort of transform inside tsconfig.json which will expand the files member.

@mihailik

This comment has been minimized.

Copy link
Contributor

commented on 45e700e Jan 21, 2015

Shouldn't --declaration option also be present in the services one?

@lcorneliussen

This comment has been minimized.

Copy link

commented Feb 2, 2015

Any information yet in which release this will be available? (incl. VS-support?)

@ahejlsberg

This comment has been minimized.

Copy link
Member Author

commented Feb 2, 2015

This will be in the 1.5 release. Not sure yet what level of VS support we'll have in that release.

@madskristensen

This comment has been minimized.

Copy link

commented Mar 25, 2015

I've added a JSON Schema for this format on http://json.schemastore.org/tsconfig

@basarat

This comment has been minimized.

@madskristensen

This comment has been minimized.

Copy link

commented Mar 25, 2015

@basarat Awesome. Thanks. Are you sure all those options are supported in tsconfig.json files too? Where's the official documentation for these options so I can get the proper description text?

@basarat

This comment has been minimized.

Copy link
Contributor

commented Mar 25, 2015

Are you sure all those options are supported in tsconfig.json files too

I assumed so. Considering they added watch to tsconfig.json as well #2222 (which I think might be a bad idea but nonetheless).

Pinging @mhegazy for an exact answer.

Where's the official documentation for these options so I can get the proper description text

Your best bet : for an up to date list: https://github.com/Microsoft/TypeScript/blob/master/src/compiler/commandLineParser.ts#L7-L175

@madskristensen

This comment has been minimized.

Copy link

commented Mar 25, 2015

Thanks for the link to the commandLineParser.ts for the definitions. I've updated the schema to reflect the entire list of options. http://json.schemastore.org/tsconfig

@mhegazy

This comment has been minimized.

Copy link

commented Mar 25, 2015

thanks @madskristensen, experimental switches are not guaranteed to work, and can be removed. so i would not add them to the schema.

@madskristensen

This comment has been minimized.

Copy link

commented Mar 25, 2015

Thanks, I've removed the experimental options

@Acaspita

This comment has been minimized.

Copy link

commented Apr 13, 2015

Is

files:['./someDirectory/'] ( == files:['someDirectory/'] )

equivalent to

files:['./someDirectory/**/*.ts']

?
If not so, could you add support for this? I wouldn't like compiler to waste time looking into /bower_components/ or /node_modules/ folders, meaning that I'd like to "easily" specify the folders to include in the project...

(* Function Definition *)
function Salute(): string;
var
   (* mmm... none... *)
begin
   writeln( 'Thank you :)');
end;
@basarat

This comment has been minimized.

Copy link
Contributor

commented Apr 13, 2015

equivalent to

No. It must point to a file. No gobbing support yet.

Requested here : #1927

@srackham

This comment has been minimized.

Copy link

commented May 5, 2015

Is there a reason that the --rootDir tsc command option is not included in the tsconfig.json schema? I'm using 1.5.0-beta.

@mhegazy

This comment has been minimized.

Copy link

commented May 5, 2015

@srackham we have not updated the schema yet.. will look into it. thanks for reporting this. filed #3046 to get it fixed.

@OleksandrChekhovskyi

This comment has been minimized.

Copy link

commented on 25e52a3 May 7, 2015

Why did this happen?
This change prevents sharing code using symlinks (for example, .d.ts files), which I think is a perfectly valid use case.

This comment has been minimized.

Copy link
Member Author

replied May 7, 2015

Symlink references can be circular so we'd need to keep track of how many we have traversed and stop at some limit. It would add some complexity, but it is certainly doable. A PR would be welcome if you're so inclined.

This comment has been minimized.

Copy link

replied May 7, 2015

Could you provide a motivational example of the case when this can happen? I don't quite see how recursive symlinks can emerge in a legitimate codebase, except by mistake.

It feels like that should just be an error. And it is by default, here is an example trace when trying to stat a circular symlink:

fs.js:797
  return binding.stat(pathModule._makeLong(path));
                 ^
Error: ELOOP, too many symbolic links encountered 'a'
    at Error (native)
    at Object.fs.statSync (fs.js:797:18)
    at Object.<anonymous> (~/temp/test.js:3:16)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3
@robertbaker

This comment has been minimized.

Copy link

commented Jun 9, 2015

I think it's a bit silly to disallow globs because a small percentage of use-cases would not work, when the majority of use-cases need it.

@httpete

This comment has been minimized.

Copy link

commented Jul 15, 2015

The use for filesGlob is so great - to do exclusions of the node_modules and other dirs, which cause tsc to choike. VSCode is crippled without this.

@mhegazy

This comment has been minimized.

Copy link

commented Jul 24, 2015

@matthew-dean

This comment has been minimized.

Copy link

commented Jul 30, 2015

sigh I wish that:

a) The web community would unify on adopting a .config directory in the root of a project to store this eve-expanding list of config files.
b) Config file definitions could be unified into a standard format. Why can't it just be config.json, with a definition specific for TypeScript, like package.json? And then Sass, Less, and others could all define their respective config.json settings (or alternatively, .config/config.json), that an IDE could import?

I think it's really unfortunate this idea was implemented in this way. 😢

@nojvek

This comment has been minimized.

Copy link
Contributor

commented Dec 10, 2015

Isn't that what the.{file} notation is for. Files that are hidden and special.What's wrong with having .gitignore, .vscode, .tsconfig. they all target different purposes.

@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.