{"action":"created","issue":{"url":"https://api.github.com/repos/google/closure-compiler/issues/3048","repository_url":"https://api.github.com/repos/google/closure-compiler","labels_url":"https://api.github.com/repos/google/closure-compiler/issues/3048/labels{/name}","comments_url":"https://api.github.com/repos/google/closure-compiler/issues/3048/comments","events_url":"https://api.github.com/repos/google/closure-compiler/issues/3048/events","html_url":"https://github.com/google/closure-compiler/issues/3048","id":348337138,"node_id":"MDU6SXNzdWUzNDgzMzcxMzg=","number":3048,"title":"Calling methods in externs upon wrong object should warn","user":{"login":"supersteves","id":10280734,"node_id":"MDQ6VXNlcjEwMjgwNzM0","avatar_url":"https://avatars2.githubusercontent.com/u/10280734?v=4","gravatar_id":"","url":"https://api.github.com/users/supersteves","html_url":"https://github.com/supersteves","followers_url":"https://api.github.com/users/supersteves/followers","following_url":"https://api.github.com/users/supersteves/following{/other_user}","gists_url":"https://api.github.com/users/supersteves/gists{/gist_id}","starred_url":"https://api.github.com/users/supersteves/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/supersteves/subscriptions","organizations_url":"https://api.github.com/users/supersteves/orgs","repos_url":"https://api.github.com/users/supersteves/repos","events_url":"https://api.github.com/users/supersteves/events{/privacy}","received_events_url":"https://api.github.com/users/supersteves/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2018-08-07T14:06:26Z","updated_at":"2018-09-24T19:15:11Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"I was calling a method which was missing from my externs, and was debugging why the compiler wasn't picking this up:\r\n\r\nExterns:\r\n``` javascript\r\nvar ExternsProblem = {};\r\n\r\n/** @constructor */\r\nvar SomethingElse = function() {};\r\n\r\nSomethingElse.prototype.something = function() {};\r\n```\r\nCode:\r\n``` javascript\r\nExternsProblem.something(); // should fail, doesn't\r\n```\r\n\r\nYou can see that `something` is defined elsewhere in the externs, but not here!\r\n\r\n[Debugger](https://closure-compiler-debugger.appspot.com/#input0%3D%250AExternsProblem.something()%253B%2520%252F%252F%2520should%2520fail%252C%2520doesn't%250A%250A%26input1%26conformanceConfig%26externs%3Dvar%2520ExternsProblem%2520%253D%2520%257B%257D%253B%250A%250A%252F**%2520%2540constructor%2520*%252F%250Avar%2520SomethingElse%2520%253D%2520function()%2520%257B%257D%253B%250A%250ASomethingElse.prototype.something%2520%253D%2520function()%2520%257B%257D%253B%250A%26refasterjs-template%26CHECK_TYPES%3Dtrue%26STRICT_CHECK_TYPES%3Dtrue%26CHECK_CONSTANTS%3Dtrue%26CHECK_DEPRECATED%3Dtrue%26CHECK_ES5_STRICT%3Dtrue%26CHECK_GLOBAL_NAMES%3Dtrue%26CHECK_GLOBAL_THIS%3Dtrue%26CHECK_LINT%3Dtrue%26CHECK_MISSING_RETURN%3Dtrue%26CHECK_UNREACHABLE_CODE%3Dtrue%26CHECK_PROVIDES%3Dtrue%26CHECK_REQUIRES%3Dtrue%26CHECK_REPORT_MISSING_OVERRIDE%3Dtrue%26CHECK_SUSPICIOUS_CODE%3Dtrue%26CHECK_SYMBOLS%3Dtrue%26CHECK_VISIBILITY%3Dtrue%26MISSING_PROPERTIES%3Dtrue%26TRANSPILE%3Dtrue%26CLOSURE_PASS%3Dtrue%26PRESERVE_TYPE_ANNOTATIONS%3Dtrue%26PRETTY_PRINT%3Dtrue)\r\n\r\n---\r\n\r\nTicking `ENABLE_ALL_DIAGNOSTIC_GROUPS` highlighted the problem: \r\n```\r\ninput0:2: WARNING - could not determine the type of this expression\r\nExternsProblem.something(); // should fail, doesn't\r\n^^^^^^^^^^^^^^\r\n```\r\n[Debugger](https://closure-compiler-debugger.appspot.com/#input0%3D%250AExternsProblem.something()%253B%2520%252F%252F%2520should%2520fail%252C%2520doesn't%250A%250A%26input1%26conformanceConfig%26externs%3Dvar%2520ExternsProblem%2520%253D%2520%257B%257D%253B%250A%250A%252F**%2520%2540constructor%2520*%252F%250Avar%2520SomethingElse%2520%253D%2520function()%2520%257B%257D%253B%250A%250ASomethingElse.prototype.something%2520%253D%2520function()%2520%257B%257D%253B%250A%26refasterjs-template%26ENABLE_ALL_DIAGNOSTIC_GROUPS%3Dtrue%26CHECK_TYPES%3Dtrue%26STRICT_CHECK_TYPES%3Dtrue%26CHECK_CONSTANTS%3Dtrue%26CHECK_DEPRECATED%3Dtrue%26CHECK_ES5_STRICT%3Dtrue%26CHECK_GLOBAL_NAMES%3Dtrue%26CHECK_GLOBAL_THIS%3Dtrue%26CHECK_LINT%3Dtrue%26CHECK_MISSING_RETURN%3Dtrue%26CHECK_UNREACHABLE_CODE%3Dtrue%26CHECK_PROVIDES%3Dtrue%26CHECK_REQUIRES%3Dtrue%26CHECK_REPORT_MISSING_OVERRIDE%3Dtrue%26CHECK_SUSPICIOUS_CODE%3Dtrue%26CHECK_SYMBOLS%3Dtrue%26CHECK_VISIBILITY%3Dtrue%26MISSING_PROPERTIES%3Dtrue%26TRANSPILE%3Dtrue%26CLOSURE_PASS%3Dtrue%26PRESERVE_TYPE_ANNOTATIONS%3Dtrue%26PRETTY_PRINT%3Dtrue)\r\n\r\nThis error is [`UNKNOWN_EXPR_TYPE`](https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/TypeCheck.java#L236) which has been disabled for 5 years.\r\n\r\n---\r\n\r\nThe solution turns out to be to add `@const` to the externs:\r\n\r\n``` javascript\r\n/** @const */\r\nvar ExternsProblem = {};\r\n...\r\n```\r\n\r\nAh. Now I see the warning I expected:\r\n```\r\ninput0:2: WARNING - Property something never defined on ExternsProblem\r\nExternsProblem.something(); // should fail, doesn't\r\n               ^^^^^^^^^\r\n```\r\n\r\n[Debugger](https://closure-compiler-debugger.appspot.com/#input0%3D%250AExternsProblem.something()%253B%2520%252F%252F%2520should%2520fail%252C%2520doesn't%250A%250A%26input1%26conformanceConfig%26externs%3D%252F**%2520%2540const%2520*%252F%250Avar%2520ExternsProblem%2520%253D%2520%257B%257D%253B%250A%250A%252F**%2520%2540constructor%2520*%252F%250Avar%2520SomethingElse%2520%253D%2520function()%2520%257B%257D%253B%250A%250ASomethingElse.prototype.something%2520%253D%2520function()%2520%257B%257D%253B%250A%26refasterjs-template%26CHECK_TYPES%3Dtrue%26STRICT_CHECK_TYPES%3Dtrue%26CHECK_CONSTANTS%3Dtrue%26CHECK_DEPRECATED%3Dtrue%26CHECK_ES5_STRICT%3Dtrue%26CHECK_GLOBAL_NAMES%3Dtrue%26CHECK_GLOBAL_THIS%3Dtrue%26CHECK_LINT%3Dtrue%26CHECK_MISSING_RETURN%3Dtrue%26CHECK_UNREACHABLE_CODE%3Dtrue%26CHECK_PROVIDES%3Dtrue%26CHECK_REQUIRES%3Dtrue%26CHECK_REPORT_MISSING_OVERRIDE%3Dtrue%26CHECK_SUSPICIOUS_CODE%3Dtrue%26CHECK_SYMBOLS%3Dtrue%26CHECK_VISIBILITY%3Dtrue%26MISSING_PROPERTIES%3Dtrue%26TRANSPILE%3Dtrue%26CLOSURE_PASS%3Dtrue%26PRESERVE_TYPE_ANNOTATIONS%3Dtrue%26PRETTY_PRINT%3Dtrue)\r\n\r\n---\r\n\r\nI gather that the compiler doesn't know the type of external global var `ExternsProblem` so never complains about any property access upon it. This makes sense.\r\n\r\nHowever we need a warning to prevent developers from calling functions that simply don't exist (typo) or aren't documented. \r\n\r\nI'm guessing `JSC_UNKNOWN_EXPR_TYPE` was disabled 5 years ago because it's old. Perhaps there's another check that should be kicking in here and isn't. I'm going to explore forcibly enabling this warning in all my externs, but would appreciate knowing how severe you think this issue is, and whether it affects other cases *outside* of externs.\r\n"},"comment":{"url":"https://api.github.com/repos/google/closure-compiler/issues/comments/424091918","html_url":"https://github.com/google/closure-compiler/issues/3048#issuecomment-424091918","issue_url":"https://api.github.com/repos/google/closure-compiler/issues/3048","id":424091918,"node_id":"MDEyOklzc3VlQ29tbWVudDQyNDA5MTkxOA==","user":{"login":"concavelenz","id":1245994,"node_id":"MDQ6VXNlcjEyNDU5OTQ=","avatar_url":"https://avatars1.githubusercontent.com/u/1245994?v=4","gravatar_id":"","url":"https://api.github.com/users/concavelenz","html_url":"https://github.com/concavelenz","followers_url":"https://api.github.com/users/concavelenz/followers","following_url":"https://api.github.com/users/concavelenz/following{/other_user}","gists_url":"https://api.github.com/users/concavelenz/gists{/gist_id}","starred_url":"https://api.github.com/users/concavelenz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/concavelenz/subscriptions","organizations_url":"https://api.github.com/users/concavelenz/orgs","repos_url":"https://api.github.com/users/concavelenz/repos","events_url":"https://api.github.com/users/concavelenz/events{/privacy}","received_events_url":"https://api.github.com/users/concavelenz/received_events","type":"User","site_admin":false},"created_at":"2018-09-24T19:15:11Z","updated_at":"2018-09-24T19:15:11Z","author_association":"CONTRIBUTOR","body":"It will certainly generate warning for values typed as \"Object\" but it understands literals:\r\n\r\nhttps://closure-compiler-debugger.appspot.com/#input0%3D%250Alet%2520a%2520%253D%2520%257B%257D%253B%250Aa.something%2520%253D%25201%253B%250Aa.somethingElse%2520%253D%25202%253B%250A%250Ause(a.something)%253B%250Ause(a.bsProp)%253B%250A%250A%250Alet%2520b%2520%253D%2520%257B%257D%253B%250Ab.bsProp%2520%253D%25202%253B%250A%250A%250A%252F**%2520%2540type%2520%257B!Object%257D%2520*%252F%2520var%2520x%2520%253D%2520fn()%253B%250Ause(x.something)%253B%250Ause(x.bsProp)%253B%250A%26input1%26conformanceConfig%26externs%3Dvar%2520fn%253B%26refasterjs-template%26includeDefaultExterns%3Dtrue%26CHECK_TYPES%3Dtrue%26STRICT_CHECK_TYPES%3Dtrue%26MISSING_PROPERTIES%3Dtrue%26TRANSPILE%3Dtrue%26CLOSURE_PASS%3Dtrue%26PRESERVE_TYPE_ANNOTATIONS%3Dtrue%26PRETTY_PRINT%3Dtrue"}}
{"actor":{"display_login":"concavelenz"}}